[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#222271: marked as done (apt-shell from apt-rpm ported)



Your message dated Wed, 13 Jan 2016 01:01:26 +0100
with message-id <20160113010023.GA5501@debian.org>
and subject line Re: Bug#222271: apt-shell from apt-rpm ported
has caused the Debian Bug report #222271,
regarding apt-shell from apt-rpm ported
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact owner@bugs.debian.org
immediately.)


-- 
222271: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=222271
Debian Bug Tracking System
Contact owner@bugs.debian.org with problems
--- Begin Message ---
Package: apt
Version: 0.5.14
Severity: wishlist
Tags: patch

You find attached a patch to add apt-shell from apt-rpm to debian apt. 
Apt-shell is a shell like interface for apt with readline support, 
statefull cache and other goodies. See:
https://distro.conectiva.com.br/pipermail/apt-rpm/2003-March/001412.html
for a summary of the features.

The patch is split into two parts: 
1. apt-shell-common.diff adds stuff to apt that apt-shell needs 
2. apt-shell-shell.diff is the shell interface itself

The patch is against apt-0.5.14 and work for me(tm). It looks like it
does not break other apps linked against libapt (but I tested only
synaptic). 

bye,
 Michael

-- Package-specific info:

-- (/etc/apt/preferences present, but not submitted) --


-- (/etc/apt/sources.list present, but not submitted) --


-- System Information:
Debian Release: testing/unstable
Architecture: i386
Kernel: Linux sam 2.4.22 #26 Wed Oct 8 11:38:11 CEST 2003 i686
Locale: LANG=C, LC_CTYPE=de_DE

Versions of packages apt depends on:
ii  libc6                        2.3.2.ds1-8 GNU C Library: Shared libraries an
ii  libgcc1                      1:3.3.2-4   GCC support library
ii  libreadline4                 4.3-8       GNU readline and history libraries
ii  libstdc++5                   1:3.3.2-4   The GNU Standard C++ Library v3

-- no debconf information

--- apt-0.5.14.orig/apt-pkg/contrib/configuration.cc
+++ apt-0.5.14/apt-pkg/contrib/configuration.cc
@@ -50,6 +50,35 @@
 {
 };
 
+// CNC:2003-02-23 - Copy constructor.
+Configuration::Configuration(Configuration &Conf) : ToFree(true)
+{
+   Root = new Item;
+   if (Conf.Root->Child)
+      CopyChildren(Conf.Root, Root);
+}
+
+void Configuration::CopyChildren(Item *From, Item *To)
+{
+   Item *Parent = To;
+   To->Child = new Item;
+   From = From->Child;
+   To = To->Child;
+   while (1) {
+      To->Parent = Parent;
+      To->Value = From->Value;
+      To->Tag = From->Tag;
+      if (From->Child)
+	 CopyChildren(From, To);
+      From = From->Next;
+      if (From) {
+	 To->Next = new Item;
+	 To = To->Next;
+      } else {
+	 break;
+      }
+   }
+}
 									/*}}}*/
 // Configuration::~Configuration - Destructor				/*{{{*/
 // ---------------------------------------------------------------------
@@ -276,7 +306,8 @@
       
       // bool
       case 'b': 
-      return FindB(key, Default) ? "true" : "false";
+      // CNC:2003-11-23
+      return FindB(key, StringToBool(Default)) ? "true" : "false";
       
       // int
       case 'i': 
@@ -714,7 +745,9 @@
       // Skip bad file names ala run-parts
       const char *C = Ent->d_name;
       for (; *C != 0; C++)
-	 if (isalpha(*C) == 0 && isdigit(*C) == 0 && *C != '_' && *C != '-')
+	 // CNC:2002-11-25
+	 if (isalpha(*C) == 0 && isdigit(*C) == 0
+	     && *C != '_' && *C != '-' && *C != '.')
 	    break;
       if (*C != 0)
 	 continue;
@@ -738,3 +771,5 @@
    return true;
 }
 									/*}}}*/
+
+// vim:sts=3:sw=3
--- apt-0.5.14.orig/apt-pkg/contrib/configuration.h
+++ apt-0.5.14/apt-pkg/contrib/configuration.h
@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: configuration.h,v 1.16 2002/11/11 06:55:50 doogie Exp $
+// $Id: configuration.h,v 1.2 2003/01/29 18:43:48 niemeyer Exp $
 /* ######################################################################
 
    Configuration Class
@@ -65,6 +65,9 @@
    {
       return ((Configuration *)this)->Lookup(Name,false);
    }  
+
+   // CNC:2003-02-23 - Helper for copy constructor.
+   void CopyChildren(Item *From, Item *To);
    
    public:
 
@@ -94,6 +97,9 @@
    inline void Dump() { Dump(std::clog); };
    void Dump(std::ostream& str);
 
+   // CNC:2003-02-23 - Copy constructor.
+   Configuration(Configuration &Conf);
+
    Configuration(const Item *Root);
    Configuration();
    ~Configuration();
--- apt-0.5.14.orig/apt-pkg/contrib/error.cc
+++ apt-0.5.14/apt-pkg/contrib/error.cc
@@ -235,3 +235,57 @@
    *End = Itm;
 }
 									/*}}}*/
+// CNC:2003-02-24 
+// GlobalError::*State() - Functions allowing a given error state to be /*}}}*/
+//                         saved and restored later on.
+// ---------------------------------------------------------------------
+/* */
+void GlobalError::PushState()
+{
+   State *New = new State;
+   New->List = List;
+   New->Next = Stack;
+   Stack = New;
+   List = 0;
+   PendingFlag = false;
+}
+
+bool GlobalError::PopState()
+{  
+   if (Stack == 0)
+      return false;
+   State *Top = Stack;
+   Item **End = &Top->List;
+   for (Item *I = Top->List; I != 0; I = I->Next)
+      End = &I->Next;
+   *End = List;
+   List = Top->List;
+   PendingFlag |= Top->PendingFlag;
+   Stack = Top->Next;
+   delete Top;
+   return true;
+}
+
+bool GlobalError::PopBackState()
+{
+   if (Stack == 0)
+      return false;
+   State *Bottom = Stack;
+   State *PreBottom = 0;
+   while (Bottom->Next != 0) {
+      PreBottom = Bottom;
+      Bottom = Bottom->Next;
+   }
+   Item **End = &Bottom->List;
+   for (Item *I = Bottom->List; I != 0; I = I->Next)
+      End = &I->Next;
+   *End = List;
+   List = Bottom->List;
+   PendingFlag |= Bottom->PendingFlag;
+   delete Bottom;
+   if (PreBottom != 0)
+      PreBottom->Next = 0;
+   else
+      Stack = 0;
+   return true;
+}
--- apt-0.5.14.orig/apt-pkg/contrib/error.h
+++ apt-0.5.14/apt-pkg/contrib/error.h
@@ -70,8 +70,24 @@
    bool PendingFlag;
    void Insert(Item *I);
    
+   // CNC:2003-02-24 - Introduced a stack of errors. This allows one to 
+   //                  delay error handling until a later time.
+   struct State
+   {
+       Item *List;
+       bool PendingFlag;
+       State *Next;
+   };
+   State *Stack;
+
    public:
 
+   // CNC:2003-02-24 - See above.
+   void PushState();
+   bool PopState();
+   bool PopBackState();
+
+
    // Call to generate an error from a library call.
    bool Errno(const char *Function,const char *Description,...) APT_MFORMAT2;
    bool WarningE(const char *Function,const char *Description,...) APT_MFORMAT2;
--- apt-0.5.14.orig/apt-pkg/pkgrecords.cc
+++ apt-0.5.14/apt-pkg/pkgrecords.cc
@@ -42,6 +42,11 @@
       if (Files[I->ID] == 0)
 	 return;
    }   
+   
+   // CNC:2002-11-28
+   // We store that to make sure that the destructor won't segfault,
+   // even if the Cache object was destructed before this instance.
+   PackageFileCount = Cache.HeaderP->PackageFileCount;
 }
 									/*}}}*/
 // Records::~pkgRecords - Destructor					/*{{{*/
@@ -49,7 +54,9 @@
 /* */
 pkgRecords::~pkgRecords()
 {
-   for (unsigned I = 0; I != Cache.HeaderP->PackageFileCount; I++)
+   // CNC:2002-11-28
+   // See comments above.
+   for (unsigned I = 0; I != PackageFileCount; I++)
       delete Files[I];
    delete [] Files;
 }
--- apt-0.5.14.orig/apt-pkg/depcache.cc
+++ apt-0.5.14/apt-pkg/depcache.cc
@@ -864,3 +864,77 @@
    return Dep.IsCritical();
 }
 									/*}}}*/
+// CNC:2003-02-24
+// pkgDepCache::State::* - Routines to work on the state of a DepCache. /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void pkgDepCache::State::Copy(pkgDepCache::State const &Other)
+{
+   memcpy(this, &Other, sizeof(*this));
+   int Size = Dep->Head().PackageCount;
+   int DepSize = Dep->Head().DependsCount;
+   PkgState = new StateCache[Size];
+   PkgIgnore = new bool[Size];
+   DepState = new unsigned char[DepSize];
+   memcpy(PkgState, Other.PkgState, Size*sizeof(*PkgState));
+   memcpy(PkgIgnore, Other.PkgIgnore, Size*sizeof(*PkgIgnore));
+   memcpy(DepState, Other.DepState, DepSize*sizeof(*DepState));
+}
+
+void pkgDepCache::State::Save(pkgDepCache *dep)
+{
+   Dep = dep;
+   delete[] PkgState;
+   delete[] DepState;
+   delete[] PkgIgnore;
+   int Size = Dep->Head().PackageCount;
+   int DepSize = Dep->Head().DependsCount;
+   PkgState = new StateCache[Size];
+   PkgIgnore = new bool[Size];
+   DepState = new unsigned char[DepSize];
+   memcpy(PkgState, Dep->PkgState, Size*sizeof(*PkgState));
+   memset(PkgIgnore, 0, Size*sizeof(*PkgIgnore));
+   memcpy(DepState, Dep->DepState, DepSize*sizeof(*DepState));
+   iUsrSize = Dep->iUsrSize;
+   iDownloadSize= Dep->iDownloadSize;
+   iInstCount = Dep->iInstCount;
+   iDelCount = Dep->iDelCount;
+   iKeepCount = Dep->iKeepCount;
+   iBrokenCount = Dep->iBrokenCount;
+   iBadCount = Dep->iBadCount;
+}
+
+void pkgDepCache::State::Restore()
+{
+   memcpy(Dep->PkgState, PkgState, Dep->Head().PackageCount*sizeof(*PkgState));
+   memcpy(Dep->DepState, DepState, Dep->Head().DependsCount*sizeof(*DepState));
+   Dep->iUsrSize = iUsrSize;
+   Dep->iDownloadSize= iDownloadSize;
+   Dep->iInstCount = iInstCount;
+   Dep->iDelCount = iDelCount;
+   Dep->iKeepCount = iKeepCount;
+   Dep->iBrokenCount = iBrokenCount;
+   Dep->iBadCount = iBadCount;
+}
+
+bool pkgDepCache::State::Changed()
+{
+   int Size = Dep->Head().PackageCount;
+   StateCache *NewPkgState = Dep->PkgState;
+   for (int i = 0; i != Size; i++) {
+      if (PkgIgnore[i] == false &&
+          ((PkgState[i].Status != NewPkgState[i].Status) ||
+          (PkgState[i].Mode != NewPkgState[i].Mode)))
+         return true;
+   }
+   return false;
+}
+
+void pkgDepCache::State::UnIgnoreAll()
+{
+   memset(PkgIgnore, 0, Dep->Head().PackageCount*sizeof(*PkgIgnore));
+}
+
+                                                                        /*}}}*/
+
+// vim:sts=3:sw=3
--- apt-0.5.14.orig/apt-pkg/depcache.h
+++ apt-0.5.14/apt-pkg/depcache.h
@@ -164,9 +164,14 @@
    
    public:
 
+   class State;
+   friend class State;
+
    // Legacy.. We look like a pkgCache
    inline operator pkgCache &() {return *Cache;};
    inline Header &Head() {return *Cache->HeaderP;};
+   bool RemoveDepends(); // CNC:2002-08-01
+
    inline PkgIterator PkgBegin() {return Cache->PkgBegin();};
    inline PkgIterator FindPkg(string const &Name) {return Cache->FindPkg(Name);};
 
@@ -208,4 +213,66 @@
    virtual ~pkgDepCache();
 };
 
+// CNC:2003-02-24 - Class to work on the state of a depcache.
+class pkgDepCache::State
+{
+   protected:
+
+   pkgDepCache *Dep;
+
+   StateCache *PkgState;
+   unsigned char *DepState;
+   double iUsrSize;
+   double iDownloadSize;
+   unsigned long iInstCount;
+   unsigned long iDelCount;
+   unsigned long iKeepCount;
+   unsigned long iBrokenCount;
+   unsigned long iBadCount;
+
+   bool *PkgIgnore;
+
+   public:
+
+   void Save(pkgDepCache *Dep);
+   void Restore();
+   bool Changed();
+
+   void Ignore(PkgIterator const &I) {PkgIgnore[I->ID] = true;};
+   void UnIgnore(PkgIterator const &I) {PkgIgnore[I->ID] = false;};
+   bool Ignored(PkgIterator const &I) {return PkgIgnore[I->ID];};
+   void UnIgnoreAll();
+
+   StateCache &operator [](pkgCache::PkgIterator const &I) {return PkgState[I->ID];};
+   // Size queries
+   inline double UsrSize() {return iUsrSize;};
+   inline double DebSize() {return iDownloadSize;};
+   inline unsigned long DelCount() {return iDelCount;};
+   inline unsigned long KeepCount() {return iKeepCount;};
+   inline unsigned long InstCount() {return iInstCount;};
+   inline unsigned long BrokenCount() {return iBrokenCount;};
+   inline unsigned long BadCount() {return iBadCount;};
+
+   void Copy(State const &Other);
+   void operator =(State const &Other)
+      {
+         delete[] PkgState;
+         delete[] DepState;
+         delete[] PkgIgnore;
+         Copy(Other);
+      };
+   State(const State &Other)
+      { Copy(Other); };
+   State(pkgDepCache *Dep=NULL)
+         : Dep(0), PkgState(0), DepState(0), PkgIgnore(0)
+      { if (Dep != NULL) Save(Dep); };
+   ~State()
+      {
+         delete[] PkgState;
+         delete[] DepState;
+         delete[] PkgIgnore;
+      };
+};
+
+
 #endif
--- apt-0.5.14.orig/apt-pkg/indexfile.h
+++ apt-0.5.14/apt-pkg/indexfile.h
@@ -66,6 +66,9 @@
    virtual string ArchiveURI(string /*File*/) const {return string();};
    virtual bool GetIndexes(pkgAcquire *Owner) const;
 
+   // CNC:2002-07-04
+   virtual bool GetReleases(pkgAcquire *Owner) const {return true;};
+
    // Interface for the record parsers
    virtual pkgSrcRecords::Parser *CreateSrcParser() const {return 0;};
    
--- apt-0.5.14.orig/apt-pkg/pkgrecords.h
+++ apt-0.5.14/apt-pkg/pkgrecords.h
@@ -33,7 +33,10 @@
    
    pkgCache &Cache;
    Parser **Files;
-      
+
+   // CNC:2002-11-28
+   int PackageFileCount;
+   
    public:
 
    // Lookup function
@@ -67,7 +70,10 @@
    
    // The record in binary form
    virtual void GetRec(const char *&Start,const char *&Stop) {Start = Stop = 0;};
-   
+
+   // CNC:2003-11-21
+   virtual bool HasFile(const char *File) {return false;};
+
    virtual ~Parser() {};
 };
 
--- apt-0.5.14.orig/apt-pkg/sourcelist.cc
+++ apt-0.5.14/apt-pkg/sourcelist.cc
@@ -20,6 +20,9 @@
 
 #include <apti18n.h>
 
+// CNC:2003-11-21
+#include <apt-pkg/pkgsystem.h>
+
 #include <fstream>
 									/*}}}*/
 
@@ -223,20 +226,47 @@
 {
    return ReadVendors() && Read(_config->FindFile("Dir::Etc::sourcelist"));
 }
+
+// CNC:2003-03-03 - Needed to preserve backwards compatibility.
+// SourceList::Reset - Clear the sourcelist contents                    /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void pkgSourceList::Reset()
+{
+   for (const_iterator I = SrcList.begin(); I != SrcList.end(); I++)
+      delete *I;
+   SrcList.erase(SrcList.begin(),SrcList.end());
+   // CNC:2003-11-21
+   // mvo: this is for the new "apt-get instal filename.rpm" stuff
+   //_system->AddSourceFiles(SrcList);
+}
 									/*}}}*/
+// CNC:2003-03-03 - Function moved to ReadAppend() and Reset().
 // SourceList::Read - Parse the sourcelist file				/*{{{*/
 // ---------------------------------------------------------------------
 /* */
 bool pkgSourceList::Read(string File)
 {
+   Reset();
+   return ReadAppend(File);
+}
+
+                                                                        /*}}}*/
+// SourceList::ReadAppend - Parse a sourcelist file                     /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool pkgSourceList::ReadAppend(string File)
+{
    // Open the stream for reading
    ifstream F(File.c_str(),ios::in /*| ios::nocreate*/);
    if (!F != 0)
       return _error->Errno("ifstream::ifstream",_("Opening %s"),File.c_str());
-   
+
+#if 0 // Now Reset() does this.
    for (const_iterator I = SrcList.begin(); I != SrcList.end(); I++)
       delete *I;
    SrcList.erase(SrcList.begin(),SrcList.end());
+#endif
    char Buffer[300];
 
    int CurLine = 0;
@@ -246,62 +276,66 @@
       CurLine++;
       _strtabexpand(Buffer,sizeof(Buffer));
       if (F.fail() && !F.eof())
-	 return _error->Error(_("Line %u too long in source list %s."),
-			      CurLine,File.c_str());
+         return _error->Error(_("Line %u too long in source list %s."),
+                              CurLine,File.c_str());
+
 
-      
       char *I;
-      for (I = Buffer; *I != 0 && *I != '#'; I++);
+      // CNC:2003-02-20 - Do not break if '#' is inside [].
+      for (I = Buffer; *I != 0 && *I != '#'; I++)
+         if (*I == '[')
+            for (I++; *I != 0 && *I != ']'; I++);
       *I = 0;
-      
       const char *C = _strstrip(Buffer);
-      
+
       // Comment or blank
       if (C[0] == '#' || C[0] == 0)
-	 continue;
-      	    
+         continue;
+
       // Grok it
       string LineType;
       if (ParseQuoteWord(C,LineType) == false)
-	 return _error->Error(_("Malformed line %u in source list %s (type)"),CurLine,File.c_str());
+         return _error->Error(_("Malformed line %u in source list %s (type)"),CurLine,File.c_str());
 
       Type *Parse = Type::GetType(LineType.c_str());
       if (Parse == 0)
-	 return _error->Error(_("Type '%s' is not known in on line %u in source list %s"),LineType.c_str(),CurLine,File.c_str());
-      
+         return _error->Error(_("Type '%s' is not known in on line %u in source list %s"),LineType.c_str(),CurLine,File.c_str());
+
       // Authenticated repository
       Vendor const *Vndr = 0;
       if (C[0] == '[')
       {
-	 string VendorID;
-	 
-	 if (ParseQuoteWord(C,VendorID) == false)
-	     return _error->Error(_("Malformed line %u in source list %s (vendor id)"),CurLine,File.c_str());
-
-	 if (VendorID.length() < 2 || VendorID.end()[-1] != ']')
-	     return _error->Error(_("Malformed line %u in source list %s (vendor id)"),CurLine,File.c_str());
-	 VendorID = string(VendorID,1,VendorID.size()-2);
-	 
-	 for (vector<Vendor const *>::const_iterator iter = VendorList.begin();
-	      iter != VendorList.end(); iter++) 
-	 {
-	    if ((*iter)->VendorID == VendorID)
-	    {
-	       Vndr = *iter;
-	       break;
-	    }
-	 }
-
-	 if (Vndr == 0)
-	    return _error->Error(_("Unknown vendor ID '%s' in line %u of source list %s"),
-				 VendorID.c_str(),CurLine,File.c_str());
+         string VendorID;
+
+         if (ParseQuoteWord(C,VendorID) == false)
+             return _error->Error(_("Malformed line %u in source list %s (vendor id)"),CurLine,File.c_str());
+
+         if (VendorID.length() < 2 || VendorID.end()[-1] != ']')
+             return _error->Error(_("Malformed line %u in source list %s (vendor id)"),CurLine,File.c_str());
+         VendorID = string(VendorID,1,VendorID.size()-2);
+
+         for (vector<Vendor const *>::const_iterator iter = VendorList.begin();
+              iter != VendorList.end(); iter++)
+         {
+            if ((*iter)->VendorID == VendorID)
+            {
+               Vndr = *iter;
+               break;
+            }
+         }
+
+         if (Vndr == 0)
+            return _error->Error(_("Unknown vendor ID '%s' in line %u of source list %s"),
+                                 VendorID.c_str(),CurLine,File.c_str());
       }
-      
+
       if (Parse->ParseLine(SrcList,Vndr,C,CurLine,File) == false)
-	 return false;
+         return false;
    }
    return true;
 }
+
+
 									/*}}}*/
 // SourceList::FindIndex - Get the index associated with a file		/*{{{*/
 // ---------------------------------------------------------------------
@@ -332,3 +366,14 @@
    return true;
 }
 									/*}}}*/
+// CNC:2002-07-04
+// SourceList::GetReleases - Load release files into the downloader     /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool pkgSourceList::GetReleases(pkgAcquire *Owner) const
+{
+   for (const_iterator I = SrcList.begin(); I != SrcList.end(); I++)
+      if ((*I)->GetReleases(Owner) == false)
+         return false;
+   return true;
+}
--- apt-0.5.14.orig/apt-pkg/sourcelist.h
+++ apt-0.5.14/apt-pkg/sourcelist.h
@@ -95,6 +95,12 @@
    bool Read(string File);
    bool ReadVendors();
    
+   // CNC:2003-03-03
+   void Reset();
+   bool ReadAppend(string File);
+   bool ReadSourceDir(string Dir);
+
+
    // List accessors
    inline const_iterator begin() const {return SrcList.begin();};
    inline const_iterator end() const {return SrcList.end();};
@@ -105,6 +111,9 @@
 		  pkgIndexFile *&Found) const;
    bool GetIndexes(pkgAcquire *Owner) const;
    
+   // CNC:2002-07-04
+   bool GetReleases(pkgAcquire *Owner) const;
+
    pkgSourceList();
    pkgSourceList(string File);
    ~pkgSourceList();      
--- apt-0.5.14.orig/apt-pkg/version.h
+++ apt-0.5.14/apt-pkg/version.h
@@ -27,6 +27,9 @@
 #include <apt-pkg/strutl.h>    
 #include <string>
 
+// CNC:2002-07-10
+#include <apt-pkg/pkgcache.h>
+
 using std::string;
 
 class pkgVersioningSystem
@@ -42,7 +45,9 @@
    // Compare versions..
    virtual int DoCmpVersion(const char *A,const char *Aend,
 			  const char *B,const char *Bend) = 0;   
-
+ 
+   virtual bool CheckDep(const char *PkgVer,pkgCache::DepIterator Dep)
+       {return CheckDep(PkgVer,Dep->CompareOp,Dep.TargetVer());};
    virtual bool CheckDep(const char *PkgVer,int Op,const char *DepVer) = 0;
    virtual int DoCmpReleaseVer(const char *A,const char *Aend,
 			       const char *B,const char *Bend) = 0;
--- apt-0.5.14.orig/apt-pkg/versionmatch.cc
+++ apt-0.5.14/apt-pkg/versionmatch.cc
@@ -26,7 +26,9 @@
 // VersionMatch::pkgVersionMatch - Constructor				/*{{{*/
 // ---------------------------------------------------------------------
 /* Break up the data string according to the selected type */
-pkgVersionMatch::pkgVersionMatch(string Data,MatchType Type) : Type(Type)
+// CNC:2003-11-05
+// mvo: prepeare for enhanced searching as found in apt-rpm
+pkgVersionMatch::pkgVersionMatch(string Data,MatchType Type,int Op) : VerOp(Op), Type(Type)
 {
    MatchAll = false;
    VerPrefixMatch = false;
@@ -143,6 +145,8 @@
 /* */
 pkgCache::VerIterator pkgVersionMatch::Find(pkgCache::PkgIterator Pkg)
 {
+   // CNC:2003-11-05
+   pkgVersioningSystem *VS = Pkg.Cache()->VS;
    pkgCache::VerIterator Ver = Pkg.VersionList();
    for (; Ver.end() == false; Ver++)
    {
--- apt-0.5.14.orig/apt-pkg/versionmatch.h
+++ apt-0.5.14/apt-pkg/versionmatch.h
@@ -45,6 +45,8 @@
    // Version Matching
    string VerStr;
    bool VerPrefixMatch;
+   // CNC:2003-11-05
+   int VerOp;
 
    // Release Matching
    string RelVerStr;
@@ -66,7 +68,8 @@
    bool FileMatch(pkgCache::PkgFileIterator File);
    pkgCache::VerIterator Find(pkgCache::PkgIterator Pkg);
 			       
-   pkgVersionMatch(string Data,MatchType Type);
+   // CNC:2003-11-05
+   pkgVersionMatch(string Data,MatchType Type,int Op=pkgCache::Dep::Equals);
 };
 
 #endif
--- apt-0.5.14.orig/cmdline/makefile
+++ apt-0.5.14/cmdline/makefile
@@ -19,6 +19,13 @@
 SOURCE = apt-get.cc acqprogress.cc
 include $(PROGRAM_H)
 
+# The apt-shell program
+PROGRAM=apt-shell
+SLIBS = -lapt-pkg -lreadline
+LIB_MAKES = apt-pkg/makefile
+SOURCE = apt-shell.cc acqprogress.cc 
+include $(PROGRAM_H)
+
 # The apt-config program
 PROGRAM=apt-config
 SLIBS = -lapt-pkg
--- apt-0.5.14.orig/cmdline/apt-shell.cc
+++ apt-0.5.14/cmdline/apt-shell.cc
@@ -0,0 +1,4480 @@
+// -*- mode: cpp; mode: fold -*-
+// Description								/*{{{*/
+// $Id: apt-get.cc,v 1.126 2003/02/12 16:14:08 doogie Exp $
+/* ######################################################################
+   
+   apt-get - Cover for dpkg
+   
+   This is an allout cover for dpkg implementing a safer front end. It is
+   based largely on libapt-pkg.
+
+   The syntax is different, 
+      apt-get [opt] command [things]
+   Where command is:
+      update - Resyncronize the package files from their sources
+      upgrade - Smart-Download the newest versions of all packages
+      dselect-upgrade - Follows dselect's changes to the Status: field
+                       and installes new and removes old packages
+      dist-upgrade - Powerfull upgrader designed to handle the issues with
+                    a new distribution.
+      install - Download and install a given package (by name, not by .deb)
+      check - Update the package cache and check for broken packages
+      clean - Erase the .debs downloaded to /var/cache/apt/archives and
+              the partial dir too
+
+   ##################################################################### */
+									/*}}}*/
+// Include Files							/*{{{*/
+#include <apt-pkg/error.h>
+#include <apt-pkg/cmndline.h>
+#include <apt-pkg/init.h>
+#include <apt-pkg/depcache.h>
+#include <apt-pkg/pkgcache.h>
+#include <apt-pkg/sourcelist.h>
+#include <apt-pkg/algorithms.h>
+#include <apt-pkg/acquire-item.h>
+#include <apt-pkg/strutl.h>
+#include <apt-pkg/clean.h>
+#include <apt-pkg/srcrecords.h>
+#include <apt-pkg/version.h>
+#include <apt-pkg/cachefile.h>
+#include <apt-pkg/sptr.h>
+#include <apt-pkg/versionmatch.h>
+
+#include <config.h>
+#include <apti18n.h>
+
+// CNC:2003-03-17
+//#include <apt-pkg/luaiface.h>
+    
+#include "acqprogress.h"
+
+// CNC:2003-02-14 - apti18n.h includes libintl.h which includes locale.h,
+// 		    as reported by Radu Greab.
+//#include <locale.h>
+#include <langinfo.h>
+#include <fstream>
+#include <termios.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/statvfs.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <regex.h>
+#include <sys/wait.h>
+
+#include <readline/readline.h>
+#include <readline/history.h>
+#include <fnmatch.h>
+									/*}}}*/
+
+using namespace std;
+
+ostream c0out(0);
+ostream c1out(0);
+ostream c2out(0);
+ofstream devnull("/dev/null");
+unsigned int ScreenWidth = 80;
+
+// class CacheFile - Cover class for some dependency cache functions	/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+class CacheFile : public pkgCacheFile
+{
+   static pkgCache *SortCache;
+   static int NameComp(const void *a,const void *b);
+   bool IsRoot;
+   
+   public:
+   pkgCache::Package **List;
+   
+   void Sort();
+   bool CheckDeps(bool AllowBroken = false);
+   bool BuildCaches()
+   {
+      OpTextProgress Prog(*_config);
+      if (pkgCacheFile::BuildCaches(Prog,IsRoot) == false)
+	 return false;
+      return true;
+   }
+   bool Open() 
+   {
+      OpTextProgress Prog(*_config);
+      if (pkgCacheFile::Open(Prog,IsRoot) == false)
+	 return false;
+      Sort();
+      return true;
+   };
+   bool CanCommit()
+   {
+      return IsRoot;
+   }
+   CacheFile() : List(0)
+   {
+      IsRoot = (getuid() == 0);
+   };
+};
+									/*}}}*/
+
+static CacheFile *GCache = NULL;
+
+class AutoRestore
+{
+   pkgDepCache::State State;
+   bool Guarded;
+   public:
+   inline pkgDepCache::State *operator ->() {return &State;};
+   inline pkgDepCache::State *operator &() {return &State;};
+   inline void UnGuard() { Guarded = false; };
+   AutoRestore(pkgDepCache &Cache)
+      : State(&Cache), Guarded(true) {};
+   ~AutoRestore() { if (Guarded) State.Restore(); };
+};
+
+class AutoReOpenCache
+{
+   CacheFile **Cache;
+   bool Guarded;
+   public:
+   inline void UnGuard() { Guarded = false; };
+   AutoReOpenCache(CacheFile *&Cache)
+      : Cache(&Cache), Guarded(true) {};
+   ~AutoReOpenCache()
+   {
+      if (Guarded) {
+	 delete *Cache;
+	 *Cache = new CacheFile;
+	 (*Cache)->Open();
+	 if ((*Cache)->CheckDeps(true) == false) {
+	    c1out << _("There are broken packages. ")
+		  << _("Run `check' to see them.") << endl;
+	    c1out << _("You can try to fix them automatically with `install -f'.") << endl;
+	 }
+      }
+   };
+};
+
+void CommandHelp(const char *Name);
+bool CheckHelp(CommandLine &CmdL, unsigned int MaxArgs=512)
+{
+   if (CmdL.FileSize()-1 > MaxArgs) {
+      _error->Error(_("Excessive arguments"));
+      return true;
+   }
+   if (_config->FindB("help") == true) {
+      CommandHelp(CmdL.FileList[0]);
+      return true;
+   }
+   return false;
+}
+
+// YnPrompt - Yes No Prompt.						/*{{{*/
+// ---------------------------------------------------------------------
+/* Returns true on a Yes.*/
+bool YnPrompt()
+{
+   if (_config->FindB("APT::Get::Assume-Yes",false) == true)
+   {
+      c1out << _("Y") << endl;
+      return true;
+   }
+
+   char response[1024] = "";
+   cin.getline(response, sizeof(response));
+
+   if (!cin)
+      return false;
+
+   if (strlen(response) == 0)
+      return true;
+
+   regex_t Pattern;
+   int Res;
+
+   Res = regcomp(&Pattern, nl_langinfo(YESEXPR),
+                 REG_EXTENDED|REG_ICASE|REG_NOSUB);
+
+   if (Res != 0) {
+      char Error[300];        
+      regerror(Res,&Pattern,Error,sizeof(Error));
+      return _error->Error(_("Regex compilation error - %s"),Error);
+   }
+   
+   Res = regexec(&Pattern, response, 0, NULL, 0);
+   if (Res == 0)
+      return true;
+   return false;
+}
+									/*}}}*/
+// AnalPrompt - Annoying Yes No Prompt.					/*{{{*/
+// ---------------------------------------------------------------------
+/* Returns true on a Yes.*/
+bool AnalPrompt(const char *Text)
+{
+   char Buf[1024];
+   cin.getline(Buf,sizeof(Buf));
+   if (strcmp(Buf,Text) == 0)
+      return true;
+   return false;
+}
+									/*}}}*/
+// ShowList - Show a list						/*{{{*/
+// ---------------------------------------------------------------------
+/* This prints out a string of space separated words with a title and 
+   a two space indent line wraped to the current screen width. */
+bool ShowList(ostream &out,string Title,string List,string VersionsList)
+{
+   if (List.empty() == true)
+      return true;
+   // trim trailing space
+   int NonSpace = List.find_last_not_of(' ');
+   if (NonSpace != -1)
+   {
+      List = List.erase(NonSpace + 1);
+      if (List.empty() == true)
+	 return true;
+   }
+
+   // Acount for the leading space
+   int ScreenWidth = ::ScreenWidth - 3;
+      
+   out << Title << endl;
+   string::size_type Start = 0;
+   string::size_type VersionsStart = 0;
+   while (Start < List.size())
+   {
+      if(_config->FindB("APT::Get::Show-Versions",false) == true &&
+         VersionsList.size() > 0) {
+         string::size_type End;
+         string::size_type VersionsEnd;
+         
+         End = List.find(' ',Start);
+         VersionsEnd = VersionsList.find('\n', VersionsStart);
+
+         out << "   " << string(List,Start,End - Start) << " (" << 
+            string(VersionsList,VersionsStart,VersionsEnd - VersionsStart) << 
+            ")" << endl;
+
+	 if (End == string::npos || End < Start)
+	    End = Start + ScreenWidth;
+
+         Start = End + 1;
+         VersionsStart = VersionsEnd + 1;
+      } else {
+         string::size_type End;
+
+         if (Start + ScreenWidth >= List.size())
+            End = List.size();
+         else
+            End = List.rfind(' ',Start+ScreenWidth);
+
+         if (End == string::npos || End < Start)
+            End = Start + ScreenWidth;
+         out << "  " << string(List,Start,End - Start) << endl;
+         Start = End + 1;
+      }
+   }   
+
+   return false;
+}
+									/*}}}*/
+// ShowBroken - Debugging aide						/*{{{*/
+// ---------------------------------------------------------------------
+/* This prints out the names of all the packages that are broken along
+   with the name of each each broken dependency and a quite version 
+   description.
+   
+   The output looks like:
+ The following packages have unmet dependencies:
+     exim: Depends: libc6 (>= 2.1.94) but 2.1.3-10 is to be installed
+           Depends: libldap2 (>= 2.0.2-2) but it is not going to be installed
+           Depends: libsasl7 but it is not going to be installed   
+ */
+void ShowBroken(ostream &out,CacheFile &Cache,bool Now,pkgDepCache::State *State=NULL)
+{
+   out << _("The following packages have unmet dependencies:") << endl;
+   for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
+   {
+      pkgCache::PkgIterator I(Cache,Cache.List[J]);
+      
+      if (Now == true)
+      {
+	 if (Cache[I].NowBroken() == false)
+	    continue;
+      }
+      else
+      {
+	 if (Cache[I].InstBroken() == false)
+	    continue;
+      }
+      
+      // Print out each package and the failed dependencies
+      out <<"  " <<  I.Name() << ":";
+      unsigned Indent = strlen(I.Name()) + 3;
+      bool First = true;
+      pkgCache::VerIterator Ver;
+      
+      if (Now == true)
+	 Ver = I.CurrentVer();
+      else
+	 Ver = Cache[I].InstVerIter(Cache);
+      
+      if (Ver.end() == true)
+      {
+	 out << endl;
+	 continue;
+      }
+      
+      for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false;)
+      {
+	 // Compute a single dependency element (glob or)
+	 pkgCache::DepIterator Start;
+	 pkgCache::DepIterator End;
+	 D.GlobOr(Start,End);
+
+         // CNC:2003-02-22 - IsImportantDep() currently calls IsCritical(), so
+         //		     these two are currently doing the same thing. Check
+         //		     comments in IsImportantDep() definition.
+#if 0
+	 if (Cache->IsImportantDep(End) == false)
+	    continue;
+#else
+	 if (End.IsCritical() == false)
+	    continue;
+#endif
+	 
+	 if (Now == true)
+	 {
+	    if ((Cache[End] & pkgDepCache::DepGNow) == pkgDepCache::DepGNow)
+	       continue;
+	 }
+	 else
+	 {
+	    if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
+	       continue;
+	 }
+	 
+	 bool FirstOr = true;
+	 while (1)
+	 {
+	    if (First == false)
+	       for (unsigned J = 0; J != Indent; J++)
+		  out << ' ';
+	    First = false;
+
+	    if (FirstOr == false)
+	    {
+	       for (unsigned J = 0; J != strlen(End.DepType()) + 3; J++)
+		  out << ' ';
+	    }
+	    else
+	       out << ' ' << End.DepType() << ": ";
+	    FirstOr = false;
+	    
+	    out << Start.TargetPkg().Name();
+	 
+	    // Show a quick summary of the version requirements
+	    if (Start.TargetVer() != 0)
+	       out << " (" << Start.CompType() << " " << Start.TargetVer() << ")";
+	    
+	    /* Show a summary of the target package if possible. In the case
+	       of virtual packages we show nothing */	 
+	    pkgCache::PkgIterator Targ = Start.TargetPkg();
+	    if (Targ->ProvidesList == 0)
+	    {
+	       out << ' ';
+	       pkgCache::VerIterator Ver = Cache[Targ].InstVerIter(Cache);
+	       if (Now == true)
+		  Ver = Targ.CurrentVer();
+	       	    
+	       if (Ver.end() == false)
+	       {
+		  if (Now == true)
+		     ioprintf(out,_("but %s is installed"),Ver.VerStr());
+		  else
+		     ioprintf(out,_("but %s is to be installed"),Ver.VerStr());
+	       }	       
+	       else
+	       {
+		  if (Cache[Targ].CandidateVerIter(Cache).end() == true)
+		  {
+		     if (Targ->ProvidesList == 0)
+			out << _("but it is not installable");
+		     else
+			out << _("but it is a virtual package");
+		  }		  
+		  else
+		     out << (Now?_("but it is not installed"):_("but it is not going to be installed"));
+	       }	       
+	    }
+	    
+	    if (Start != End)
+	       out << _(" or");
+	    out << endl;
+	    
+	    if (Start == End)
+	       break;
+	    Start++;
+	 }	 
+      }	    
+   }   
+}
+									/*}}}*/
+// ShowNew - Show packages to newly install				/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void ShowNew(ostream &out,CacheFile &Cache,pkgDepCache::State *State=NULL)
+{
+   /* Print out a list of packages that are going to be installed extra
+      to what the user asked */
+   string List;
+   string VersionsList;
+   for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
+   {
+      pkgCache::PkgIterator I(Cache,Cache.List[J]);
+      if (Cache[I].NewInstall() == true &&
+	  (State == NULL || (*State)[I].NewInstall() == false)) {
+	 List += string(I.Name()) + " ";
+         VersionsList += string(Cache[I].CandVersion) + "\n";
+      }
+   }
+   
+   ShowList(out,_("The following NEW packages will be installed:"),List,VersionsList);
+}
+									/*}}}*/
+// ShowDel - Show packages to delete					/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void ShowDel(ostream &out,CacheFile &Cache,pkgDepCache::State *State=NULL)
+{
+   /* Print out a list of packages that are going to be removed extra
+      to what the user asked */
+   string List, RepList; // CNC:2002-07-25
+   string VersionsList;
+   for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
+   {
+      pkgCache::PkgIterator I(Cache,Cache.List[J]);
+      if (Cache[I].Delete() == true &&
+	  (State == NULL || (*State)[I].Delete() == false))
+      {
+	 // CNC:2002-07-25
+	 bool Obsoleted = false;
+	 string by;
+	 for (pkgCache::DepIterator D = I.RevDependsList(); D.end() == false; D++)
+	 {
+	    if (D->Type == pkgCache::Dep::Obsoletes &&
+	        Cache[D.ParentPkg()].Install() &&
+	        (pkgCache::Version*)D.ParentVer() == Cache[D.ParentPkg()].InstallVer &&
+	        Cache->VS().CheckDep(I.CurrentVer().VerStr(), D) == true)
+	    {
+	       if (Obsoleted)
+		  by += ", " + string(D.ParentPkg().Name());
+	       else
+	       {
+		  Obsoleted = true;
+		  by = D.ParentPkg().Name();
+	       }
+	    }
+	 }
+	 if (Obsoleted)
+	    RepList += string(I.Name()) + " (by " + by + ")  ";
+	 else
+	 {
+	    if ((Cache[I].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge)
+	       List += string(I.Name()) + "* ";
+	    else
+	       List += string(I.Name()) + " ";
+	 }
+     
+     VersionsList += string(Cache[I].CandVersion)+ "\n";
+      }
+   }
+   
+   // CNC:2002-07-25
+   ShowList(out,_("The following packages will be REPLACED:"),RepList,VersionsList);
+   ShowList(out,_("The following packages will be REMOVED:"),List,VersionsList);
+}
+									/*}}}*/
+// ShowKept - Show kept packages					/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void ShowKept(ostream &out,CacheFile &Cache,pkgDepCache::State *State=NULL)
+{
+   string List;
+   string VersionsList;
+   for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
+   {	 
+      pkgCache::PkgIterator I(Cache,Cache.List[J]);
+      
+      if (State == NULL) {
+	 // Not interesting
+	 if (Cache[I].Upgrade() == true || Cache[I].Upgradable() == false ||
+	     I->CurrentVer == 0 || Cache[I].Delete() == true)
+	    continue;
+      } else {
+	 // Not interesting
+	 if (!((Cache[I].Install() == false && (*State)[I].Install() == true) ||
+	       (Cache[I].Delete() == false && (*State)[I].Delete() == true)))
+	    continue;
+      }
+      
+      List += string(I.Name()) + " ";
+      VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
+   }
+   ShowList(out,_("The following packages have been kept back"),List,VersionsList);
+}
+									/*}}}*/
+// ShowUpgraded - Show upgraded packages				/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void ShowUpgraded(ostream &out,CacheFile &Cache,pkgDepCache::State *State=NULL)
+{
+   string List;
+   string VersionsList;
+   for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
+   {
+      pkgCache::PkgIterator I(Cache,Cache.List[J]);
+      
+      if (State == NULL) {
+	 // Not interesting
+	 if (Cache[I].Upgrade() == false || Cache[I].NewInstall() == true)
+	    continue;
+      } else {
+	 // Not interesting
+	 if (Cache[I].NewInstall() == true ||
+	     !(Cache[I].Upgrade() == true && (*State)[I].Upgrade() == false))
+	    continue;
+      }
+      
+      List += string(I.Name()) + " ";
+      VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
+   }
+   ShowList(out,_("The following packages will be upgraded"),List,VersionsList);
+}
+									/*}}}*/
+// ShowDowngraded - Show downgraded packages				/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool ShowDowngraded(ostream &out,CacheFile &Cache,pkgDepCache::State *State=NULL)
+{
+   string List;
+   string VersionsList;
+   for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
+   {
+      pkgCache::PkgIterator I(Cache,Cache.List[J]);
+      
+      if (State == NULL) {
+	 // Not interesting
+	 if (Cache[I].Downgrade() == false || Cache[I].NewInstall() == true)
+	    continue;
+      } else {
+	 // Not interesting
+	 if (Cache[I].NewInstall() == true ||
+	     !(Cache[I].Downgrade() == true && (*State)[I].Downgrade() == false))
+	    continue;
+      }
+      
+      List += string(I.Name()) + " ";
+      VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
+   }
+   return ShowList(out,_("The following packages will be DOWNGRADED"),List,VersionsList);
+}
+									/*}}}*/
+// ShowHold - Show held but changed packages				/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool ShowHold(ostream &out,CacheFile &Cache,pkgDepCache::State *State=NULL)
+{
+   string List;
+   string VersionsList;
+   for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
+   {
+      pkgCache::PkgIterator I(Cache,Cache.List[J]);
+      if (Cache[I].InstallVer != (pkgCache::Version *)I.CurrentVer() &&
+	  I->SelectedState == pkgCache::State::Hold &&
+	  (State == NULL ||
+	   Cache[I].InstallVer != (*State)[I].InstallVer)) {
+	 List += string(I.Name()) + " ";
+	 VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
+      }
+   }
+
+   return ShowList(out,_("The following held packages will be changed:"),List,VersionsList);
+}
+									/*}}}*/
+// ShowEssential - Show an essential package warning			/*{{{*/
+// ---------------------------------------------------------------------
+/* This prints out a warning message that is not to be ignored. It shows
+   all essential packages and their dependents that are to be removed. 
+   It is insanely risky to remove the dependents of an essential package! */
+bool ShowEssential(ostream &out,CacheFile &Cache,pkgDepCache::State *State=NULL)
+{
+   string List;
+   string VersionsList;
+   bool *Added = new bool[Cache->Head().PackageCount];
+   for (unsigned int I = 0; I != Cache->Head().PackageCount; I++)
+      Added[I] = false;
+   
+   for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
+   {
+      pkgCache::PkgIterator I(Cache,Cache.List[J]);
+      if ((I->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential &&
+	  (I->Flags & pkgCache::Flag::Important) != pkgCache::Flag::Important)
+	 continue;
+      
+      // The essential package is being removed
+      if (Cache[I].Delete() == true &&
+	  (State == NULL || (*State)[I].Delete() == false))
+      {
+	 if (Added[I->ID] == false)
+	 {
+	    // CNC:2003-03-21 - Do not consider a problem if that package is being obsoleted
+	    //                  by something else.
+	    bool Obsoleted = false;
+	    for (pkgCache::DepIterator D = I.RevDependsList(); D.end() == false; D++)
+	    {
+	       if (D->Type == pkgCache::Dep::Obsoletes &&
+		   Cache[D.ParentPkg()].Install() &&
+		   ((pkgCache::Version*)D.ParentVer() == Cache[D.ParentPkg()].InstallVer ||
+		    (pkgCache::Version*)D.ParentVer() == ((pkgCache::Version*)D.ParentPkg().CurrentVer())) &&
+		   Cache->VS().CheckDep(I.CurrentVer().VerStr(), D) == true)
+	       {
+		  Obsoleted = true;
+		  break;
+	       }
+	    }
+	    if (Obsoleted == false) {
+	       Added[I->ID] = true;
+	       List += string(I.Name()) + " ";
+	    }
+        //VersionsList += string(Cache[I].CurVersion) + "\n"; ???
+	 }
+      }
+      
+      if (I->CurrentVer == 0)
+	 continue;
+
+      // Print out any essential package depenendents that are to be removed
+      for (pkgCache::DepIterator D = I.CurrentVer().DependsList(); D.end() == false; D++)
+      {
+	 // Skip everything but depends
+	 if (D->Type != pkgCache::Dep::PreDepends &&
+	     D->Type != pkgCache::Dep::Depends)
+	    continue;
+	 
+	 pkgCache::PkgIterator P = D.SmartTargetPkg();
+	 if (Cache[P].Delete() == true &&
+	     (State == NULL || (*State)[P].Delete() == false))
+	 {
+	    if (Added[P->ID] == true)
+	       continue;
+
+	    // CNC:2003-03-21 - Do not consider a problem if that package is being obsoleted
+	    //                  by something else.
+	    bool Obsoleted = false;
+	    for (pkgCache::DepIterator D = P.RevDependsList(); D.end() == false; D++)
+	    {
+	       if (D->Type == pkgCache::Dep::Obsoletes &&
+		   Cache[D.ParentPkg()].Install() &&
+		   ((pkgCache::Version*)D.ParentVer() == Cache[D.ParentPkg()].InstallVer ||
+		    (pkgCache::Version*)D.ParentVer() == ((pkgCache::Version*)D.ParentPkg().CurrentVer())) &&
+		   Cache->VS().CheckDep(P.CurrentVer().VerStr(), D) == true)
+	       {
+		  Obsoleted = true;
+		  break;
+	       }
+	    }
+	    if (Obsoleted == true)
+	       continue;
+
+	    Added[P->ID] = true;
+	    
+	    char S[300];
+	    snprintf(S,sizeof(S),_("%s (due to %s) "),P.Name(),I.Name());
+	    List += S;
+        //VersionsList += "\n"; ???
+	 }	 
+      }      
+   }
+   
+   delete [] Added;
+   return ShowList(out,_("WARNING: The following essential packages will be removed\n"
+			 "This should NOT be done unless you know exactly what you are doing!"),List,VersionsList);
+}
+									/*}}}*/
+// Stats - Show some statistics						/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void Stats(ostream &out,pkgDepCache &Dep,pkgDepCache::State *State=NULL)
+{
+   unsigned long Upgrade = 0;
+   unsigned long Downgrade = 0;
+   unsigned long Install = 0;
+   unsigned long ReInstall = 0;
+   // CNC:2002-07-29
+   unsigned long Replace = 0;
+   unsigned long Remove = 0;
+   unsigned long Keep = 0;
+   for (pkgCache::PkgIterator I = Dep.PkgBegin(); I.end() == false; I++)
+   {
+      if (Dep[I].NewInstall() == true &&
+	  (State == NULL || (*State)[I].NewInstall() == false))
+	 Install++;
+      else
+      {
+	 if (Dep[I].Upgrade() == true &&
+	     (State == NULL || (*State)[I].Upgrade() == false))
+	    Upgrade++;
+	 else
+	    if (Dep[I].Downgrade() == true &&
+		(State == NULL || (*State)[I].Downgrade() == false))
+	       Downgrade++;
+	    else
+	       if (State != NULL &&
+		   (((*State)[I].NewInstall() == true && Dep[I].NewInstall() == false) ||
+		    ((*State)[I].Upgrade() == true && Dep[I].Upgrade() == false) ||
+		    ((*State)[I].Downgrade() == true && Dep[I].Downgrade() == false)))
+		  Keep++;
+      }
+      // CNC:2002-07-29
+      if (Dep[I].Delete() == true &&
+	  (State == NULL || (*State)[I].Delete() == false))
+      {
+	 bool Obsoleted = false;
+	 string by;
+	 for (pkgCache::DepIterator D = I.RevDependsList();
+	      D.end() == false; D++)
+	 {
+	    if (D->Type == pkgCache::Dep::Obsoletes &&
+	        Dep[D.ParentPkg()].Install() &&
+	        (pkgCache::Version*)D.ParentVer() == Dep[D.ParentPkg()].InstallVer &&
+	        Dep.VS().CheckDep(I.CurrentVer().VerStr(), D) == true)
+	    {
+	       Obsoleted = true;
+	       break;
+	    }
+	 }
+	 if (Obsoleted)
+	    Replace++;
+	 else
+	    Remove++;
+      }
+      else if ((Dep[I].iFlags & pkgDepCache::ReInstall) == pkgDepCache::ReInstall &&
+	       (State == NULL || !((*State)[I].iFlags & pkgDepCache::ReInstall)))
+	 ReInstall++;
+   }   
+
+   ioprintf(out,_("%lu upgraded, %lu newly installed, "),
+	    Upgrade,Install);
+   
+   if (ReInstall != 0)
+      ioprintf(out,_("%lu reinstalled, "),ReInstall);
+   if (Downgrade != 0)
+      ioprintf(out,_("%lu downgraded, "),Downgrade);
+   // CNC:2002-07-29
+   if (Replace != 0)
+      ioprintf(out,_("%lu replaced, "),Replace);
+
+   // CNC:2002-07-29
+   if (State == NULL)
+      ioprintf(out,_("%lu removed and %lu not upgraded.\n"),
+	       Remove,Dep.KeepCount());
+   else
+      ioprintf(out,_("%lu removed and %lu kept.\n"),Remove,Keep);
+
+   
+   if (Dep.BadCount() != 0)
+      ioprintf(out,_("%lu not fully installed or removed.\n"),
+	       Dep.BadCount());
+}
+									/*}}}*/
+
+// ShowChanges - Show what would change between the saved state and the /*{{{*/
+//	         cache file state.
+// ---------------------------------------------------------------------
+/* */
+bool ShowChanges(CacheFile &Cache,pkgDepCache::State *State=NULL)
+{
+   ShowUpgraded(c1out,Cache,State);
+   ShowDel(c1out,Cache,State);
+   ShowNew(c1out,Cache,State);
+   if (State != NULL)
+      ShowKept(c1out,Cache,State);
+   ShowHold(c1out,Cache,State);
+   ShowDowngraded(c1out,Cache,State);
+   ShowEssential(c1out,Cache,State);
+   Stats(c1out,Cache,State);
+
+   if (State != NULL) {
+      double DebBytes = Cache->DebSize()-State->DebSize();
+      // Number of bytes
+      if (DebBytes >= 0)
+	 ioprintf(c1out,_("Will need more %sB of archives.\n"),
+		  SizeToStr(DebBytes).c_str());
+      else
+	 ioprintf(c1out,_("Will need less %sB of archives.\n"),
+		  SizeToStr(-1*DebBytes).c_str());
+
+      double UsrSize = Cache->UsrSize()-State->UsrSize();
+      // Size delta
+      if (UsrSize >= 0)
+	 ioprintf(c1out,_("After unpacking will need more %sB of disk space.\n"),
+		  SizeToStr(UsrSize).c_str());
+      else
+	 ioprintf(c1out,_("After unpacking will need less %sB of disk space.\n"),
+		  SizeToStr(-1*UsrSize).c_str());
+   } else {
+      double DebBytes = Cache->DebSize();
+      // Number of bytes
+      ioprintf(c1out,_("Will need %sB of archives.\n"),
+	       SizeToStr(DebBytes).c_str());
+
+      // Size delta
+      if (Cache->UsrSize() >= 0)
+	 ioprintf(c1out,_("After unpacking %sB of additional disk space will be used.\n"),
+		  SizeToStr(Cache->UsrSize()).c_str());
+      else
+	 ioprintf(c1out,_("After unpacking %sB disk space will be freed.\n"),
+		  SizeToStr(-1*Cache->UsrSize()).c_str());
+   }
+   return true;
+}
+									/*}}}*/
+
+bool ConfirmChanges(CacheFile &Cache, AutoRestore &StateGuard)
+{
+   if (StateGuard->Changed()) {
+      c2out << _("Unrequested changes are needed to execute this operation.")
+	    << endl;
+      ShowChanges(Cache,&StateGuard);
+      c2out << _("Do you want to continue? [Y/n] ") << flush;
+      if (YnPrompt() == false) {
+	 c2out << _("Abort.") << endl;
+	 return false;
+      }
+   }
+   StateGuard.UnGuard();
+   return true;
+}
+
+// CacheFile::NameComp - QSort compare by name				/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+pkgCache *CacheFile::SortCache = 0;
+int CacheFile::NameComp(const void *a,const void *b)
+{
+   if (*(pkgCache::Package **)a == 0 || *(pkgCache::Package **)b == 0)
+      return *(pkgCache::Package **)a - *(pkgCache::Package **)b;
+   
+   const pkgCache::Package &A = **(pkgCache::Package **)a;
+   const pkgCache::Package &B = **(pkgCache::Package **)b;
+
+   return strcmp(SortCache->StrP + A.Name,SortCache->StrP + B.Name);
+}
+									/*}}}*/
+// CacheFile::Sort - Sort by name					/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void CacheFile::Sort()
+{
+   delete [] List;
+   List = new pkgCache::Package *[Cache->Head().PackageCount];
+   memset(List,0,sizeof(*List)*Cache->Head().PackageCount);
+   pkgCache::PkgIterator I = Cache->PkgBegin();
+   for (;I.end() != true; I++)
+      List[I->ID] = I;
+
+   SortCache = *this;
+   qsort(List,Cache->Head().PackageCount,sizeof(*List),NameComp);
+}
+									/*}}}*/
+// CacheFile::CheckDeps - Open the cache file				/*{{{*/
+// ---------------------------------------------------------------------
+/* This routine generates the caches and then opens the dependency cache
+   and verifies that the system is OK. */
+bool CacheFile::CheckDeps(bool AllowBroken)
+{
+   if (_error->PendingError() == true)
+      return false;
+
+   // Check that the system is OK
+   //if (DCache->DelCount() != 0 || DCache->InstCount() != 0)
+   //   return _error->Error("Internal Error, non-zero counts");
+   
+   // Apply corrections for half-installed packages
+   if (pkgApplyStatus(*DCache) == false)
+      return false;
+   
+   // Nothing is broken
+   if (DCache->BrokenCount() == 0 || AllowBroken == true)
+      return true;
+
+   // Attempt to fix broken things
+   if (_config->FindB("APT::Get::Fix-Broken",false) == true)
+   {
+      c1out << _("Correcting dependencies...") << flush;
+      if (pkgFixBroken(*DCache) == false || DCache->BrokenCount() != 0)
+      {
+	 c1out << _(" failed.") << endl;
+	 ShowBroken(c1out,*this,true);
+
+	 return _error->Error(_("Unable to correct dependencies"));
+      }
+      if (pkgMinimizeUpgrade(*DCache) == false)
+	 return _error->Error(_("Unable to minimize the upgrade set"));
+      
+      c1out << _(" Done") << endl;
+   }
+   else
+   {
+      c1out << _("You might want to run `install -f' to correct these.") << endl;
+      ShowBroken(c1out,*this,true);
+
+      return _error->Error(_("Unmet dependencies. Try using -f."));
+   }
+      
+   return true;
+}
+									/*}}}*/
+
+// CNC:2002-07-06
+bool DoClean(CommandLine &CmdL);
+bool DoAutoClean(CommandLine &CmdL);
+
+// InstallPackages - Actually download and install the packages		/*{{{*/
+// ---------------------------------------------------------------------
+/* This displays the informative messages describing what is going to 
+   happen and then calls the download routines */
+bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
+		     bool Saftey = true)
+{
+   if (_config->FindB("APT::Get::Purge",false) == true)
+   {
+      pkgCache::PkgIterator I = Cache->PkgBegin();
+      for (; I.end() == false; I++)
+      {
+	 if (I.Purge() == false && Cache[I].Mode == pkgDepCache::ModeDelete)
+	    Cache->MarkDelete(I,true);
+      }
+   }
+   
+   bool Fail = false;
+   bool Essential = false;
+   
+   // Show all the various warning indicators
+   // CNC:2002-03-06 - Change Show-Upgraded default to true, and move upwards.
+   if (_config->FindB("APT::Get::Show-Upgraded",true) == true)
+      ShowUpgraded(c1out,Cache);
+   ShowDel(c1out,Cache);
+   ShowNew(c1out,Cache);
+   if (ShwKept == true)
+      ShowKept(c1out,Cache);
+   Fail |= !ShowHold(c1out,Cache);
+   Fail |= !ShowDowngraded(c1out,Cache);
+   Essential = !ShowEssential(c1out,Cache);
+   Fail |= Essential;
+   Stats(c1out,Cache);
+   
+   // Sanity check
+   if (Cache->BrokenCount() != 0)
+   {
+      ShowBroken(c1out,Cache,false);
+      return _error->Error("Internal Error, InstallPackages was called with broken packages!");
+   }
+
+   if (Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
+       Cache->BadCount() == 0)
+      return true;
+
+   // No remove flag
+   if (Cache->DelCount() != 0 && _config->FindB("APT::Get::Remove",true) == false)
+      return _error->Error(_("Packages need to be removed but Remove is disabled."));
+       
+   // Run the simulator ..
+   if (_config->FindB("APT::Get::Simulate") == true)
+   {
+      pkgSimulate PM(Cache);
+      pkgPackageManager::OrderResult Res = PM.DoInstall();
+      if (Res == pkgPackageManager::Failed)
+	 return false;
+      if (Res != pkgPackageManager::Completed)
+	 return _error->Error("Internal Error, Ordering didn't finish");
+      return true;
+   }
+   
+   // Create the text record parser
+   pkgRecords Recs(Cache);
+   if (_error->PendingError() == true)
+      return false;
+   
+   // Lock the archive directory
+   FileFd Lock;
+   if (_config->FindB("Debug::NoLocking",false) == false &&
+       _config->FindB("APT::Get::Print-URIs") == false)
+   {
+      Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
+      if (_error->PendingError() == true)
+	 return _error->Error(_("Unable to lock the download directory"));
+   }
+   
+   // Create the download object
+   AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));   
+   pkgAcquire Fetcher(&Stat);
+
+   // Read the source list
+   pkgSourceList List;
+   if (List.ReadMainList() == false)
+      return _error->Error(_("The list of sources could not be read."));
+   
+   // Create the package manager and prepare to download
+   SPtr<pkgPackageManager> PM= _system->CreatePM(Cache);
+   if (PM->GetArchives(&Fetcher,&List,&Recs) == false || 
+       _error->PendingError() == true)
+      return false;
+
+   // Display statistics
+   double FetchBytes = Fetcher.FetchNeeded();
+   double FetchPBytes = Fetcher.PartialPresent();
+   double DebBytes = Fetcher.TotalNeeded();
+   if (DebBytes != Cache->DebSize())
+   {
+      c0out << DebBytes << ',' << Cache->DebSize() << endl;
+      c0out << "How odd.. The sizes didn't match, email apt@packages.debian.org" << endl;
+   }
+   
+   // Number of bytes
+   if (DebBytes != FetchBytes)
+      ioprintf(c1out,_("Need to get %sB/%sB of archives.\n"),
+	       SizeToStr(FetchBytes).c_str(),SizeToStr(DebBytes).c_str());
+   else
+      ioprintf(c1out,_("Need to get %sB of archives.\n"),
+	       SizeToStr(DebBytes).c_str());
+
+   // Size delta
+   if (Cache->UsrSize() >= 0)
+      ioprintf(c1out,_("After unpacking %sB of additional disk space will be used.\n"),
+	       SizeToStr(Cache->UsrSize()).c_str());
+   else
+      ioprintf(c1out,_("After unpacking %sB disk space will be freed.\n"),
+	       SizeToStr(-1*Cache->UsrSize()).c_str());
+
+   if (_error->PendingError() == true)
+      return false;
+
+   /* Check for enough free space, but only if we are actually going to
+      download */
+   if (_config->FindB("APT::Get::Print-URIs") == false &&
+       _config->FindB("APT::Get::Download",true) == true)
+   {
+      struct statvfs Buf;
+      string OutputDir = _config->FindDir("Dir::Cache::Archives");
+      if (statvfs(OutputDir.c_str(),&Buf) != 0)
+	 return _error->Errno("statvfs","Couldn't determine free space in %s",
+			      OutputDir.c_str());
+      // CNC:2002-07-11
+      if (unsigned(Buf.f_bavail) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
+	 return _error->Error(_("You don't have enough free space in %s."),
+			      OutputDir.c_str());
+   }
+   
+   // Fail safe check
+   if (_config->FindI("quiet",0) >= 2 ||
+       _config->FindB("APT::Get::Assume-Yes",false) == true)
+   {
+      if (Fail == true && _config->FindB("APT::Get::Force-Yes",false) == false)
+	 return _error->Error(_("There are problems and -y was used without --force-yes"));
+   }         
+
+   if (Essential == true && Saftey == true)
+   {
+      if (_config->FindB("APT::Get::Trivial-Only",false) == true)
+	 return _error->Error(_("Trivial Only specified but this is not a trivial operation."));
+      
+      const char *Prompt = _("Yes, do as I say!");
+      ioprintf(c2out,
+	       _("You are about to do something potentially harmful\n"
+		 "To continue type in the phrase '%s'\n"
+		 " ?] "),Prompt);
+      c2out << flush;
+      if (AnalPrompt(Prompt) == false)
+      {
+	 c2out << _("Abort.") << endl;
+	 exit(1);
+      }     
+   }
+   else
+   {      
+      // Prompt to continue
+      if (Ask == true || Fail == true)
+      {            
+	 if (_config->FindB("APT::Get::Trivial-Only",false) == true)
+	    return _error->Error(_("Trivial Only specified but this is not a trivial operation."));
+	 
+	 if (_config->FindI("quiet",0) < 2 &&
+	     _config->FindB("APT::Get::Assume-Yes",false) == false)
+	 {
+	    c2out << _("Do you want to continue? [Y/n] ") << flush;
+	 
+	    if (YnPrompt() == false)
+	    {
+	       c2out << _("Abort.") << endl;
+	       exit(1);
+	    }     
+	 }	 
+      }      
+   }
+   
+   // Just print out the uris an exit if the --print-uris flag was used
+   if (_config->FindB("APT::Get::Print-URIs") == true)
+   {
+      pkgAcquire::UriIterator I = Fetcher.UriBegin();
+      for (; I != Fetcher.UriEnd(); I++)
+	 cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' << 
+	       I->Owner->FileSize << ' ' << I->Owner->MD5Sum() << endl;
+      return true;
+   }
+
+   /* Unlock the dpkg lock if we are not going to be doing an install
+      after. */
+   if (_config->FindB("APT::Get::Download-Only",false) == true)
+      _system->UnLock();
+
+   // CNC:2003-02-24
+   bool Ret = true;
+
+   AutoReOpenCache CacheGuard(GCache);
+   
+   // Run it
+   while (1)
+   {
+      bool Transient = false;
+      if (_config->FindB("APT::Get::Download",true) == false)
+      {
+	 for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I < Fetcher.ItemsEnd();)
+	 {
+	    if ((*I)->Local == true)
+	    {
+	       I++;
+	       continue;
+	    }
+
+	    // Close the item and check if it was found in cache
+	    (*I)->Finished();
+	    if ((*I)->Complete == false)
+	       Transient = true;
+	    
+	    // Clear it out of the fetch list
+	    delete *I;
+	    I = Fetcher.ItemsBegin();
+	 }	 
+      }
+      
+      if (Fetcher.Run() == pkgAcquire::Failed)
+	 return false;
+
+      // CNC:2003-02-24
+      _error->PopState();
+      
+      // Print out errors
+      bool Failed = false;
+      for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
+      {
+	 if ((*I)->Status == pkgAcquire::Item::StatDone &&
+	     (*I)->Complete == true)
+	    continue;
+	 
+	 if ((*I)->Status == pkgAcquire::Item::StatIdle)
+	 {
+	    Transient = true;
+	    // Failed = true;
+	    continue;
+	 }
+
+	 fprintf(stderr,_("Failed to fetch %s  %s\n"),(*I)->DescURI().c_str(),
+		 (*I)->ErrorText.c_str());
+	 Failed = true;
+      }
+
+      /* If we are in no download mode and missing files and there were
+         'failures' then the user must specify -m. Furthermore, there 
+         is no such thing as a transient error in no-download mode! */
+      if (Transient == true &&
+	  _config->FindB("APT::Get::Download",true) == false)
+      {
+	 Transient = false;
+	 Failed = true;
+      }
+      
+      if (_config->FindB("APT::Get::Download-Only",false) == true)
+      {
+	 if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
+	    return _error->Error(_("Some files failed to download"));
+	 c1out << _("Download complete and in download only mode") << endl;
+	 return true;
+      }
+      
+      if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
+      {
+	 return _error->Error(_("Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?"));
+      }
+      
+      if (Transient == true && Failed == true)
+	 return _error->Error(_("--fix-missing and media swapping is not currently supported"));
+      
+      // Try to deal with missing package files
+      if (Failed == true && PM->FixMissing() == false)
+      {
+	 cerr << _("Unable to correct missing packages.") << endl;
+	 return _error->Error(_("Aborting Install."));
+      }
+
+      // CNC:2002-10-18
+      if (Transient == false || _config->FindB("Acquire::CDROM::Copy-All", false) == false) {
+	 if (Transient == true) {
+	    // We must do that in a system independent way. */
+	    _config->Set("RPM::Install-Options::", "--nodeps");
+	 }
+	 _system->UnLock();
+	 pkgPackageManager::OrderResult Res = PM->DoInstall();
+	 if (Res == pkgPackageManager::Failed || _error->PendingError() == true)
+	 {
+	    if (Transient == false)
+	       return false;
+	    Ret = false;
+	 }
+
+	 // CNC:2002-07-06
+	 if (Res == pkgPackageManager::Completed)
+	 {
+	    CommandLine *CmdL = NULL; // Watch out! If used will blow up!
+	    if (_config->FindB("APT::Post-Install::Clean",false) == true) 
+	       Ret &= DoClean(*CmdL);
+	    else if (_config->FindB("APT::Post-Install::AutoClean",false) == true) 
+	       Ret &= DoAutoClean(*CmdL);
+	    return Ret;
+	 }
+	 
+	 _system->Lock();
+      }
+
+      // CNC:2003-02-24
+      _error->PushState();
+      
+      // Reload the fetcher object and loop again for media swapping
+      Fetcher.Shutdown();
+      if (PM->GetArchives(&Fetcher,&List,&Recs) == false)
+	 return false;
+   }   
+}
+									/*}}}*/
+#define MODE_INSTALL 0
+#define MODE_REMOVE  1
+#define MODE_KEEP    2
+// TryToInstall - Try to install a single package			/*{{{*/
+// ---------------------------------------------------------------------
+/* This used to be inlined in DoInstall, but with the advent of regex package
+   name matching it was split out.. */
+bool TryToInstall(pkgCache::PkgIterator Pkg,pkgDepCache &Cache,
+		  pkgProblemResolver &Fix,int Mode,bool BrokenFix,
+		  unsigned int &ExpectedInst,bool AllowFail = true)
+{
+   /* This is a pure virtual package and there is a single available 
+      provides */
+   if (Cache[Pkg].CandidateVer == 0 && Pkg->ProvidesList != 0 &&
+       Pkg.ProvidesList()->NextProvides == 0)
+   {
+      pkgCache::PkgIterator Tmp = Pkg.ProvidesList().OwnerPkg();
+      // CNC:2003-11-21 - Check if the current candidate is really
+      //                  providing that dependency
+      ioprintf(c1out,_("Selecting %s for '%s'\n"),
+	       Tmp.Name(),Pkg.Name());
+      pkgCache::VerIterator Ver = Cache[Tmp].CandidateVerIter(Cache);
+      pkgCache::PrvIterator Prv = Ver.ProvidesList();
+      bool Found = false;
+      for (; Prv.end() == false; Prv++) {
+	 if (strcmp(Prv.Name(), Pkg.Name()) == 0) {
+	    Found = true;
+	    break;
+	 }
+      }
+      if (Found == false) {
+	 // The current candidate doesn't provide the needed dependency.
+	 // Look for one that does.
+	 Ver = Tmp.VersionList();
+	 for (; Ver.end() == false; Ver++) {
+	    Prv = Ver.ProvidesList();
+	    Found = false;
+	    for (; Prv.end() == false; Prv++) {
+	       if (strcmp(Prv.Name(), Pkg.Name()) == 0) {
+		  Found = true;
+		  break;
+	       }
+	    }
+	    if (Found) {
+	       Cache.SetCandidateVersion(Ver);
+	       break;
+	    }
+	 }
+	 if (Found == false) {
+	    ioprintf(c1out,_("Internal error. Package %s doesn't provide %s\n"),Tmp.Name(),Pkg.Name());
+	    return false;
+	 }
+      }
+      Pkg = Tmp;
+   }
+   
+   // Handle the no-upgrade case
+   if (_config->FindB("APT::Get::upgrade",true) == false &&
+       Pkg->CurrentVer != 0)
+   {
+      if (AllowFail == true)
+	 ioprintf(c1out,_("Skipping %s, it is already installed and upgrade is not set.\n"),
+		  Pkg.Name());
+      return true;
+   }
+   
+   // Check if there is something at all to install
+   pkgDepCache::StateCache &State = Cache[Pkg];
+   if (Mode == MODE_REMOVE && Pkg->CurrentVer == 0)
+   {
+      Fix.Clear(Pkg);
+      Fix.Protect(Pkg);
+      Fix.Remove(Pkg);
+      
+      /* We want to continue searching for regex hits, so we return false here
+         otherwise this is not really an error. */
+      if (AllowFail == false)
+	 return false;
+      
+      ioprintf(c1out,_("Package %s is not installed, so not removed\n"),Pkg.Name());
+      return true;
+   }
+   
+   if (State.CandidateVer == 0 && Mode == MODE_INSTALL)
+   {
+      if (AllowFail == false)
+	 return false;
+      
+      if (Pkg->ProvidesList != 0)
+      {
+	 ioprintf(c1out,_("Package %s is a virtual package provided by:\n"),
+		  Pkg.Name());
+	 
+	 pkgCache::PrvIterator I = Pkg.ProvidesList();
+	 for (; I.end() == false; I++)
+	 {
+	    pkgCache::PkgIterator Pkg = I.OwnerPkg();
+	    
+	    if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer())
+	    {
+	       if (Cache[Pkg].Install() == true && Cache[Pkg].NewInstall() == false)
+		  c1out << "  " << Pkg.Name() << " " << I.OwnerVer().VerStr() <<
+		  _(" [Installed]") << endl;
+	       else
+		  c1out << "  " << Pkg.Name() << " " << I.OwnerVer().VerStr() << endl;
+	    }      
+	 }
+	 c1out << _("You should explicitly select one to install.") << endl;
+      }
+      else
+      {
+	 ioprintf(c1out,
+	 _("Package %s has no available version, but exists in the database.\n"
+	   "This typically means that the package was mentioned in a dependency and\n"
+	   "never uploaded, has been obsoleted or is not available with the contents\n"
+	   "of sources.list\n"),Pkg.Name());
+	 
+	 string List;
+	 string VersionsList;
+	 SPtrArray<bool> Seen = new bool[Cache.Head().PackageCount];
+	 memset(Seen,0,Cache.Head().PackageCount*sizeof(*Seen));
+	 pkgCache::DepIterator Dep = Pkg.RevDependsList();
+	 for (; Dep.end() == false; Dep++)
+	 {
+	    // CNC:2002-07-30
+	    if (Dep->Type != pkgCache::Dep::Replaces &&
+	        Dep->Type != pkgCache::Dep::Obsoletes)
+	       continue;
+	    if (Seen[Dep.ParentPkg()->ID] == true)
+	       continue;
+	    Seen[Dep.ParentPkg()->ID] = true;
+	    List += string(Dep.ParentPkg().Name()) + " ";
+            //VersionsList += string(Dep.ParentPkg().CurVersion) + "\n"; ???
+	 }	    
+	 ShowList(c1out,_("However the following packages replace it:"),List,VersionsList);
+      }
+      
+      _error->Error(_("Package %s has no installation candidate"),Pkg.Name());
+      return false;
+   }
+
+   Fix.Clear(Pkg);
+   Fix.Protect(Pkg);   
+
+   if (Mode == MODE_KEEP) {
+      Cache.MarkKeep(Pkg);
+      return true;
+   }
+   
+   if (Mode == MODE_REMOVE)
+   {
+      Fix.Remove(Pkg);
+      Cache.MarkDelete(Pkg,_config->FindB("APT::Get::Purge",false));
+      return true;
+   }
+   
+   // Install it
+   Cache.MarkInstall(Pkg,false);
+   if (State.Install() == false)
+   {
+      if (_config->FindB("APT::Get::ReInstall",false) == true)
+      {
+	 if (Pkg->CurrentVer == 0 || Pkg.CurrentVer().Downloadable() == false)
+	    ioprintf(c1out,_("Reinstallation of %s is not possible, it cannot be downloaded.\n"),
+		     Pkg.Name());
+	 else
+	    Cache.SetReInstall(Pkg,true);
+      }      
+      else
+      {
+	 if (AllowFail == true)
+	    ioprintf(c1out,_("%s is already the newest version.\n"),
+		     Pkg.Name());
+      }      
+   }   
+   else
+      ExpectedInst++;
+   
+   // Install it with autoinstalling enabled.
+   if (State.InstBroken() == true && BrokenFix == false)
+      Cache.MarkInstall(Pkg,true);
+   return true;
+}
+									/*}}}*/
+// TryToChangeVer - Try to change a candidate version			/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+// CNC:2003-11-05 - Applied patch by ALT-Linux changing the way
+//                  versions are requested by the user.
+static const char *op2str(int op)
+{
+   switch (op & 0x0f)
+   {
+      case pkgCache::Dep::LessEq: return "<=";
+      case pkgCache::Dep::GreaterEq: return ">=";
+      case pkgCache::Dep::Less: return "<";
+      case pkgCache::Dep::Greater: return ">";
+      case pkgCache::Dep::Equals: return "=";
+      case pkgCache::Dep::NotEquals: return "!";
+      default: return "";
+   }
+}
+
+// CNC:2003-11-11
+bool TryToChangeVer(pkgCache::PkgIterator &Pkg,pkgDepCache &Cache,
+ 		    int VerOp,const char *VerTag,bool IsRel)
+{
+   // CNC:2003-11-05
+   pkgVersionMatch Match(VerTag,(IsRel == true?pkgVersionMatch::Release : 
+ 				 pkgVersionMatch::Version),VerOp);
+   
+   pkgCache::VerIterator Ver = Match.Find(Pkg);
+			 
+   if (Ver.end() == true)
+   {
+      // CNC:2003-11-05
+      if (IsRel == true)
+	 return _error->Error(_("Release %s'%s' for '%s' was not found"),
+			      op2str(VerOp),VerTag,Pkg.Name());
+      return _error->Error(_("Version %s'%s' for '%s' was not found"),
+			   op2str(VerOp),VerTag,Pkg.Name());
+   }
+   
+   if (strcmp(VerTag,Ver.VerStr()) != 0)
+   {
+      // CNC:2003-11-11
+      if (IsRel == true)
+	 ioprintf(c1out,_("Selected version %s (%s) for %s\n"),
+		  Ver.VerStr(),Ver.RelStr().c_str(),Pkg.Name());
+      else
+	 ioprintf(c1out,_("Selected version %s for %s\n"),
+		  Ver.VerStr(),Pkg.Name());
+   }
+   
+   Cache.SetCandidateVersion(Ver);
+   // CNC:2003-11-11
+   Pkg = Ver.ParentPkg();
+   return true;
+}
+									/*}}}*/
+// FindSrc - Find a source record					/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs,
+			       pkgSrcRecords &SrcRecs,string &Src,
+			       pkgDepCache &Cache)
+{
+   // We want to pull the version off the package specification..
+   string VerTag;
+   string TmpSrc = Name;
+   string::size_type Slash = TmpSrc.rfind('=');
+   if (Slash != string::npos)
+   {
+      VerTag = string(TmpSrc.begin() + Slash + 1,TmpSrc.end());
+      TmpSrc = string(TmpSrc.begin(),TmpSrc.begin() + Slash);
+   }
+   
+   /* Lookup the version of the package we would install if we were to
+      install a version and determine the source package name, then look
+      in the archive for a source package of the same name. In theory
+      we could stash the version string as well and match that too but
+      today there aren't multi source versions in the archive. */
+   if (_config->FindB("APT::Get::Only-Source") == false && 
+       VerTag.empty() == true)
+   {
+      pkgCache::PkgIterator Pkg = Cache.FindPkg(TmpSrc);
+      if (Pkg.end() == false)
+      {
+	 pkgCache::VerIterator Ver = Cache.GetCandidateVer(Pkg);      
+	 if (Ver.end() == false)
+	 {
+	    pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList());
+	    Src = Parse.SourcePkg();
+	 }
+      }   
+   }
+   
+   // No source package name..
+   if (Src.empty() == true)
+      Src = TmpSrc;
+   
+   // The best hit
+   pkgSrcRecords::Parser *Last = 0;
+   unsigned long Offset = 0;
+   string Version;
+   bool IsMatch = false;
+   
+   // If we are matching by version then we need exact matches to be happy
+   if (VerTag.empty() == false)
+      IsMatch = true;
+   
+   /* Iterate over all of the hits, which includes the resulting
+      binary packages in the search */
+   pkgSrcRecords::Parser *Parse;
+   SrcRecs.Restart();
+   while ((Parse = SrcRecs.Find(Src.c_str(),false)) != 0)
+   {
+      string Ver = Parse->Version();
+      
+      // Skip name mismatches
+      if (IsMatch == true && Parse->Package() != Src)
+	 continue;
+      
+      if (VerTag.empty() == false)
+      {
+	 /* Don't want to fall through because we are doing exact version 
+	    matching. */
+	 if (Cache.VS().CmpVersion(VerTag,Ver) != 0)
+	    continue;
+	 
+	 Last = Parse;
+	 Offset = Parse->Offset();
+	 break;
+      }
+				  
+      // Newer version or an exact match
+      if (Last == 0 || Cache.VS().CmpVersion(Version,Ver) < 0 || 
+	  (Parse->Package() == Src && IsMatch == false))
+      {
+	 IsMatch = Parse->Package() == Src;
+	 Last = Parse;
+	 Offset = Parse->Offset();
+	 Version = Ver;
+      }      
+   }
+   
+   if (Last == 0)
+      return 0;
+   
+   if (Last->Jump(Offset) == false)
+      return 0;
+   
+   return Last;
+}
+									/*}}}*/
+
+// DoUpdate - Update the package lists					/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool DoUpdate(CommandLine &CmdL)
+{
+   if (CheckHelp(CmdL) == true)
+      return true;
+
+   bool Partial = false;
+   pkgSourceList List;
+
+   if (CmdL.FileSize() != 1)
+   {
+      List.ReadVendors();
+      for (const char **I = CmdL.FileList + 1; *I != 0; I++)
+      {
+	 string Repo = _config->FindDir("Dir::Etc::sourceparts") + *I;
+	 if (FileExists(Repo) == false)
+	    Repo += ".list";
+	 if (FileExists(Repo) == true)
+	 {
+	    if (List.ReadAppend(Repo) == true)
+	       Partial = true;
+	    else
+	       return _error->Error(_("Sources list %s could not be read"),Repo.c_str());
+	 }
+	 else
+	    return _error->Error(_("Sources list %s doesn't exist"),Repo.c_str());
+      }
+   }
+   else if (List.ReadMainList() == false)
+      return false;
+
+   // Lock the list directory
+   FileFd Lock;
+   if (_config->FindB("Debug::NoLocking",false) == false)
+   {
+      Lock.Fd(GetLock(_config->FindDir("Dir::State::Lists") + "lock"));
+      if (_error->PendingError() == true)
+	 return _error->Error(_("Unable to lock the list directory"));
+   }
+
+// CNC:2003-03-19
+#ifdef WITH_LUA
+   _lua->SetDepCache(*GCache);
+   _lua->RunScripts("Scripts::AptGet::Update::Pre", false);
+   _lua->ResetCaches();
+#endif
+   
+   // Create the download object
+   AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
+   pkgAcquire Fetcher(&Stat);
+
+   // CNC:2002-07-03
+   bool Failed = false;
+   // Populate it with release file URIs
+   if (List.GetReleases(&Fetcher) == false)
+      return false;
+   if (_config->FindB("APT::Get::Print-URIs") == false)
+   {
+      Fetcher.Run();
+      for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
+      {
+	 if ((*I)->Status == pkgAcquire::Item::StatDone)
+	    continue;
+	 (*I)->Finished();
+	 Failed = true;
+      }
+      if (Failed == true)
+	 _error->Warning(_("Release files for some repositories could not be retrieved or authenticated. Such repositories are being ignored."));
+   }
+   
+   // Populate it with the source selection
+   if (List.GetIndexes(&Fetcher) == false)
+	 return false;
+   
+   // Just print out the uris an exit if the --print-uris flag was used
+   if (_config->FindB("APT::Get::Print-URIs") == true)
+   {
+      pkgAcquire::UriIterator I = Fetcher.UriBegin();
+      for (; I != Fetcher.UriEnd(); I++)
+	 cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' << 
+	       I->Owner->FileSize << ' ' << I->Owner->MD5Sum() << endl;
+      return true;
+   }
+   
+   // Run it
+   if (Fetcher.Run() == pkgAcquire::Failed)
+      return false;
+
+   for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
+   {
+      if ((*I)->Status == pkgAcquire::Item::StatDone)
+	 continue;
+
+      (*I)->Finished();
+      
+      fprintf(stderr,_("Failed to fetch %s  %s\n"),(*I)->DescURI().c_str(),
+	      (*I)->ErrorText.c_str());
+      Failed = true;
+   }
+   
+   // Clean out any old list files
+   if (_config->FindB("APT::Get::List-Cleanup",true) == true)
+   {
+      if (Fetcher.Clean(_config->FindDir("Dir::State::lists")) == false ||
+	  Fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/") == false)
+	 return false;
+   }
+
+   {
+      AutoReOpenCache CacheGuard(GCache);
+   }
+
+// CNC:2003-03-19
+#ifdef WITH_LUA
+   _lua->SetDepCache(*GCache);
+   _lua->RunScripts("Scripts::AptGet::Update::Post", false);
+   _lua->ResetCaches();
+#endif
+   
+   if (Failed == true)
+      return _error->Error(_("Some index files failed to download, they have been ignored, or old ones used instead."));
+   
+   return true;
+}
+									/*}}}*/
+// DoUpgrade - Upgrade all packages					/*{{{*/
+// ---------------------------------------------------------------------
+/* Upgrade all packages without installing new packages or erasing old
+   packages */
+bool DoUpgrade(CommandLine &CmdL)
+{
+   if (CheckHelp(CmdL, 0) == true)
+      return true;
+   
+   CacheFile &Cache = *GCache;
+   if (GCache->CanCommit() == false) {
+      _error->Error(_("You have no permissions for that"));
+      return false;
+   }
+   
+   AutoRestore StateGuard(Cache);
+   
+   if (GCache->CheckDeps() == false)
+      return false;
+
+   // Do the upgrade
+   if (pkgAllUpgrade(Cache) == false)
+   {
+      ShowBroken(c1out,Cache,false);
+      return _error->Error(_("Internal Error, AllUpgrade broke stuff"));
+   }
+
+// CNC:2003-03-19
+#ifdef WITH_LUA
+   _lua->SetDepCache(Cache);
+   _lua->RunScripts("Scripts::AptGet::Upgrade", false);
+   _lua->ResetCaches();
+#endif
+
+   ConfirmChanges(Cache, StateGuard);
+   
+   return true;
+}
+									/*}}}*/
+// DoInstall - Install packages from the command line			/*{{{*/
+// ---------------------------------------------------------------------
+/* Install named packages */
+bool DoInstall(CommandLine &CmdL)
+{
+   if (CheckHelp(CmdL) == true)
+      return true;
+
+   CacheFile &Cache = *GCache;
+   if (GCache->CanCommit() == false) {
+      _error->Error(_("You have no permissions for that"));
+      return false;
+   }
+   if (Cache.CheckDeps(CmdL.FileSize() != 1) == false)
+      return false;
+
+   // Enter the special broken fixing mode if the user specified arguments
+   bool BrokenFix = false;
+   if (Cache->BrokenCount() != 0)
+      BrokenFix = true;
+   
+   unsigned int ExpectedInst = 0;
+   unsigned int Packages = 0;
+   pkgProblemResolver Fix(Cache);
+   
+   int DefMode = MODE_INSTALL;
+   if (strcasecmp(CmdL.FileList[0],"remove") == 0)
+      DefMode = MODE_REMOVE;
+   else if (strcasecmp(CmdL.FileList[0],"keep") == 0)
+      DefMode = MODE_KEEP;
+
+   AutoRestore StateGuard(Cache);
+
+   for (const char **I = CmdL.FileList + 1; *I != 0; I++)
+   {
+      // Duplicate the string
+      unsigned int Length = strlen(*I);
+      char S[300];
+      if (Length >= sizeof(S))
+	 continue;
+      strcpy(S,*I);
+      
+      // CNC:2003-03-15
+      char OrigS[300];
+      strcpy(OrigS,S);
+      
+      // See if we are removing and special indicators..
+      int Mode = DefMode;
+      char *VerTag = 0;
+      bool VerIsRel = false;
+      // CNC:2003-11-05
+      int VerOp = 0;
+      while (Cache->FindPkg(S).end() == true)
+      {
+	 // Handle an optional end tag indicating what to do
+	 if (Length >= 1 && S[Length - 1] == '-')
+	 {
+	    Mode = MODE_REMOVE;
+	    S[--Length] = 0;
+	    continue;
+	 }
+	 
+	 if (Length >= 1 && S[Length - 1] == '+')
+	 {
+	    Mode = MODE_INSTALL;
+	    S[--Length] = 0;
+	    continue;
+	 }
+	 
+	 // CNC:2003-11-05
+	 char *sep = strpbrk(S,"=><");
+	 if (sep)
+	 {
+	    char *p;
+	    int eq = 0, gt = 0, lt = 0;
+
+	    VerIsRel = false;
+	    for (p = sep; *p && strchr("=><",*p); ++p)
+	       switch (*p)
+	       {
+		  case '=': eq = 1; break;
+		  case '>': gt = 1; break;
+		  case '<': lt = 1; break;
+	       }
+	    if (eq)
+	    {
+	       if (lt && gt)
+		  return _error->Error(_("Couldn't parse name '%s'"),S);
+	       else if (lt)
+		  VerOp = pkgCache::Dep::LessEq;
+	       else if (gt)
+		  VerOp = pkgCache::Dep::GreaterEq;
+	       else
+		  VerOp = pkgCache::Dep::Equals;
+	    }
+	    else
+	    {
+	       if (lt && gt)
+		  VerOp = pkgCache::Dep::NotEquals;
+	       else if (lt)
+		  VerOp = pkgCache::Dep::Less;
+	       else if (gt)
+		  VerOp = pkgCache::Dep::Greater;
+	       else
+		  return _error->Error(_("Couldn't parse name '%s'"),S);
+	    }
+	    *sep = '\0';
+	    VerTag = p;
+	 }
+	 
+	 // CNC:2003-11-21 - Try to handle unknown file items.
+	 if (S[0] == '/')
+	 {
+	    pkgRecords Recs(Cache);
+	    if (_error->PendingError() == true)
+	       return false;
+	    pkgCache::PkgIterator Pkg = (*Cache).PkgBegin();
+	    for (; Pkg.end() == false; Pkg++)
+	    {
+	       // Should we try on all versions?
+	       pkgCache::VerIterator Ver = (*Cache)[Pkg].CandidateVerIter(*Cache);
+	       if (Ver.end() == false)
+	       {
+		  pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList());
+		  if (Parse.HasFile(S)) {
+		     strcpy(S, Pkg.Name());
+		     // Confirm the translation.
+		     ExpectedInst += 1000;
+		     break;
+		  }
+	       }
+	    }
+	 }
+
+	 char *Slash = strchr(S,'/');
+	 if (Slash != 0)
+	 {
+	    VerIsRel = true;
+	    *Slash = 0;
+	    VerTag = Slash + 1;
+	 }
+	 
+	 break;
+      }
+      
+      // Locate the package
+      pkgCache::PkgIterator Pkg = Cache->FindPkg(S);
+      Packages++;
+      if (Pkg.end() == true)
+      {
+	 // Check if the name is a regex
+	 const char *I;
+	 for (I = S; *I != 0; I++)
+	    if (*I == '?' || *I == '*' || *I == '|' ||
+	        *I == '[' || *I == '^' || *I == '$')
+	       break;
+
+	 // CNC:2003-05-15
+	 if (*I == 0) {
+#ifdef WITH_LUA
+	    vector<string> VS;
+	    _lua->SetDepCache(Cache);
+	    _lua->SetDontFix();
+	    _lua->SetGlobal("argument", OrigS);
+	    _lua->SetGlobal("translated", VS);
+	    _lua->RunScripts("Scripts::AptGet::Install::TranslateArg", false);
+	    const char *name = _lua->GetGlobal("translated");
+	    if (name != NULL) {
+	       VS.push_back(name);
+	    } else {
+	       _lua->GetGlobalVS("translated", VS);
+	    }
+	    _lua->ResetGlobals();
+	    _lua->ResetCaches();
+
+	    // Translations must always be confirmed
+	    ExpectedInst += 1000;
+
+	    // Run over the matches
+	    bool Hit = false;
+	    for (vector<string>::const_iterator I = VS.begin();
+	         I != VS.end(); I++) {
+
+	       Pkg = Cache->FindPkg(*I);
+	       if (Pkg.end() == true)
+		  continue;
+
+	       ioprintf(c1out,_("Selecting %s for '%s'\n"),
+			Pkg.Name(),OrigS);
+	    
+	       Hit |= TryToInstall(Pkg,Cache,Fix,Mode,BrokenFix,
+				   ExpectedInst,true);
+	    }
+	 
+	    if (Hit == true)
+	       continue;
+#endif
+	    return _error->Error(_("Couldn't find package %s"),S);
+	 }
+
+	 // Regexs must always be confirmed
+	 ExpectedInst += 1000;
+	 
+	 // Compile the regex pattern
+	 regex_t Pattern;
+	 int Res;
+	 if ((Res = regcomp(&Pattern,S,REG_EXTENDED | REG_ICASE |
+		     REG_NOSUB)) != 0)
+	 {
+	    char Error[300];	    
+	    regerror(Res,&Pattern,Error,sizeof(Error));
+	    return _error->Error(_("Regex compilation error - %s"),Error);
+	 }
+	 
+	 // Run over the matches
+	 bool Hit = false;
+	 for (Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
+	 {
+	    if (regexec(&Pattern,Pkg.Name(),0,0,0) != 0)
+	       continue;
+	    
+	    // CNC:2003-11-23
+	    ioprintf(c1out,_("Selecting %s for '%s'\n"),
+		     Pkg.Name(),S);
+	    StateGuard->Ignore(Pkg);
+	    
+	    if (VerTag != 0)
+	       // CNC:2003-11-05
+	       if (TryToChangeVer(Pkg,Cache,VerOp,VerTag,VerIsRel) == false)
+		  return false;
+	    
+	    Hit |= TryToInstall(Pkg,Cache,Fix,Mode,BrokenFix,
+				ExpectedInst,false);
+	 }
+	 regfree(&Pattern);
+	 
+	 if (Hit == false)
+	    return _error->Error(_("Couldn't find package %s"),S);
+      }
+      else
+      {
+	 if (VerTag != 0)
+	    // CNC:2003-11-05
+	    if (TryToChangeVer(Pkg,Cache,VerOp,VerTag,VerIsRel) == false)
+	       return false;
+	 if (TryToInstall(Pkg,Cache,Fix,Mode,BrokenFix,ExpectedInst) == false)
+	    return false;
+	 StateGuard->Ignore(Pkg);
+      }
+   }
+
+// CNC:2003-03-19
+#ifdef WITH_LUA
+   _lua->SetDepCache(Cache);
+   _lua->SetDontFix();
+   _lua->RunScripts("Scripts::AptGet::Install::PreResolve", false);
+   _lua->ResetCaches();
+#endif
+
+#if 0 // PORTME
+   // CNC:2002-08-01
+   if (_config->FindB("APT::Remove-Depends",false) == true)
+      Fix.RemoveDepends();
+#endif
+
+   /* If we are in the Broken fixing mode we do not attempt to fix the
+      problems. This is if the user invoked install without -f and gave
+      packages */
+   if (BrokenFix == true && Cache->BrokenCount() != 0)
+   {
+      ConfirmChanges(Cache, StateGuard);
+      c1out << _("There are still broken packages. ")
+	    << _("Run `check' to see them.") << endl;
+      c1out << _("You can try to fix them automatically with `install -f'.") << endl;
+      return true;
+   }
+
+   // Call the scored problem resolver
+   if (DefMode != MODE_KEEP) {
+      Fix.InstallProtect();
+      if (Fix.Resolve(true) == false)
+	 _error->Discard();
+   } else {
+      if (Fix.Resolve(false) == false)
+	 _error->Discard();
+   }
+
+// CNC:2003-03-19
+#ifdef WITH_LUA
+   if (Cache->BrokenCount() == 0) {
+      _lua->SetDepCache(Cache);
+      _lua->SetProblemResolver(&Fix);
+      _lua->RunScripts("Scripts::AptGet::Install::PostResolve", false);
+      _lua->ResetCaches();
+   }
+#endif
+
+
+   // Now we check the state of the packages,
+   if (Cache->BrokenCount() != 0)
+   {
+      c1out << 
+       _("Some packages could not be installed. This may mean that you have\n" 
+	 "requested an impossible situation or if you are using the unstable\n" 
+	 "distribution that some required packages have not yet been created\n"
+	 "or been moved out of Incoming.") << endl;
+      if (Packages == 1)
+      {
+	 c1out << endl;
+	 c1out << 
+	  _("Since you only requested a single operation it is extremely likely that\n"
+	    "the package is simply not installable and a bug report against\n" 
+	    "that package should be filed.") << endl;
+      }
+
+      c1out << _("The following information may help to resolve the situation:") << endl;
+      c1out << endl;
+      ShowBroken(c1out,Cache,false);
+
+      return _error->Error(_("Broken packages"));
+   }
+
+   ConfirmChanges(Cache, StateGuard);
+
+   return true;
+}
+									/*}}}*/
+// DoDistUpgrade - Automatic smart upgrader				/*{{{*/
+// ---------------------------------------------------------------------
+/* Intelligent upgrader that will install and remove packages at will */
+bool DoDistUpgrade(CommandLine &CmdL)
+{
+   if (CheckHelp(CmdL,0) == true)
+      return true;
+
+   CacheFile &Cache = *GCache;
+   if (GCache->CanCommit() == false) {
+      _error->Error(_("You have no permissions for that"));
+      return false;
+   }
+
+   AutoRestore StateGuard(Cache);
+
+   if (GCache->CheckDeps() == false)
+      return false;
+
+   c0out << _("Calculating Upgrade... ") << flush;
+   if (pkgDistUpgrade(*Cache) == false)
+   {
+      c0out << _("Failed") << endl;
+      ShowBroken(c1out,Cache,false);
+      return false;
+   }
+
+// CNC:2003-03-19
+#ifdef WITH_LUA
+   _lua->SetDepCache(Cache);
+   _lua->RunScripts("Scripts::AptGet::DistUpgrade", false);
+   _lua->ResetCaches();
+#endif
+   
+   c0out << _("Done") << endl;
+   
+   ConfirmChanges(Cache, StateGuard);
+
+   return true;
+}
+									/*}}}*/
+// DoDSelectUpgrade - Do an upgrade by following dselects selections	/*{{{*/
+// ---------------------------------------------------------------------
+/* Follows dselect's selections */
+bool DoDSelectUpgrade(CommandLine &CmdL)
+{
+   if (CheckHelp(CmdL,0) == true)
+      return true;
+
+   CacheFile &Cache = *GCache;
+   if (GCache->CanCommit() == false) {
+      _error->Error(_("You have no permissions for that"));
+      return false;
+   }
+   
+   AutoRestore StateGuard(Cache);
+   
+   if (GCache->CheckDeps() == false)
+      return false;
+   
+   // Install everything with the install flag set
+   pkgCache::PkgIterator I = Cache->PkgBegin();
+   for (;I.end() != true; I++)
+   {
+      /* Install the package only if it is a new install, the autoupgrader
+         will deal with the rest */
+      if (I->SelectedState == pkgCache::State::Install)
+	 Cache->MarkInstall(I,false);
+   }
+
+   /* Now install their deps too, if we do this above then order of
+      the status file is significant for | groups */
+   for (I = Cache->PkgBegin();I.end() != true; I++)
+   {
+      /* Install the package only if it is a new install, the autoupgrader
+         will deal with the rest */
+      if (I->SelectedState == pkgCache::State::Install)
+	 Cache->MarkInstall(I,true);
+   }
+   
+   // Apply erasures now, they override everything else.
+   for (I = Cache->PkgBegin();I.end() != true; I++)
+   {
+      // Remove packages 
+      if (I->SelectedState == pkgCache::State::DeInstall ||
+	  I->SelectedState == pkgCache::State::Purge)
+	 Cache->MarkDelete(I,I->SelectedState == pkgCache::State::Purge);
+   }
+
+   /* Resolve any problems that dselect created, allupgrade cannot handle
+      such things. We do so quite agressively too.. */
+   if (Cache->BrokenCount() != 0)
+   {      
+      pkgProblemResolver Fix(Cache);
+
+      // Hold back held packages.
+      if (_config->FindB("APT::Ignore-Hold",false) == false)
+      {
+	 for (pkgCache::PkgIterator I = Cache->PkgBegin(); I.end() == false; I++)
+	 {
+	    if (I->SelectedState == pkgCache::State::Hold)
+	    {
+	       Fix.Protect(I);
+	       Cache->MarkKeep(I);
+	    }
+	 }
+      }
+   
+      if (Fix.Resolve() == false)
+      {
+	 ShowBroken(c1out,Cache,false);
+	 return _error->Error("Internal Error, problem resolver broke stuff");
+      }
+   }
+
+   // Now upgrade everything
+   if (pkgAllUpgrade(Cache) == false)
+   {
+      ShowBroken(c1out,Cache,false);
+      return _error->Error("Internal Error, problem resolver broke stuff");
+   }
+
+   ConfirmChanges(Cache, StateGuard);
+   
+   return true;
+}
+									/*}}}*/
+// DoClean - Remove download archives					/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool DoClean(CommandLine &CmdL)
+{
+   if (CheckHelp(CmdL,0) == true)
+      return true;
+
+   if (_config->FindB("APT::Get::Simulate") == true)
+   {
+      cout << "Del " << _config->FindDir("Dir::Cache::archives") << "* " <<
+	 _config->FindDir("Dir::Cache::archives") << "partial/*" << endl;
+      return true;
+   }
+   
+   // Lock the archive directory
+   FileFd Lock;
+   if (_config->FindB("Debug::NoLocking",false) == false)
+   {
+      Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
+      if (_error->PendingError() == true)
+	 return _error->Error(_("Unable to lock the download directory"));
+   }
+   
+   pkgAcquire Fetcher;
+   Fetcher.Clean(_config->FindDir("Dir::Cache::archives"));
+   Fetcher.Clean(_config->FindDir("Dir::Cache::archives") + "partial/");
+   return true;
+}
+									/*}}}*/
+// DoAutoClean - Smartly remove downloaded archives			/*{{{*/
+// ---------------------------------------------------------------------
+/* This is similar to clean but it only purges things that cannot be 
+   downloaded, that is old versions of cached packages. */
+class LogCleaner : public pkgArchiveCleaner
+{
+   protected:
+   virtual void Erase(const char *File,string Pkg,string Ver,struct stat &St) 
+   {
+      c1out << "Del " << Pkg << " " << Ver << " [" << SizeToStr(St.st_size) << "B]" << endl;
+      
+      if (_config->FindB("APT::Get::Simulate") == false)
+	 unlink(File);      
+   };
+};
+
+bool DoAutoClean(CommandLine &CmdL)
+{
+   if (CheckHelp(CmdL,0) == true)
+      return true;
+
+   // Lock the archive directory
+   FileFd Lock;
+   if (_config->FindB("Debug::NoLocking",false) == false)
+   {
+      Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
+      if (_error->PendingError() == true)
+	 return _error->Error(_("Unable to lock the download directory"));
+   }
+   
+   CacheFile &Cache = *GCache;
+#if 0
+   if (Cache.Open() == false)
+      return false;
+#endif
+   
+   LogCleaner Cleaner;
+   
+   return Cleaner.Go(_config->FindDir("Dir::Cache::archives"),*Cache) &&
+      Cleaner.Go(_config->FindDir("Dir::Cache::archives") + "partial/",*Cache);
+}
+									/*}}}*/
+// DoCheck - Perform the check operation				/*{{{*/
+// ---------------------------------------------------------------------
+/* Opening automatically checks the system, this command is mostly used
+   for debugging */
+bool DoCheck(CommandLine &CmdL)
+{
+   if (CheckHelp(CmdL,0) == true)
+      return true;
+
+   CacheFile &Cache = *GCache;
+   AutoRestore StateGuard(Cache);
+
+   if (GCache->CheckDeps() == false)
+      return false;
+   
+   return true;
+}
+									/*}}}*/
+// DoBuildDep - Install/removes packages to satisfy build dependencies  /*{{{*/
+// ---------------------------------------------------------------------
+/* This function will look at the build depends list of the given source 
+   package and install the necessary packages to make it true, or fail. */
+bool DoBuildDep(CommandLine &CmdL)
+{
+   if (CheckHelp(CmdL) == true)
+      return true;
+
+   CacheFile &Cache = *GCache;
+   if (GCache->CanCommit() == false) {
+      _error->Error(_("You have no permissions for that"));
+      return false;
+   }
+   
+   AutoRestore StateGuard(Cache);
+   
+   if (GCache->CheckDeps() == false)
+      return false;
+
+   if (CmdL.FileSize() <= 1)
+      return _error->Error(_("Must specify at least one package to check builddeps for"));
+   
+   // Read the source list
+   pkgSourceList List;
+   if (List.ReadMainList() == false)
+      return _error->Error(_("The list of sources could not be read."));
+   
+   // Create the text record parsers
+   pkgRecords Recs(Cache);
+   pkgSrcRecords SrcRecs(List);
+   if (_error->PendingError() == true)
+      return false;
+
+   // Create the download object
+   AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));   
+   pkgAcquire Fetcher(&Stat);
+
+   unsigned J = 0;
+   for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++)
+   {
+      string Src;
+      pkgSrcRecords::Parser *Last = FindSrc(*I,Recs,SrcRecs,Src,*Cache);
+      if (Last == 0)
+	 return _error->Error(_("Unable to find a source package for %s"),Src.c_str());
+            
+      // Process the build-dependencies
+      vector<pkgSrcRecords::Parser::BuildDepRec> BuildDeps;
+      if (Last->BuildDepends(BuildDeps, _config->FindB("APT::Get::Arch-Only",false)) == false)
+      	return _error->Error(_("Unable to get build-dependency information for %s"),Src.c_str());
+   
+      // Also ensure that build-essential packages are present
+      Configuration::Item const *Opts = _config->Tree("APT::Build-Essential");
+      if (Opts) 
+	 Opts = Opts->Child;
+      for (; Opts; Opts = Opts->Next)
+      {
+	 if (Opts->Value.empty() == true)
+	    continue;
+
+         pkgSrcRecords::Parser::BuildDepRec rec;
+	 rec.Package = Opts->Value;
+	 rec.Type = pkgSrcRecords::Parser::BuildDependIndep;
+	 rec.Op = 0;
+	 BuildDeps.push_back(rec);
+      }
+
+      if (BuildDeps.size() == 0)
+      {
+	 ioprintf(c1out,_("%s has no build depends.\n"),Src.c_str());
+	 continue;
+      }
+      
+      // Install the requested packages
+      unsigned int ExpectedInst = 0;
+      vector <pkgSrcRecords::Parser::BuildDepRec>::iterator D;
+      pkgProblemResolver Fix(Cache);
+      bool skipAlternatives = false; // skip remaining alternatives in an or group
+      for (D = BuildDeps.begin(); D != BuildDeps.end(); D++)
+      {
+         bool hasAlternatives = (((*D).Op & pkgCache::Dep::Or) == pkgCache::Dep::Or);
+
+         if (skipAlternatives == true)
+         {
+            if (!hasAlternatives)
+               skipAlternatives = false; // end of or group
+            continue;
+         }
+
+         if ((*D).Type == pkgSrcRecords::Parser::BuildConflict ||
+	     (*D).Type == pkgSrcRecords::Parser::BuildConflictIndep)
+         {
+            pkgCache::PkgIterator Pkg = Cache->FindPkg((*D).Package);
+            // Build-conflicts on unknown packages are silently ignored
+            if (Pkg.end() == true)
+               continue;
+
+            pkgCache::VerIterator IV = (*Cache)[Pkg].InstVerIter(*Cache);
+
+            /* 
+             * Remove if we have an installed version that satisfies the 
+             * version criteria
+             */
+            if (IV.end() == false && 
+                Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
+               TryToInstall(Pkg,Cache,Fix,MODE_REMOVE,false,ExpectedInst);
+         }
+	 else // BuildDep || BuildDepIndep
+         {
+            if (_config->FindB("Debug::BuildDeps",false) == true)
+                 cout << "Looking for " << (*D).Package << "...\n";
+
+	    pkgCache::PkgIterator Pkg = Cache->FindPkg((*D).Package);
+
+	    // CNC:2003-11-21 - Try to handle unknown file deps.
+	    if (Pkg.end() == true && (*D).Package[0] == '/')
+	    {
+	       const char *File = (*D).Package.c_str();
+	       Pkg = (*Cache).PkgBegin();
+	       for (; Pkg.end() == false; Pkg++)
+	       {
+		  // Should we try on all versions?
+		  pkgCache::VerIterator Ver = (*Cache)[Pkg].CandidateVerIter(*Cache);
+		  if (Ver.end() == false)
+		  {
+		     pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList());
+		     if (Parse.HasFile(File))
+			break;
+		  }
+	       }
+	    }
+
+	    if (Pkg.end() == true)
+            {
+               if (_config->FindB("Debug::BuildDeps",false) == true)
+                    cout << " (not found)" << (*D).Package << endl;
+
+               if (hasAlternatives)
+                  continue;
+
+               return _error->Error(_("%s dependency for %s cannot be satisfied "
+                                      "because the package %s cannot be found"),
+                                    Last->BuildDepType((*D).Type),Src.c_str(),
+                                    (*D).Package.c_str());
+            }
+
+            /*
+             * if there are alternatives, we've already picked one, so skip
+             * the rest
+             *
+             * TODO: this means that if there's a build-dep on A|B and B is
+             * installed, we'll still try to install A; more importantly,
+             * if A is currently broken, we cannot go back and try B. To fix 
+             * this would require we do a Resolve cycle for each package we 
+             * add to the install list. Ugh
+             */
+                       
+	    /* 
+	     * If this is a virtual package, we need to check the list of
+	     * packages that provide it and see if any of those are
+	     * installed
+	     */
+            pkgCache::PrvIterator Prv = Pkg.ProvidesList();
+            for (; Prv.end() != true; Prv++)
+	    {
+               if (_config->FindB("Debug::BuildDeps",false) == true)
+                    cout << "  Checking provider " << Prv.OwnerPkg().Name() << endl;
+
+	       if ((*Cache)[Prv.OwnerPkg()].InstVerIter(*Cache).end() == false)
+	          break;
+            }
+            
+            // Get installed version and version we are going to install
+	    pkgCache::VerIterator IV = (*Cache)[Pkg].InstVerIter(*Cache);
+
+            if ((*D).Version[0] != '\0') {
+                 // Versioned dependency
+
+                 pkgCache::VerIterator CV = (*Cache)[Pkg].CandidateVerIter(*Cache);
+
+                 for (; CV.end() != true; CV++)
+                 {
+                      if (Cache->VS().CheckDep(CV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
+                           break;
+                 }
+                 if (CV.end() == true)
+		   if (hasAlternatives)
+		   {
+		      continue;
+		   }
+		   else
+		   {
+                      return _error->Error(_("%s dependency for %s cannot be satisfied "
+                                             "because no available versions of package %s "
+                                             "can satisfy version requirements"),
+                                           Last->BuildDepType((*D).Type),Src.c_str(),
+                                           (*D).Package.c_str());
+		   }
+            }
+            else
+            {
+               // Only consider virtual packages if there is no versioned dependency
+               if (Prv.end() == false)
+               {
+                  if (_config->FindB("Debug::BuildDeps",false) == true)
+                     cout << "  Is provided by installed package " << Prv.OwnerPkg().Name() << endl;
+                  skipAlternatives = hasAlternatives;
+                  continue;
+               }
+            }
+            if (IV.end() == false)
+            {
+               if (_config->FindB("Debug::BuildDeps",false) == true)
+                  cout << "  Is installed\n";
+
+               if (Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
+               {
+                  skipAlternatives = hasAlternatives;
+                  continue;
+               }
+
+               if (_config->FindB("Debug::BuildDeps",false) == true)
+                  cout << "    ...but the installed version doesn't meet the version requirement\n";
+
+               if (((*D).Op & pkgCache::Dep::LessEq) == pkgCache::Dep::LessEq)
+               {
+                  return _error->Error(_("Failed to satisfy %s dependency for %s: Installed package %s is too new"),
+                                       Last->BuildDepType((*D).Type),
+                                       Src.c_str(),
+                                       Pkg.Name());
+               }
+            }
+
+
+            if (_config->FindB("Debug::BuildDeps",false) == true)
+               cout << "  Trying to install " << (*D).Package << endl;
+
+            if (TryToInstall(Pkg,Cache,Fix,false,false,ExpectedInst) == true)
+            {
+               // We successfully installed something; skip remaining alternatives
+               skipAlternatives = hasAlternatives;
+               continue;
+            }
+            else if (hasAlternatives)
+            {
+               if (_config->FindB("Debug::BuildDeps",false) == true)
+                  cout << "  Unsatisfiable, trying alternatives\n";
+               continue;
+            }
+            else
+            {
+               return _error->Error(_("Failed to satisfy %s dependency for %s: %s"),
+                                    Last->BuildDepType((*D).Type),
+                                    Src.c_str(),
+                                    (*D).Package.c_str());
+            }
+	 }	       
+      }
+      
+      Fix.InstallProtect();
+      if (Fix.Resolve(true) == false)
+	 _error->Discard();
+      
+      // Now we check the state of the packages,
+      if (Cache->BrokenCount() != 0)
+	 return _error->Error(_("Some broken packages were found while trying to process build-dependencies for %s.\n"
+				"You might want to run `apt-get -f install' to correct these."),*I);
+   }
+  
+   ConfirmChanges(Cache, StateGuard);
+
+   return true;
+}
+									/*}}}*/
+// * - Scripting stuff.							/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool DoScript(CommandLine &CmdL)
+{
+   if (CheckHelp(CmdL) == true)
+      return true;
+
+   CacheFile &Cache = *GCache;
+   AutoRestore StateGuard(Cache);
+
+   for (const char **I = CmdL.FileList+1; *I != 0; I++)
+      _config->Set("Scripts::AptShell::Script::", *I);
+
+// CNC:2003-03-19
+#ifdef WITH_LUA
+   _lua->SetDepCache(Cache);
+   _lua->RunScripts("Scripts::AptShell::Script", false);
+   _lua->RunScripts("Scripts::AptGet::Script", true);
+   _lua->RunScripts("Scripts::AptCache::Script", true);
+   _lua->ResetCaches();
+#endif
+
+   _config->Clear("Scripts::AptShell::Script");
+
+   ConfirmChanges(Cache, StateGuard);
+
+   return true;
+}
+
+									/*}}}*/
+
+// --- Unchanged stuff from apt-cache.
+
+// LocalitySort - Sort a version list by package file locality		/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+int LocalityCompare(const void *a, const void *b)
+{
+   pkgCache::VerFile *A = *(pkgCache::VerFile **)a;
+   pkgCache::VerFile *B = *(pkgCache::VerFile **)b;
+   
+   if (A == 0 && B == 0)
+      return 0;
+   if (A == 0)
+      return 1;
+   if (B == 0)
+      return -1;
+   
+   if (A->File == B->File)
+      return A->Offset - B->Offset;
+   return A->File - B->File;
+}
+
+void LocalitySort(pkgCache::VerFile **begin,
+		  unsigned long Count,size_t Size)
+{   
+   qsort(begin,Count,Size,LocalityCompare);
+}
+									/*}}}*/
+
+// Depends - Print out a dependency tree				/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool Depends(CommandLine &CmdL)
+{
+   if (CheckHelp(CmdL) == true)
+      return true;
+
+   pkgCache &Cache = *GCache;
+   SPtrArray<unsigned> Colours = new unsigned[Cache.Head().PackageCount];
+   memset(Colours,0,sizeof(*Colours)*Cache.Head().PackageCount);
+   
+   for (const char **I = CmdL.FileList + 1; *I != 0; I++)
+   {
+      pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
+      if (Pkg.end() == true)
+      {
+	 _error->Warning(_("Unable to locate package %s"),*I);
+	 continue;
+      }
+      Colours[Pkg->ID] = 1;
+   }
+   
+   bool Recurse = _config->FindB("APT::Cache::RecurseDepends",false);
+   bool Installed = _config->FindB("APT::Cache::Installed",false);
+   bool DidSomething;
+   do
+   {
+      DidSomething = false;
+      for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
+      {
+	 if (Colours[Pkg->ID] != 1)
+	    continue;
+	 Colours[Pkg->ID] = 2;
+	 DidSomething = true;
+	 
+	 pkgCache::VerIterator Ver = Pkg.VersionList();
+	 if (Ver.end() == true)
+	 {
+	    cout << '<' << Pkg.Name() << '>' << endl;
+	    continue;
+	 }
+	 
+	 // CNC:2003-03-03
+	 cout << Pkg.Name() << "-" << Ver.VerStr() << endl;
+	 
+	 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
+	 {
+
+	    pkgCache::PkgIterator Trg = D.TargetPkg();
+
+	    if((Installed && Trg->CurrentVer != 0) || !Installed)
+	      {
+
+		if ((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or)
+		  cout << " |";
+		else
+		  cout << "  ";
+	    
+		// Show the package
+	        if (Trg->VersionList == 0)
+	           cout << D.DepType() << ": <" << Trg.Name() << ">" << endl;
+	        // CNC:2003-03-03
+	        else if (D.TargetVer() == 0)
+	           cout << D.DepType() << ": " << Trg.Name() << endl;
+	        else
+	           cout << D.DepType() << ": " << Trg.Name()
+		        << " " << D.CompType() << " " << D.TargetVer() << endl;
+	    
+		if (Recurse == true)
+		  Colours[D.TargetPkg()->ID]++;
+
+	      }
+	    
+	    // Display all solutions
+	    SPtrArray<pkgCache::Version *> List = D.AllTargets();
+	    pkgPrioSortList(Cache,List);
+	    for (pkgCache::Version **I = List; *I != 0; I++)
+	    {
+	       pkgCache::VerIterator V(Cache,*I);
+	       if (V != Cache.VerP + V.ParentPkg()->VersionList ||
+		   V->ParentPkg == D->Package)
+		  continue;
+	       // CNC:2003-03-03
+	       cout << "    " << V.ParentPkg().Name()
+		    << "-" << V.VerStr() << endl;
+	       
+	       if (Recurse == true)
+		  Colours[D.ParentPkg()->ID]++;
+	    }
+	 }
+      }      
+   }   
+   while (DidSomething == true);
+   
+   return true;
+}
+									/*}}}*/
+// RDepends - Print out a reverse dependency tree - mbc			/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool RDepends(CommandLine &CmdL)
+{
+   if (CheckHelp(CmdL) == true)
+      return true;
+
+   pkgCache &Cache = *GCache;
+   SPtrArray<unsigned> Colours = new unsigned[Cache.Head().PackageCount];
+   memset(Colours,0,sizeof(*Colours)*Cache.Head().PackageCount);
+   
+   for (const char **I = CmdL.FileList + 1; *I != 0; I++)
+   {
+      pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
+      if (Pkg.end() == true)
+      {
+	 _error->Warning(_("Unable to locate package %s"),*I);
+	 continue;
+      }
+      Colours[Pkg->ID] = 1;
+   }
+   
+   bool Recurse = _config->FindB("APT::Cache::RecurseDepends",false);
+   bool Installed = _config->FindB("APT::Cache::Installed",false);
+   bool DidSomething;
+   do
+   {
+      DidSomething = false;
+      for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
+      {
+	 if (Colours[Pkg->ID] != 1)
+	    continue;
+	 Colours[Pkg->ID] = 2;
+	 DidSomething = true;
+	 
+	 pkgCache::VerIterator Ver = Pkg.VersionList();
+	 if (Ver.end() == true)
+	 {
+	    cout << '<' << Pkg.Name() << '>' << endl;
+	    continue;
+	 }
+	 
+	 cout << Pkg.Name() << endl;
+	 
+	 cout << "Reverse Depends:" << endl;
+	 for (pkgCache::DepIterator D = Pkg.RevDependsList(); D.end() == false; D++)
+	 {	    
+	    // Show the package
+	    pkgCache::PkgIterator Trg = D.ParentPkg();
+
+	    if((Installed && Trg->CurrentVer != 0) || !Installed)
+	      {
+
+		if ((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or)
+		  cout << " |";
+		else
+		  cout << "  ";
+
+		if (Trg->VersionList == 0)
+		  cout << D.DepType() << ": <" << Trg.Name() << ">" << endl;
+		else
+		  cout << Trg.Name() << endl;
+
+		if (Recurse == true)
+		  Colours[D.ParentPkg()->ID]++;
+
+	      }
+	    
+	    // Display all solutions
+	    SPtrArray<pkgCache::Version *> List = D.AllTargets();
+	    pkgPrioSortList(Cache,List);
+	    for (pkgCache::Version **I = List; *I != 0; I++)
+	    {
+	       pkgCache::VerIterator V(Cache,*I);
+	       if (V != Cache.VerP + V.ParentPkg()->VersionList ||
+		   V->ParentPkg == D->Package)
+		  continue;
+	       cout << "    " << V.ParentPkg().Name() << endl;
+	       
+	       if (Recurse == true)
+		  Colours[D.ParentPkg()->ID]++;
+	    }
+	 }
+      }      
+   }   
+   while (DidSomething == true);
+   
+   return true;
+}
+
+									/*}}}*/
+// CNC:2003-02-19
+// WhatDepends - Print out a reverse dependency tree			/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool WhatDepends(CommandLine &CmdL)
+{
+   if (CheckHelp(CmdL) == true)
+      return true;
+
+   pkgCache &Cache = *GCache;
+   SPtrArray<unsigned> Colours = new unsigned[Cache.Head().PackageCount];
+   memset(Colours,0,sizeof(*Colours)*Cache.Head().PackageCount);
+   
+   for (const char **I = CmdL.FileList + 1; *I != 0; I++)
+   {
+      pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
+      if (Pkg.end() == true)
+      {
+	 _error->Warning(_("Unable to locate package %s"),*I);
+	 continue;
+      }
+      Colours[Pkg->ID] = 1;
+   }
+   
+   bool Recurse = _config->FindB("APT::Cache::RecurseDepends",false);
+   bool DidSomething;
+   do
+   {
+      DidSomething = false;
+      for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
+      {
+	 if (Colours[Pkg->ID] != 1)
+	    continue;
+	 Colours[Pkg->ID] = 2;
+	 DidSomething = true;
+	 
+	 pkgCache::VerIterator Ver = Pkg.VersionList();
+	 if (Ver.end() == true)
+	    cout << '<' << Pkg.Name() << '>' << endl;
+	 else
+	    cout << Pkg.Name() << "-" << Ver.VerStr() << endl;
+
+	 SPtrArray<unsigned> LocalColours = 
+		     new unsigned[Cache.Head().PackageCount];
+	 memset(LocalColours,0,sizeof(*LocalColours)*Cache.Head().PackageCount);
+	    
+	 // Display all dependencies directly on the package.
+	 for (pkgCache::DepIterator RD = Pkg.RevDependsList();
+	      RD.end() == false; RD++)
+	 {
+	    pkgCache::PkgIterator Parent = RD.ParentPkg();
+
+	    if (LocalColours[Parent->ID] == 1)
+	       continue;
+	    LocalColours[Parent->ID] = 1;
+	       
+	    if (Ver.end() == false && RD.TargetVer() &&
+	        Cache.VS->CheckDep(Ver.VerStr(),RD) == false)
+	       continue;
+
+	    if (Recurse == true && Colours[Parent->ID] == 0)
+	       Colours[Parent->ID] = 1;
+
+	    pkgCache::VerIterator ParentVer = Parent.VersionList();
+
+	    // Show the package
+	    cout << "  " << Parent.Name()
+		 << "-" << ParentVer.VerStr() << endl;
+
+	    // Display all dependencies from that package that relate
+	    // to the queried package.
+	    for (pkgCache::DepIterator D = ParentVer.DependsList();
+	         D.end() == false; D++)
+	    {
+	       // If this is a virtual package, there's no provides.
+	       if (Ver.end() == true) {
+		  // If it's not the same package, and there's no provides
+		  // skip that package.
+		  if (D.TargetPkg() != Pkg)
+		     continue;
+	       } else if (D.TargetPkg() != Pkg ||
+			  Cache.VS->CheckDep(Ver.VerStr(),D) == false) {
+		  // Oops. Either it's not the same package, or the
+		  // version didn't match. Check virtual provides from
+		  // the queried package version and verify if this
+		  // dependency matches one of those.
+		  bool Hit = false;
+		  for (pkgCache::PrvIterator Prv = Ver.ProvidesList();
+		       Prv.end() == false; Prv++) {
+		     if (Prv.ParentPkg() == D.TargetPkg() &&
+			 (Prv.ParentPkg()->VersionList == 0 ||
+			  Cache.VS->CheckDep(Prv.ProvideVersion(),D)==false)) {
+			Hit = true;
+			break;
+		     }
+		  }
+		  if (Hit == false)
+		     continue;
+	       }
+
+	       // Bingo!
+	       pkgCache::PkgIterator Trg = D.TargetPkg();
+	       if (Trg->VersionList == 0)
+		  cout << "    " << D.DepType()
+				 << ": <" << Trg.Name() << ">" << endl;
+	       else if (D.TargetVer() == 0)
+		  cout << "    " << D.DepType()
+				 << ": " << Trg.Name() << endl;
+	       else
+		  cout << "    " << D.DepType()
+				 << ": " << Trg.Name()
+				 << " " << D.CompType() << " "
+				 << D.TargetVer() << endl;
+
+	       // Display all solutions
+	       SPtrArray<pkgCache::Version *> List = D.AllTargets();
+	       pkgPrioSortList(Cache,List);
+	       for (pkgCache::Version **I = List; *I != 0; I++)
+	       {
+		  pkgCache::VerIterator V(Cache,*I);
+		  if (V != Cache.VerP + V.ParentPkg()->VersionList ||
+		      V->ParentPkg == D->Package)
+		     continue;
+		  cout << "      " << V.ParentPkg().Name()
+		       << "-" << V.VerStr() << endl;
+		  
+		  if (Recurse == true)
+		     Colours[D.ParentPkg()->ID]++;
+	       }
+	    }
+	 }
+
+	 // Is this a virtual package the user queried directly?
+	 if (Ver.end())
+	    continue;
+
+	 // Display all dependencies on virtual provides, which were not
+	 // yet shown in the step above.
+	 for (pkgCache::PrvIterator RDPrv = Ver.ProvidesList();
+	      RDPrv.end() == false; RDPrv++) {
+	    for (pkgCache::DepIterator RD = RDPrv.ParentPkg().RevDependsList();
+	         RD.end() == false; RD++)
+	    {
+	       pkgCache::PkgIterator Parent = RD.ParentPkg();
+
+	       if (LocalColours[Parent->ID] == 1)
+		  continue;
+	       LocalColours[Parent->ID] = 1;
+		  
+	       if (Ver.end() == false &&
+		   Cache.VS->CheckDep(Ver.VerStr(),RD) == false)
+		  continue;
+
+	       if (Recurse == true && Colours[Parent->ID] == 0)
+		  Colours[Parent->ID] = 1;
+
+	       pkgCache::VerIterator ParentVer = Parent.VersionList();
+
+	       // Show the package
+	       cout << "  " << Parent.Name()
+		    << "-" << ParentVer.VerStr() << endl;
+
+	       for (pkgCache::DepIterator D = ParentVer.DependsList();
+		    D.end() == false; D++)
+	       {
+		  // Go on if it's the same package and version or
+		  // if it's the same package and has no versions
+		  // (a virtual package).
+		  if (D.TargetPkg() != RDPrv.ParentPkg() ||
+		      (RDPrv.ProvideVersion() != 0 &&
+		       Cache.VS->CheckDep(RDPrv.ProvideVersion(),D) == false))
+		     continue;
+
+		  // Bingo!
+		  pkgCache::PkgIterator Trg = D.TargetPkg();
+		  if (Trg->VersionList == 0)
+		     cout << "    " << D.DepType()
+				    << ": <" << Trg.Name() << ">" << endl;
+		  else if (D.TargetVer() == 0)
+		     cout << "    " << D.DepType()
+				    << ": " << Trg.Name() << endl;
+		  else
+		     cout << "    " << D.DepType()
+				    << ": " << Trg.Name()
+				    << " " << D.CompType() << " "
+				    << D.TargetVer() << endl;
+
+		  // Display all solutions
+		  SPtrArray<pkgCache::Version *> List = D.AllTargets();
+		  pkgPrioSortList(Cache,List);
+		  for (pkgCache::Version **I = List; *I != 0; I++)
+		  {
+		     pkgCache::VerIterator V(Cache,*I);
+		     if (V != Cache.VerP + V.ParentPkg()->VersionList ||
+			 V->ParentPkg == D->Package)
+			continue;
+		     cout << "      " << V.ParentPkg().Name()
+			  << "-" << V.VerStr() << endl;
+		     
+		     if (Recurse == true)
+			Colours[D.ParentPkg()->ID]++;
+		  }
+	       }
+	    }
+	 }
+      } 
+   }
+   while (DidSomething == true);
+   
+   return true;
+}
+									/*}}}*/
+// UnMet - Show unmet dependencies					/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool UnMet(CommandLine &CmdL)
+{
+   if (CheckHelp(CmdL,0) == true)
+      return true;
+
+   pkgCache &Cache = *GCache;
+   bool Important = _config->FindB("APT::Cache::Important",false);
+   
+   for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
+   {
+      for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
+      {
+	 bool Header = false;
+	 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false;)
+	 {
+	    // Collect or groups
+	    pkgCache::DepIterator Start;
+	    pkgCache::DepIterator End;
+	    D.GlobOr(Start,End);
+	    
+	    // Skip conflicts and replaces
+	    if (End->Type != pkgCache::Dep::PreDepends &&
+		End->Type != pkgCache::Dep::Depends && 
+		End->Type != pkgCache::Dep::Suggests &&
+		End->Type != pkgCache::Dep::Recommends)
+	       continue;
+
+	    // Important deps only
+	    if (Important == true)
+	       if (End->Type != pkgCache::Dep::PreDepends &&
+		   End->Type != pkgCache::Dep::Depends)
+		  continue;
+	    
+	    // Verify the or group
+	    bool OK = false;
+	    pkgCache::DepIterator RealStart = Start;
+	    do
+	    {
+	       // See if this dep is Ok
+	       pkgCache::Version **VList = Start.AllTargets();
+	       if (*VList != 0)
+	       {
+		  OK = true;
+		  delete [] VList;
+		  break;
+	       }
+	       delete [] VList;
+	       
+	       if (Start == End)
+		  break;
+	       Start++;
+	    }
+	    while (1);
+
+	    // The group is OK
+	    if (OK == true)
+	       continue;
+	    
+	    // Oops, it failed..
+	    if (Header == false)
+	       ioprintf(cout,_("Package %s version %s has an unmet dep:\n"),
+			P.Name(),V.VerStr());
+	    Header = true;
+	    
+	    // Print out the dep type
+	    cout << " " << End.DepType() << ": ";
+
+	    // Show the group
+	    Start = RealStart;
+	    do
+	    {
+	       cout << Start.TargetPkg().Name();
+	       if (Start.TargetVer() != 0)
+		  cout << " (" << Start.CompType() << " " << Start.TargetVer() <<
+		  ")";
+	       if (Start == End)
+		  break;
+	       cout << " | ";
+	       Start++;
+	    }
+	    while (1);
+	    
+	    cout << endl;
+	 }	 
+      }
+   }   
+   return true;
+}
+									/*}}}*/
+// DumpPackage - Show a dump of a package record			/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool DumpPackage(CommandLine &CmdL)
+{   
+   if (CheckHelp(CmdL) == true)
+      return true;
+
+   pkgCache &Cache = *GCache;
+   for (const char **I = CmdL.FileList + 1; *I != 0; I++)
+   {
+      pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
+      if (Pkg.end() == true)
+      {
+	 _error->Warning(_("Unable to locate package %s"),*I);
+	 continue;
+      }
+
+      cout << "Package: " << Pkg.Name() << endl;
+      cout << "Versions: " << endl;
+      for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
+      {
+	 cout << Cur.VerStr();
+	 for (pkgCache::VerFileIterator Vf = Cur.FileList(); Vf.end() == false; Vf++)
+	    cout << "(" << Vf.File().FileName() << ")";
+	 cout << endl;
+      }
+      
+      cout << endl;
+      
+      cout << "Reverse Depends: " << endl;
+      for (pkgCache::DepIterator D = Pkg.RevDependsList(); D.end() != true; D++)
+      {
+	 cout << "  " << D.ParentPkg().Name() << ',' << D.TargetPkg().Name();
+	 if (D->Version != 0)
+	    cout << ' ' << DeNull(D.TargetVer()) << endl;
+	 else
+	    cout << endl;
+      }
+      
+      cout << "Dependencies: " << endl;
+      for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
+      {
+	 cout << Cur.VerStr() << " - ";
+	 for (pkgCache::DepIterator Dep = Cur.DependsList(); Dep.end() != true; Dep++)
+	    cout << Dep.TargetPkg().Name() << " (" << (int)Dep->CompareOp << " " << DeNull(Dep.TargetVer()) << ") ";
+	 cout << endl;
+      }      
+
+      cout << "Provides: " << endl;
+      for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
+      {
+	 cout << Cur.VerStr() << " - ";
+	 for (pkgCache::PrvIterator Prv = Cur.ProvidesList(); Prv.end() != true; Prv++)
+	    cout << Prv.ParentPkg().Name() << " ";
+	 cout << endl;
+      }
+      cout << "Reverse Provides: " << endl;
+      for (pkgCache::PrvIterator Prv = Pkg.ProvidesList(); Prv.end() != true; Prv++)
+	 cout << Prv.OwnerPkg().Name() << " " << Prv.OwnerVer().VerStr() << endl;            
+   }
+
+   return true;
+}
+									/*}}}*/
+// DisplayRecord - Displays the complete record for the package		/*{{{*/
+// ---------------------------------------------------------------------
+/* This displays the package record from the proper package index file. 
+   It is not used by DumpAvail for performance reasons. */
+bool DisplayRecord(pkgCache::VerIterator V)
+{
+   // Find an appropriate file
+   pkgCache::VerFileIterator Vf = V.FileList();
+   for (; Vf.end() == false; Vf++)
+      if ((Vf.File()->Flags & pkgCache::Flag::NotSource) == 0)
+	 break;
+   if (Vf.end() == true)
+      Vf = V.FileList();
+      
+// CNC:2002-07-24
+#if HAVE_RPM
+   pkgRecords Recs(*GCache);
+   pkgRecords::Parser &P = Recs.Lookup(Vf);
+   const char *Start;
+   const char *End;
+   P.GetRec(Start,End);
+   fwrite(Start,End-Start,1,stdout);
+   putc('\n',stdout);
+#else
+   // Check and load the package list file
+   pkgCache::PkgFileIterator I = Vf.File();
+   if (I.IsOk() == false)
+      return _error->Error(_("Package file %s is out of sync."),I.FileName());
+   
+   FileFd PkgF(I.FileName(),FileFd::ReadOnly);
+   if (_error->PendingError() == true)
+      return false;
+   
+   // Read the record and then write it out again.
+   unsigned char *Buffer = new unsigned char[((pkgCache*)GCache)->HeaderP->MaxVerFileSize+1];
+   Buffer[V.FileList()->Size] = '\n';
+   if (PkgF.Seek(V.FileList()->Offset) == false ||
+       PkgF.Read(Buffer,V.FileList()->Size) == false ||
+       fwrite(Buffer,1,V.FileList()->Size+1,stdout) < V.FileList()->Size+1)
+   {
+      delete [] Buffer;
+      return false;
+   }
+   
+   delete [] Buffer;
+#endif
+
+   return true;
+}
+									/*}}}*/
+// Search - Perform a search						/*{{{*/
+// ---------------------------------------------------------------------
+/* This searches the package names and pacakge descriptions for a pattern */
+struct ExVerFile
+{
+   pkgCache::VerFile *Vf;
+   bool NameMatch;
+};
+
+bool Search(CommandLine &CmdL)
+{
+   if (CheckHelp(CmdL) == true)
+      return true;
+
+   pkgCache &Cache = *GCache;
+   bool ShowFull = _config->FindB("APT::Cache::ShowFull",false);
+   bool NamesOnly = _config->FindB("APT::Cache::NamesOnly",false);
+   unsigned NumPatterns = CmdL.FileSize() -1;
+   
+   pkgDepCache::Policy Plcy;
+   
+   // Make sure there is at least one argument
+   if (NumPatterns < 1)
+      return _error->Error(_("You must give exactly one pattern"));
+   
+   // Compile the regex pattern
+   regex_t *Patterns = new regex_t[NumPatterns];
+   memset(Patterns,0,sizeof(*Patterns)*NumPatterns);
+   for (unsigned I = 0; I != NumPatterns; I++)
+   {
+      if (regcomp(&Patterns[I],CmdL.FileList[I+1],REG_EXTENDED | REG_ICASE | 
+		  REG_NOSUB) != 0)
+      {
+	 for (; I != 0; I--)
+	    regfree(&Patterns[I]);
+	 return _error->Error("Regex compilation error");
+      }      
+   }
+   
+   // Create the text record parser
+   pkgRecords Recs(Cache);
+   if (_error->PendingError() == true)
+   {
+      for (unsigned I = 0; I != NumPatterns; I++)
+	 regfree(&Patterns[I]);
+      return false;
+   }
+   
+   ExVerFile *VFList = new ExVerFile[Cache.HeaderP->PackageCount+1];
+   memset(VFList,0,sizeof(*VFList)*Cache.HeaderP->PackageCount+1);
+
+   // Map versions that we want to write out onto the VerList array.
+   for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
+   {
+      VFList[P->ID].NameMatch = NumPatterns != 0;
+      for (unsigned I = 0; I != NumPatterns; I++)
+      {
+	 if (regexec(&Patterns[I],P.Name(),0,0,0) == 0)
+	    VFList[P->ID].NameMatch &= true;
+	 else
+	    VFList[P->ID].NameMatch = false;
+      }
+        
+      // Doing names only, drop any that dont match..
+      if (NamesOnly == true && VFList[P->ID].NameMatch == false)
+	 continue;
+	 
+      // Find the proper version to use. 
+      pkgCache::VerIterator V = Plcy.GetCandidateVer(P);
+      if (V.end() == false)
+	 VFList[P->ID].Vf = V.FileList();
+   }
+      
+   // Include all the packages that provide matching names too
+   for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
+   {
+      if (VFList[P->ID].NameMatch == false)
+	 continue;
+
+      for (pkgCache::PrvIterator Prv = P.ProvidesList() ; Prv.end() == false; Prv++)
+      {
+	 pkgCache::VerIterator V = Plcy.GetCandidateVer(Prv.OwnerPkg());
+	 if (V.end() == false)
+	 {
+	    VFList[Prv.OwnerPkg()->ID].Vf = V.FileList();
+	    VFList[Prv.OwnerPkg()->ID].NameMatch = true;
+	 }
+      }
+   }
+
+   LocalitySort(&VFList->Vf,Cache.HeaderP->PackageCount,sizeof(*VFList));
+
+   // Iterate over all the version records and check them
+   for (ExVerFile *J = VFList; J->Vf != 0; J++)
+   {
+      pkgRecords::Parser &P = Recs.Lookup(pkgCache::VerFileIterator(Cache,J->Vf));
+
+      bool Match = true;
+      if (J->NameMatch == false)
+      {
+	 string LongDesc = P.LongDesc();
+	 Match = NumPatterns != 0;
+	 for (unsigned I = 0; I != NumPatterns; I++)
+	 {
+	    if (regexec(&Patterns[I],LongDesc.c_str(),0,0,0) == 0)
+	       Match &= true;
+	    else
+	       Match = false;
+	 }
+      }
+      
+      if (Match == true)
+      {
+	 if (ShowFull == true)
+	 {
+	    const char *Start;
+	    const char *End;
+	    P.GetRec(Start,End);
+	    fwrite(Start,End-Start,1,stdout);
+	    putc('\n',stdout);
+	 }	 
+	 else
+	    printf("%s - %s\n",P.Name().c_str(),P.ShortDesc().c_str());
+      }
+   }
+   
+   delete [] VFList;
+   for (unsigned I = 0; I != NumPatterns; I++)
+      regfree(&Patterns[I]);
+   if (ferror(stdout))
+       return _error->Error("Write to stdout failed");
+   return true;
+}
+
+// DoList - List packages.	 					/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool DoList(CommandLine &CmdL)
+{
+   if (CheckHelp(CmdL) == true)
+      return true;
+
+   CacheFile &Cache = *GCache;
+
+   bool MatchAll = (CmdL.FileSize() == 1);
+   bool ShowUpgradable = _config->FindB("APT::Cache::ShowUpgradable", false);
+   bool ShowInstalled = _config->FindB("APT::Cache::ShowInstalled", false);
+
+   const char **PatternList = &CmdL.FileList[1];
+   int NumPatterns = CmdL.FileSize()-1;
+
+   bool ShowVersion = _config->FindB("APT::Cache::ShowVersion", false);
+   bool ShowSummary = _config->FindB("APT::Cache::ShowSummary", false);
+
+   const char *PkgName;
+   int Matches[Cache->Head().PackageCount];
+   int NumMatches = 0;
+   int Len, NameMaxLen = 0, VerMaxLen = 0;
+   bool Matched;
+   for (unsigned int J = 0; J < Cache->Head().PackageCount; J++)
+   {
+      Matched = false;
+      pkgCache::PkgIterator Pkg(Cache,Cache.List[J]);
+      if (Pkg->VersionList == 0)
+	 continue;
+      if (ShowInstalled && Pkg->CurrentVer == 0)
+	 continue;
+      if (ShowUpgradable &&
+	  (Pkg->CurrentVer == 0 || Cache[Pkg].Upgradable() == false))
+	 continue;
+      PkgName = Pkg.Name();
+      if (MatchAll == true)
+	 Matched = true;
+      else for (int i=0; i != NumPatterns; i++) {
+	 if (fnmatch(PatternList[i], PkgName, 0) == 0) {
+	    Matched = true;
+	    break;
+	 }
+      }
+      if (Matched == true) {
+	 Matches[NumMatches++] = J;
+	 Len = strlen(PkgName);
+	 if (Len > NameMaxLen)
+	    NameMaxLen = Len;
+	 if (ShowVersion == true && Pkg->CurrentVer != 0) {
+	    Len = strlen(Pkg.CurrentVer().VerStr());
+	    if (Len > VerMaxLen)
+	       VerMaxLen = Len;
+	 }
+      }
+   }
+
+   if (NumMatches == 0)
+      return true;
+
+   if (ShowVersion == true) {
+      const char *NameLabel = _("Name");
+      const char *InstalledLabel = _("Installed");
+      const char *CandidateLabel = _("Candidate");
+      int NameLen = strlen(NameLabel);
+      int InstalledLen = strlen(InstalledLabel);
+      int CandidateLen = strlen(CandidateLabel);
+
+      unsigned int FirstColumn = NameMaxLen+2;
+      if (FirstColumn < NameLen+2)
+	 FirstColumn = NameLen+2;
+
+      unsigned int SecondColumn = VerMaxLen+2;
+      if (SecondColumn < InstalledLen+2)
+	 SecondColumn = InstalledLen+2;
+
+      char BlankFirst[FirstColumn+1];
+      memset(BlankFirst,' ',FirstColumn);
+      BlankFirst[FirstColumn] = 0;
+
+      char BlankSecond[SecondColumn+1];
+      memset(BlankSecond,' ',SecondColumn);
+      BlankSecond[SecondColumn] = 0;
+
+      char Bar[ScreenWidth+1];
+      memset(Bar, '-', ScreenWidth);
+      Bar[ScreenWidth] = 0;
+
+      c2out << NameLabel << BlankFirst+NameLen
+	    << InstalledLabel << BlankSecond+InstalledLen
+	    << CandidateLabel << endl;
+      c2out << Bar+(ScreenWidth-NameLen) << BlankFirst+NameLen
+	    << Bar+(ScreenWidth-InstalledLen) << BlankSecond+InstalledLen
+	    << Bar+(ScreenWidth-CandidateLen) << endl;
+
+      const char *Str;
+      int StrLen;
+      for (unsigned int K = 0; K != NumMatches; K++) {
+	 pkgCache::PkgIterator Pkg(Cache,Cache.List[Matches[K]]);
+	 Str = Pkg.Name();
+	 StrLen = strlen(Str);
+	 c2out << Str << BlankFirst+StrLen;
+	 if (Pkg->CurrentVer != 0) {
+	    Str = Pkg.CurrentVer().VerStr();
+	    StrLen = strlen(Str);
+	    if (Len < SecondColumn-1)
+	       c2out << Str << BlankSecond+StrLen;
+	    else
+	       c2out << Str << " ";
+	 } else {
+	    c2out << "-" << BlankSecond+1;
+	 }
+	 Str = "-";
+	 if (Cache[Pkg].CandidateVer != 0) {
+	    Str = Cache[Pkg].CandidateVerIter(Cache).VerStr();
+	    if (Pkg->CurrentVer != 0 &&
+	        strcmp(Str, Pkg.CurrentVer().VerStr()) == 0)
+	       Str = "-";
+	 }
+	 c2out << Str << endl;
+      }
+   } else if (ShowSummary == true) {
+      pkgRecords Recs(Cache);
+      if (_error->PendingError() == true)
+	 return false;
+      for (unsigned int K = 0; K != NumMatches; K++) {
+	 pkgCache::PkgIterator Pkg(Cache,Cache.List[Matches[K]]);
+	 pkgRecords::Parser &Parse = Recs.Lookup(Pkg.VersionList().FileList());
+	 c2out << Pkg.Name() << " - " << Parse.ShortDesc() << endl;
+      }
+   } else {
+      unsigned int PerLine = ScreenWidth/(NameMaxLen+2);
+      if (PerLine == 0) PerLine = 1;
+      unsigned int ColumnLen = ScreenWidth/PerLine;
+      unsigned int NumLines = (NumMatches+PerLine-1)/PerLine;
+      char Blank[ColumnLen+1];
+      memset(Blank,' ',ColumnLen);
+      Blank[ColumnLen] = 0;
+
+      const char *Str;
+      int StrLen;
+      unsigned int K;
+      for (unsigned int Line = 0; Line != NumLines; Line++) {
+	 for (unsigned int Entry = 0; Entry != PerLine; Entry++) {
+	    K = Line+(Entry*NumLines);
+	    if (K >= NumMatches)
+	       break;
+	    pkgCache::PkgIterator Pkg(Cache,Cache.List[Matches[K]]);
+	    Str = Pkg.Name();
+	    StrLen = strlen(Str);
+	    if (Len < ColumnLen-1)
+	       c2out << Str << Blank+StrLen;
+	    else
+	       c2out << Str << " ";
+	 }
+	 c2out << endl;
+      }
+   }
+   
+   return true;
+}
+									/*}}}*/
+// ShowPackage - Dump the package record to the screen			/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool ShowPackage(CommandLine &CmdL)
+{   
+   if (CheckHelp(CmdL) == true)
+      return true;
+
+   pkgCache &Cache = *GCache;
+   pkgDepCache::Policy Plcy;
+
+   unsigned found = 0;
+   
+   for (const char **I = CmdL.FileList + 1; *I != 0; I++)
+   {
+      pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
+      if (Pkg.end() == true)
+      {
+	 _error->Warning(_("Unable to locate package %s"),*I);
+	 continue;
+      }
+
+      ++found;
+
+      // Find the proper version to use.
+      if (_config->FindB("APT::Cache::AllVersions","true") == true)
+      {
+	 pkgCache::VerIterator V;
+	 for (V = Pkg.VersionList(); V.end() == false; V++)
+	 {
+	    if (DisplayRecord(V) == false)
+	       return false;
+	 }
+      }
+      else
+      {
+	 pkgCache::VerIterator V = Plcy.GetCandidateVer(Pkg);
+	 if (V.end() == true || V.FileList().end() == true)
+	    continue;
+	 if (DisplayRecord(V) == false)
+	    return false;
+      }      
+   }
+
+   if (found > 0)
+        return true;
+   return _error->Error(_("No packages found"));
+}
+									/*}}}*/
+// --- End of stuff from apt-cache.
+
+
+// ShowHelp - Show a help screen					/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool ShowHelp(CommandLine &CmdL)
+{
+   if (CheckHelp(CmdL) == true)
+      return true;
+
+   if (CmdL.FileSize() > 1) {
+      CommandHelp(CmdL.FileList[1]);
+      return true;
+   }
+
+   ioprintf(cout,_("%s %s for %s %s compiled on %s %s\n"),PACKAGE,VERSION,
+	    COMMON_OS,COMMON_CPU,__DATE__,__TIME__);
+	    
+   if (_config->FindB("version") == true)
+   {
+      cout << _("Supported Modules:") << endl;
+      
+      for (unsigned I = 0; I != pkgVersioningSystem::GlobalListLen; I++)
+      {
+	 pkgVersioningSystem *VS = pkgVersioningSystem::GlobalList[I];
+	 if (_system != 0 && _system->VS == VS)
+	    cout << '*';
+	 else
+	    cout << ' ';
+	 cout << "Ver: " << VS->Label << endl;
+	 
+	 /* Print out all the packaging systems that will work with 
+	    this VS */
+	 for (unsigned J = 0; J != pkgSystem::GlobalListLen; J++)
+	 {
+	    pkgSystem *Sys = pkgSystem::GlobalList[J];
+	    if (_system == Sys)
+	       cout << '*';
+	    else
+	       cout << ' ';
+	    if (Sys->VS->TestCompatibility(*VS) == true)
+	       cout << "Pkg:  " << Sys->Label << " (Priority " << Sys->Score(*_config) << ")" << endl;
+	 }
+      }
+      
+      for (unsigned I = 0; I != pkgSourceList::Type::GlobalListLen; I++)
+      {
+	 pkgSourceList::Type *Type = pkgSourceList::Type::GlobalList[I];
+	 cout << " S.L: '" << Type->Name << "' " << Type->Label << endl;
+      }      
+      
+      for (unsigned I = 0; I != pkgIndexFile::Type::GlobalListLen; I++)
+      {
+	 pkgIndexFile::Type *Type = pkgIndexFile::Type::GlobalList[I];
+	 cout << " Idx: " << Type->Label << endl;
+      }      
+      
+      return true;
+   }
+   
+   cout << 
+    _("\n"
+      "Main commands:\n"
+      "   status - Show the current selections\n"
+      "   install - Install new packages\n"
+      "   remove - Remove packages\n"
+      "   keep - Keep packages\n"
+      "   upgrade - Perform a global upgrade\n"
+      "   dist-upgrade - Perform a globla distribution upgrade\n"
+      "   build-dep - Install build-dependencies for source packages\n"
+//      "   dselect-upgrade - Follow dselect selections\n"
+      "   update - Retrieve new lists of packages\n"
+      "   commit - Apply the changes in the system\n"
+      "   quit - Leave the APT shell\n"
+      "\n"
+      "Auxiliar commands:\n"
+      "   show - Show a readable record for the package\n"
+      "   showpkg - Show some general information for a single package\n"
+      "   list/ls - List packages\n"
+      "   search - Search the package list for a regex pattern\n"
+      "   script - Run scripts.\n"
+      "   depends - Show raw dependency information for a package\n"
+      "   whatdepends - Show raw dependency information on a package\n"
+      // "   rdepends - Show reverse dependency information for a package\n"
+      "   check - Verify that there are no broken dependencies\n"
+      "   unmet - Show unmet dependencies\n"
+      "   clean - Erase downloaded archive files\n"
+      "   autoclean - Erase old downloaded archive files\n"
+      "\n"
+      "For more information type \"help <cmd>\" or \"<cmd> [-h|--help]\".\n"
+      "\n"
+      "                       This APT has Super Cow Powers.\n");
+   return true;
+}
+
+void CommandHelp(const char *Name)
+{
+   unsigned long Hash = 0;
+   for (const char *p=Name; *p; p++)
+      Hash = 5*Hash + *p;
+   switch (Hash%1000000) {
+      case 73823: // install
+	 c2out << _(
+	    "Usage: install [options] pkg1[=ver] [pkg2 ...]\n"
+	    "\n"
+	    "Try to mark the given packages for installation (new packages,\n"
+	    "upgrades or downgrades) changing other packages if necessary.\n"
+	    "\n"
+	    "Options:\n"
+	    "  -h  This help text.\n"
+	    "  -y  Assume Yes to all queries and do not prompt\n"
+	    "  -f  Attempt to continue if the integrity check fails\n"
+	    "  -m  Attempt to continue if archives are unlocatable\n"
+	    "  -D  When removing packages, remove dependencies as possible\n"
+	    "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
+	    "\n"
+	 );
+	 break;
+
+      case 436466: // remove
+	 c2out << _(
+	    "Usage: remove [options] pkg1 [pkg2 ...]\n"
+	    "\n"
+	    "Try to mark the given packages for deletion, changing other\n"
+	    "packages if necessary.\n"
+	    "\n"
+	    "Options:\n"
+	    "  -h  This help text.\n"
+	    "  -y  Assume Yes to all queries and do not prompt\n"
+	    "  -f  Attempt to continue if the integrity check fails\n"
+	    "  -m  Attempt to continue if archives are unlocatable\n"
+	    "  -D  When removing packages, remove dependencies as possible\n"
+	    "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
+	    "\n"
+	 );
+	 break;
+
+      case 16517: // keep
+	 c2out << _(
+	    "Usage: keep [options] pkg1 [pkg2 ...]\n"
+	    "\n"
+	    "Try to keep the given packages, currently marked for deletion\n"
+	    "or installation, in the system, changing other packages if\n"
+	    "necessary.\n"
+	    "\n"
+	    "Options:\n"
+	    "  -h  This help text.\n"
+	    "  -y  Assume Yes to all queries and do not prompt\n"
+	    "  -f  Attempt to continue if the integrity check fails\n"
+	    "  -m  Attempt to continue if archives are unlocatable\n"
+	    "  -D  When removing packages, remove dependencies as possible\n"
+	    "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
+	    "\n"
+	 );
+	 break;
+
+      case 259776: // upgrade
+	 c2out << _(
+	    "Usage: upgrade [options]\n"
+	    "\n"
+	    "Perform a global upgrade.\n"
+	    "\n"
+	    "Options:\n"
+	    "  -h  This help text.\n"
+	    "  -y  Assume Yes to all queries and do not prompt\n"
+	    "  -f  Attempt to continue if the integrity check fails\n"
+	    "  -m  Attempt to continue if archives are unlocatable\n"
+	    "  -D  When removing packages, remove dependencies as possible\n"
+	    "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
+	    "\n"
+	 );
+
+      case 900401: // dist-upgrade
+	 c2out << _(
+	    "Usage: dist-upgrade [options]\n"
+	    "\n"
+	    "Perform a global distribution upgrade.\n"
+	    "\n"
+	    "Options:\n"
+	    "  -h  This help text.\n"
+	    "  -y  Assume Yes to all queries and do not prompt\n"
+	    "  -f  Attempt to continue if the integrity check fails\n"
+	    "  -m  Attempt to continue if archives are unlocatable\n"
+	    "  -D  When removing packages, remove dependencies as possible\n"
+	    "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
+	    "\n"
+	 );
+
+      case 209563: // showpkg
+	 c2out << _(
+	    "Usage: showpkg [options] pkg1 [pkg2 ...]\n"
+	    "\n"
+	    "Show some general information for the given packages.\n"
+	    "\n"
+	    "Options:\n"
+	    "  -h  This help text.\n"
+	    "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
+	    "\n"
+	 );
+	 break;
+
+      case 17649: // show
+	 c2out << _(
+	    "Usage: show [options] pkg1 [pkg2 ...]\n"
+	    "\n"
+	    "Show a readable record for the given packages.\n"
+	    "\n"
+	    "Options:\n"
+	    "  -h  This help text.\n"
+	    "  -a  Show information about all versions.\n"
+	    "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
+	    "\n"
+	 );
+	 break;
+
+      case 964115: // depends
+	 c2out << _(
+	    "Usage: depends [options] pkg1 [pkg2 ...]\n"
+	    "\n"
+	    "Show dependency relations for the given packages.\n"
+	    "\n"
+	    "Options:\n"
+	    "  -h  This help text.\n"
+	    "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
+	    "\n"
+	 );
+	 break;
+
+      case 151615: // whatdepends
+	 c2out << _(
+	    "Usage: whatdepends [options] pkg1 [pkg2 ...]\n"
+	    "\n"
+	    "Show dependency relations on the given packages.\n"
+	    "\n"
+	    "Options:\n"
+	    "  -h  This help text.\n"
+	    "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
+	    "\n"
+	 );
+	 break;
+
+      case 90221: // unmet
+	 c2out << _(
+	    "Usage: unmet [options]\n"
+	    "\n"
+	    "Show unsolvable relations in the cache.\n"
+	    "\n"
+	    "Options:\n"
+	    "  -h  This help text.\n"
+	    "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
+	    "\n"
+	 );
+	 break;
+
+      case 438074: // search
+	 c2out << _(
+	    "Usage: search [options] <regex>\n"
+	    "\n"
+	    "Search for the given regular expression in package names and\n"
+	    "descriptions.\n"
+	    "\n"
+	    "Options:\n"
+	    "  -h  This help text.\n"
+	    "  -n  Search only in package names.\n"
+	    "  -f  Show full records for found packages.\n"
+	    "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
+	    "\n"
+	 );
+	 break;
+
+      case 16816: // list
+      case 655: // ls
+	 c2out << _(
+	    "Usage: list/ls [options] [pattern ...]\n"
+	    "\n"
+	    "List packages matching the given patterns, or all packages if\n"
+	    "no pattern is given. Wildcards are accepted.\n"
+	    "\n"
+	    "Options:\n"
+	    "  -h  This help text.\n"
+	    "  -i  Show only installed packages.\n"
+	    "  -u  Show only installed packages that are upgradable.\n"
+	    "  -v  Show installed and candidate versions.\n"
+	    "  -s  Show summaries.\n"
+	    "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
+	    "\n"
+	 );
+	 break;
+
+      case 395741: // commit
+	 c2out << _(
+	    "Usage: commit [options]\n"
+	    "\n"
+	    "Apply the changes in the system.\n"
+	    "\n"
+	    "Options:\n"
+	    "  -h  This help text.\n"
+	    "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
+	    "\n"
+	 );
+	 break;
+
+      case 438801: // script
+	 c2out << _(
+	    "Usage: script [options] script1 [script2]\n"
+	    "\n"
+	    "Run the given scripts.\n"
+	    "\n"
+	    "Options:\n"
+	    "  -h  This help text.\n"
+	    "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
+	    "\n"
+	 );
+	 break;
+      default:
+	 _error->Error(_("No help for that"));
+   }
+}
+									/*}}}*/
+
+bool DoQuit(CommandLine &CmdL)
+{
+   _config->Set("quit", "true");
+   return true;
+}
+
+bool DoCommit(CommandLine &CmdL)
+{
+   if (CheckHelp(CmdL,0) == true)
+      return true;
+
+   if (GCache->CanCommit() == false) {
+      _error->Error(_("You have no permissions for that"));
+      return false;
+   }
+   return InstallPackages(*GCache,false);
+}
+
+bool DoStatus(CommandLine &CmdL)
+{
+   if (CheckHelp(CmdL,0) == true)
+      return true;
+
+   ShowChanges(*GCache);
+   return true;
+}
+
+// GetInitialize - Initialize things for apt-get			/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void GetInitialize()
+{
+   _config->Set("quiet",0);
+   _config->Set("help",false);
+   _config->Set("APT::Get::Download-Only",false);
+   _config->Set("APT::Get::Simulate",false);
+   _config->Set("APT::Get::Assume-Yes",false);
+   _config->Set("APT::Get::Fix-Broken",false);
+   _config->Set("APT::Get::Force-Yes",false);
+   _config->Set("APT::Get::APT::Get::No-List-Cleanup",true);
+}
+									/*}}}*/
+// SigWinch - Window size change signal handler				/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void SigWinch(int)
+{
+   // Riped from GNU ls
+#ifdef TIOCGWINSZ
+   struct winsize ws;
+  
+   if (ioctl(1, TIOCGWINSZ, &ws) != -1 && ws.ws_col >= 5)
+      ScreenWidth = ws.ws_col - 1;
+#endif
+}
+									/*}}}*/
+
+// ReadLine* - readline library stuff					/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+char *ReadLineCompCommands(const char *Text, int State)
+{
+   static char *Commands[] =  {"update", "upgrade", "install", "remove",
+	 "keep", "dist-upgrade", "dselect-upgrade", "build-dep", "clean",
+	 "autoclean", "check", "help", "commit", "exit", "quit", "status",
+	 "showpkg", "unmet", "search", "depends", "whatdepends", "rdepends",
+	 "show", "script", 0};
+   static int Last;
+   static int Len;
+   if (State == 0) {
+      Last = 0;
+      Len = strlen(Text);
+   }
+   const char *Cmd;
+   while ((Cmd = Commands[Last++])) {
+      if (strncmp(Cmd, Text, Len) == 0)
+	 return strdup(Cmd);
+   }
+   return NULL;
+}
+
+static int CompPackagesMode;
+
+char *ReadLineCompPackages(const char *Text, int State)
+{
+   CacheFile &Cache = *GCache;
+   static pkgCache::PkgIterator Pkg;
+   static int Len;
+   if (State == 0) {
+      Pkg = Cache->PkgBegin();
+      Len = strlen(Text);
+   } else {
+      Pkg++;
+   }
+   const char *Name;
+   for (; Pkg.end() == false; Pkg++) {
+      Name = Pkg.Name();
+      if (Pkg->VersionList == 0) {
+	 continue;
+      } else if (CompPackagesMode == MODE_REMOVE) {
+	 if (Pkg->CurrentVer == 0)
+	    continue;
+      } else if (CompPackagesMode == MODE_KEEP) {
+	 if (Cache[Pkg].Delete() == false && Cache[Pkg].Install() == false)
+	    continue;
+      }
+      if (strncmp(Name, Text, Len) == 0)
+	 return strdup(Name);
+   }
+   return NULL;
+}
+
+static const char *CompVersionName;
+
+char *ReadLineCompVersion(const char *Text, int State)
+{
+   CacheFile &Cache = *GCache;
+   static pkgCache::VerIterator Ver;
+   static int Len;
+   if (State == 0) {
+      pkgCache::PkgIterator Pkg = Cache->FindPkg(CompVersionName);
+      if (Pkg.end() == true)
+	 return NULL;
+      Ver = Pkg.VersionList();
+      Len = strlen(Text);
+   } else {
+      Ver++;
+   }
+   const char *Version;
+   for (; Ver.end() == false; Ver++) {
+      Version = Ver.VerStr();
+      if (strncmp(Version, Text, Len) == 0)
+	 return strdup(Version);
+   }
+   return NULL;
+}
+
+
+unsigned long ReadLineHashCmd(const char *Cmd, const char *CmdEnd)
+{
+   unsigned long Hash = 0;
+   for (; Cmd != CmdEnd; Cmd++)
+      Hash = 5*Hash + *Cmd;
+   return Hash;
+}
+   
+char **ReadLineCompletion(const char *Text, int Start, int End)
+{
+   char **Matches = (char **)NULL;
+   char *Cmd = rl_line_buffer;
+   int Pos = 0;
+   for (; *Cmd != 0 && isspace(*Cmd); Pos++, Cmd++);
+   rl_attempted_completion_over = 1;
+   if (Start == Pos)
+      Matches = rl_completion_matches(Text, ReadLineCompCommands);
+   else {
+      char *CmdEnd = Cmd;
+      while (!isspace(*CmdEnd)) CmdEnd++;
+      CompPackagesMode = -1;
+      switch (ReadLineHashCmd(Cmd,CmdEnd)) {
+	 case 2073823: // install
+	    if (*(rl_line_buffer+Start-1) == '=') {
+	       const char *NameEnd = rl_line_buffer+Start-1;
+	       const char *NameStart = NameEnd-1;
+	       while (!isspace(*NameStart)) NameStart--;
+	       if (++NameStart == NameEnd)
+		  return NULL;
+	       string PkgName(NameStart, NameEnd-NameStart);
+	       CompVersionName = PkgName.c_str();
+	       Matches = rl_completion_matches(Text, ReadLineCompVersion);
+	    } else {
+	       Matches = rl_completion_matches(Text, ReadLineCompPackages);
+	    }
+	    break;
+
+	 case 436466: // remove
+	    CompPackagesMode = MODE_REMOVE;
+	 case 16517: // keep
+	    if (CompPackagesMode == -1)
+	       CompPackagesMode = MODE_KEEP;
+	 case 2209563: // showpkg
+	 case 17649: // show
+	 case 16816: // list
+	 case 655: // ls
+	 case 1964115: // depends
+	 case 1414151615: // whatdepends
+	 case 10870365: // rdepends
+	    Matches = rl_completion_matches(Text, ReadLineCompPackages);
+	    break;
+
+	 default:
+	    break;
+      }
+   }
+   return Matches;
+}
+
+string ReadLineHistoryFile()
+{
+   string Path;
+   const char *Dir = getenv("HOME");
+   if (Dir != NULL) {
+      Path = Dir;
+      Path += "/.apt_history";
+   }
+   return Path;
+}
+
+void ReadLineInit()
+{
+   rl_readline_name = "APTShell";
+   rl_attempted_completion_function = ReadLineCompletion;
+   string History = ReadLineHistoryFile();
+   if (History.empty() == false)
+      read_history_range(History.c_str(), 0, -1);
+}
+
+void ReadLineFinish()
+{
+   string History = ReadLineHistoryFile();
+   if (History.empty() == false)
+      write_history(History.c_str());
+}
+									/*}}}*/
+
+CommandLine::Args *CommandArgs(const char *Name)
+{
+   static CommandLine::Args ChangeCacheArgs[] = {
+      {'h',"help","help",0},
+      {'q',"quiet","quiet",CommandLine::IntLevel},
+      {'q',"silent","quiet",CommandLine::IntLevel},
+      {'y',"yes","APT::Get::Assume-Yes",0},
+      {'y',"assume-yes","APT::Get::Assume-Yes",0},      
+      {'s',"simulate","APT::Get::Simulate",0},
+      {'s',"just-print","APT::Get::Simulate",0},
+      {'s',"recon","APT::Get::Simulate",0},
+      {'s',"dry-run","APT::Get::Simulate",0},
+      {'s',"no-act","APT::Get::Simulate",0},
+      {'f',"fix-broken","APT::Get::Fix-Broken",0},
+      {'D',"remove-deps","APT::Remove-Depends",0}, // CNC:2002-08-01
+      {'V',"verbose-versions","APT::Get::Show-Versions",0},
+      {'t',"target-release","APT::Default-Release",CommandLine::HasArg},
+      {'t',"default-release","APT::Default-Release",CommandLine::HasArg},
+      {0,"reinstall","APT::Get::ReInstall",0},
+      {0,"upgrade","APT::Get::upgrade",0},
+      {0,"force-yes","APT::Get::Force-Yes",0},
+      {0,"ignore-hold","APT::Ignore-Hold",0},      
+      {0,"purge","APT::Get::Purge",0},
+      {0,"remove","APT::Get::Remove",0},
+      {0,"arch-only","APT::Get::Arch-Only",0},
+      {'c',"config-file",0,CommandLine::ConfigFile},
+      {'o',"option",0,CommandLine::ArbItem},
+      {0,0,0,0}};
+
+   static CommandLine::Args CommitArgs[] = {
+      {'h',"help","help",0},
+      {'q',"quiet","quiet",CommandLine::IntLevel},
+      {'q',"silent","quiet",CommandLine::IntLevel},
+      {'y',"yes","APT::Get::Assume-Yes",0},
+      {'y',"assume-yes","APT::Get::Assume-Yes",0},      
+      {'d',"download-only","APT::Get::Download-Only",0},
+      {'s',"simulate","APT::Get::Simulate",0},
+      {'s',"just-print","APT::Get::Simulate",0},
+      {'s',"recon","APT::Get::Simulate",0},
+      {'s',"dry-run","APT::Get::Simulate",0},
+      {'s',"no-act","APT::Get::Simulate",0},
+      {'m',"ignore-missing","APT::Get::Fix-Missing",0},
+      {0,"trivial-only","APT::Get::Trivial-Only",0},
+      {0,"print-uris","APT::Get::Print-URIs",0},
+      {0,"force-yes","APT::Get::Force-Yes",0},
+      {0,"download","APT::Get::Download",0},
+      {0,"fix-missing","APT::Get::Fix-Missing",0},
+      {'c',"config-file",0,CommandLine::ConfigFile},
+      {'o',"option",0,CommandLine::ArbItem},
+      {0,0,0,0}};
+
+   static CommandLine::Args ShowArgs[] = {
+      {'h',"help","help",0},
+      {'a',"all-versions","APT::Cache::AllVersions",0},
+      {'n',"names-only","APT::Cache::NamesOnly",0},
+      {'f',"show-full","APT::Cache::ShowFull",0},
+      {'c',"config-file",0,CommandLine::ConfigFile},
+      {'o',"option",0,CommandLine::ArbItem},
+      {0,0,0,0}};
+
+   static CommandLine::Args SearchArgs[] = {
+      {'h',"help","help",0},
+      {'n',"names-only","APT::Cache::NamesOnly",0},
+      {'f',"show-full","APT::Cache::ShowFull",0},
+      {'c',"config-file",0,CommandLine::ConfigFile},
+      {'o',"option",0,CommandLine::ArbItem},
+      {0,0,0,0}};
+
+   static CommandLine::Args ListArgs[] = {
+      {'h',"help","help",0},
+      {'u',"upgradable","APT::Cache::ShowUpgradable",0},
+      {'i',"installed","APT::Cache::ShowInstalled",0},
+      {'v',"version","APT::Cache::ShowVersion",0},
+      {'s',"summary","APT::Cache::ShowSummary",0},
+      {'n',"installed","APT::Cache::Installed",0},
+      {'c',"config-file",0,CommandLine::ConfigFile},
+      {'o',"option",0,CommandLine::ArbItem},
+      {0,0,0,0}};
+
+   static CommandLine::Args NoArgs[] = {
+      {'h',"help","help",0},
+      {'v',"version","version",0},
+      {'c',"config-file",0,CommandLine::ConfigFile},
+      {'o',"option",0,CommandLine::ArbItem},
+      {0,0,0,0}};
+
+
+   unsigned long Hash = 0;
+   for (const char *p=Name; *p; p++)
+      Hash = 5*Hash + *p;
+   switch (Hash%1000000) {
+      case 73823: // install
+      case 436466: // remove
+      case 16517: // keep
+      case 259776: // upgrade
+      case 900401: // dist-upgrade
+	 return ChangeCacheArgs;
+
+      case 395741: // commit
+	 return CommitArgs;
+
+      case 209563: // showpkg
+      case 17649: // show
+	 return ShowArgs;
+
+      case 438074: // search
+	 return SearchArgs;
+
+      case 16816: // list
+      case 655: // ls
+	 return ListArgs;
+
+      default:
+	 return NoArgs;
+   }
+}
+									/*}}}*/
+int main(int argc,const char *argv[])
+{
+   CommandLine::Dispatch Cmds[] = {{"update",&DoUpdate},
+                                   {"upgrade",&DoUpgrade},
+                                   {"install",&DoInstall},
+                                   {"remove",&DoInstall},
+                                   {"keep",&DoInstall},
+                                   {"dist-upgrade",&DoDistUpgrade},
+                                   {"dselect-upgrade",&DoDSelectUpgrade},
+				   {"build-dep",&DoBuildDep},
+                                   {"clean",&DoClean},
+                                   {"autoclean",&DoAutoClean},
+                                   {"check",&DoCheck},
+				   {"help",&ShowHelp},
+				   {"commit",&DoCommit},
+				   {"quit",&DoQuit},
+				   {"exit",&DoQuit},
+				   {"status",&DoStatus},
+				   {"script",&DoScript},
+				   // apt-cache
+				   {"showpkg",&DumpPackage},
+                                   {"unmet",&UnMet},
+                                   {"search",&Search},
+                                   {"list",&DoList},
+                                   {"ls",&DoList},
+                                   {"depends",&Depends},
+                                   {"whatdepends",&WhatDepends},
+                                   {"rdepends",&RDepends},
+                                   {"show",&ShowPackage},
+                                   {0,0}};
+
+   // Set up gettext support
+   setlocale(LC_ALL,"");
+   textdomain(PACKAGE);
+
+   // Parse the command line and initialize the package library
+   CommandLine CmdL(CommandArgs(""),_config);
+   if (pkgInitConfig(*_config) == false ||
+       CmdL.Parse(argc,argv) == false ||
+       pkgInitSystem(*_config,_system) == false)
+   {
+      if (_config->FindB("version") == true)
+	 ShowHelp(CmdL);
+	 
+      _error->DumpErrors();
+      return 100;
+   }
+
+   // Deal with stdout not being a tty
+   if (ttyname(STDOUT_FILENO) == 0 && _config->FindI("quiet",0) < 1)
+      _config->Set("quiet","1");
+
+   // Setup the output streams
+   c0out.rdbuf(cout.rdbuf());
+   c1out.rdbuf(cout.rdbuf());
+   c2out.rdbuf(cout.rdbuf());
+   if (_config->FindI("quiet",0) > 0)
+      c0out.rdbuf(devnull.rdbuf());
+   if (_config->FindI("quiet",0) > 1)
+      c1out.rdbuf(devnull.rdbuf());
+
+   // Setup the signals
+   signal(SIGPIPE,SIG_IGN);
+   signal(SIGINT,SIG_IGN);
+   signal(SIGWINCH,SigWinch);
+   SigWinch(0);
+
+   // Prepare the cache
+   GCache = new CacheFile();
+   GCache->Open();
+   if (GCache->CheckDeps(true) == false) {
+      c1out << _("There are broken packages. ")
+	    << _("Run `check' to see them.") << endl;
+      c1out << _("You can try to fix them automatically with `install -f'.") << endl;
+   }
+
+   // Make a copy of the configuration. Each command will modify its
+   // own copy of the whole configuration.
+   Configuration GlobalConfig(*_config);
+
+   ReadLineInit();
+   c1out << _("Welcome to the APT shell. Type \"help\" for more information.") << endl;
+
+// CNC:2003-03-19
+#ifdef WITH_LUA
+   _lua->SetDepCache(*GCache);
+   _lua->RunScripts("Scripts::AptShell::Init", false);
+   _lua->ResetCaches();
+   bool HasCmdScripts = (_lua->HasScripts("Scripts::AptGet::Command") ||
+			 _lua->HasScripts("Scripts::AptCache::Command"));
+#endif
+
+   int largc;
+   const char *largv[1024];
+   char *line, *p, *q;
+   largv[0] = "";
+   while (_config->FindB("quit") == false)
+   {
+      if (_error->empty() == false)
+      {
+	 _error->DumpErrors();
+	 continue;
+      }
+      
+      line = readline(_config->Find("APT::Shell::Prompt", "apt> ").c_str());
+      if (!line || !*line)
+	 continue;
+      add_history(line);
+
+      largc = 1; // CommandLine.Parse() ignores the first option.
+
+      // Split the line into arguments, handling quotes.
+      p = q = line;
+      // *p = parsed contents, assigned from *q
+      // *q = buffer checker, copying valid stuff to *p
+      while (*q != 0)
+      {
+	 if (largc > sizeof(largv)/sizeof(*largv))
+	 {
+	    _error->Error(_("Exceeded maximum number of command arguments"));
+	    break;
+	 }
+	 while (isspace(*q)) q++;
+	 if (*q == 0)
+	    break;
+	 largv[largc++] = p = q;
+	 while (*q != 0 && !isspace(*q)) {
+	    if (*q == '"' || *q == '\'') {
+	       char quote = *q++;
+	       while (*q != 0) {
+		  if (*q == quote) {
+		     q++;
+		     break;
+		  } else if (*q == '\\') {
+		     switch (*(++q)) {
+			case '\0':
+			   break;
+			case '\\':
+			   *p++ = '\\';
+			   break;
+			default:
+			   *p++ = *q;
+			   break;
+		     }
+		     q++;
+		  } else {
+		     *p++ = *q++;
+		  }
+	       }
+	    } else {
+	       *p++ = *q++;
+	    }
+	 }
+	 if (*q != 0)
+	    q++;
+	 *p++ = 0;
+      }
+      if (largc == 1 || _error->empty() == false)
+	 continue;
+      largv[largc] = 0;
+      
+      // Make our own copy of the configuration.
+      delete _config;
+      _config = new Configuration(GlobalConfig);
+
+      // Prepare the command line
+      CommandLine CmdL(CommandArgs(largv[1]),_config);
+      CmdL.Parse(largc,largv);
+
+// CNC:2003-03-19
+#ifdef WITH_LUA
+      if (HasCmdScripts == true) {
+	 _lua->SetDepCache(*GCache);
+	 _lua->SetGlobal("command_args", CmdL.FileList);
+	 _lua->SetGlobal("command_consume", 0.0);
+	 _lua->RunScripts("Scripts::AptGet::Command", true);
+	 _lua->RunScripts("Scripts::AptCache::Command", true);
+	 double Consume = _lua->GetGlobalI("command_consume");
+	 _lua->ResetGlobals();
+	 _lua->ResetCaches();
+	 if (Consume == 1) {
+	    free(line);
+	    continue;
+	 }
+      }
+#endif
+
+      if (_error->PendingError() == false)
+	 CmdL.DispatchArg(Cmds);
+      
+      free(line);
+   }
+
+   ReadLineFinish();
+
+   delete GCache;
+
+   // Print any errors or warnings found during parsing
+   if (_error->empty() == false)
+   {
+      bool Errors = _error->PendingError();
+      _error->DumpErrors();
+      return Errors == true?100:0;
+   }
+   
+   return 0;   
+}
+
+// vim:sts=3:sw=3

--- End Message ---
--- Begin Message ---
On Thu, Nov 27, 2003 at 02:17:02AM +0100, Michael Vogt wrote:
> Package: apt
> Version: 0.5.14
> Severity: wishlist
> Tags: patch
> 
> You find attached a patch to add apt-shell from apt-rpm to debian apt. 
> Apt-shell is a shell like interface for apt with readline support, 
> statefull cache and other goodies. See:
> https://distro.conectiva.com.br/pipermail/apt-rpm/2003-March/001412.html
> for a summary of the features.
> 
> The patch is split into two parts: 
> 1. apt-shell-common.diff adds stuff to apt that apt-shell needs 
> 2. apt-shell-shell.diff is the shell interface itself
> 
> The patch is against apt-0.5.14 and work for me(tm). It looks like it
> does not break other apps linked against libapt (but I tested only
> synaptic). 
> 
> bye,
>  Michael

Closing this bug now, as we have no interest in merging this
anymore, even if it were possible. There's also aptsh in the
archive already for anyone reading this (not sure if it actually
works, though).

-- 
Julian Andres Klode  - Debian Developer, Ubuntu Member

See http://wiki.debian.org/JulianAndresKlode and http://jak-linux.org/.

When replying, only quote what is necessary, and write each reply
directly below the part(s) it pertains to (`inline'). Thank you.

--- End Message ---

Reply to: