97674a1ffa1797da6ed3637651002dd6fefda3f7
[apt.git] / cmdline / apt-shell.cc
1 // -*- mode: c++; mode: fold -*-
2 // Description                                                          /*{{{*/
3 // $Id: apt-get.cc,v 1.126 2003/02/12 16:14:08 doogie Exp $
4 /* ######################################################################
5    
6    apt-get - Cover for dpkg
7    
8    This is an allout cover for dpkg implementing a safer front end. It is
9    based largely on libapt-pkg.
10
11    The syntax is different, 
12       apt-get [opt] command [things]
13    Where command is:
14       update - Resyncronize the package files from their sources
15       upgrade - Smart-Download the newest versions of all packages
16       dselect-upgrade - Follows dselect's changes to the Status: field
17                        and installes new and removes old packages
18       dist-upgrade - Powerfull upgrader designed to handle the issues with
19                     a new distribution.
20       install - Download and install a given package (by name, not by .deb)
21       check - Update the package cache and check for broken packages
22       clean - Erase the .debs downloaded to /var/cache/apt/archives and
23               the partial dir too
24
25    ##################################################################### */
26                                                                         /*}}}*/
27 // Include Files                                                        /*{{{*/
28 #include <apt-pkg/error.h>
29 #include <apt-pkg/cmndline.h>
30 #include <apt-pkg/init.h>
31 #include <apt-pkg/depcache.h>
32 #include <apt-pkg/sourcelist.h>
33 #include <apt-pkg/algorithms.h>
34 #include <apt-pkg/acquire-item.h>
35 #include <apt-pkg/strutl.h>
36 #include <apt-pkg/clean.h>
37 #include <apt-pkg/srcrecords.h>
38 #include <apt-pkg/version.h>
39 #include <apt-pkg/cachefile.h>
40 #include <apt-pkg/sptr.h>
41 #include <apt-pkg/versionmatch.h>
42
43 #include <config.h>
44 #include <apti18n.h>
45
46 // CNC:2003-03-17
47 #include <apt-pkg/luaiface.h>
48     
49 #include "acqprogress.h"
50 #include "cmdline.h"
51
52 // CNC:2003-02-14 - apti18n.h includes libintl.h which includes locale.h,
53 //                  as reported by Radu Greab.
54 //#include <locale.h>
55 #include <langinfo.h>
56 #include <fstream>
57 #include <termios.h>
58 #include <sys/ioctl.h>
59 #include <sys/stat.h>
60 #include <sys/statvfs.h>
61 #include <sys/types.h>
62 #include <signal.h>
63 #include <unistd.h>
64 #include <stdio.h>
65 #include <errno.h>
66 #include <regex.h>
67 #include <sys/wait.h>
68
69 #include <readline/readline.h>
70 #include <readline/history.h>
71 #include <fnmatch.h>
72                                                                         /*}}}*/
73
74 using namespace std;
75
76 // class CacheFile - Cover class for some dependency cache functions    /*{{{*/
77 // ---------------------------------------------------------------------
78 /* */
79 class CacheFile : public cmdCacheFile
80 {
81    bool IsRoot;
82    
83    public:
84    bool CheckDeps(bool AllowBroken = false);
85    bool BuildCaches()
86    {
87       OpTextProgress Prog(*_config);
88       if (pkgCacheFile::BuildCaches(Prog,IsRoot) == false)
89          return false;
90       return true;
91    }
92    bool Open() 
93    {
94       OpTextProgress Prog(*_config);
95       if (pkgCacheFile::Open(Prog,IsRoot) == false)
96          return false;
97       Sort();
98       return true;
99    };
100    bool CanCommit()
101    {
102       return IsRoot;
103    }
104    CacheFile() : cmdCacheFile()
105    {
106       IsRoot = (getuid() == 0);
107    };
108 };
109                                                                         /*}}}*/
110
111 static CacheFile *GCache = NULL;
112
113 class AutoRestore
114 {
115    pkgDepCache::State State;
116    bool Guarded;
117    public:
118    inline pkgDepCache::State *operator ->() {return &State;};
119    inline pkgDepCache::State *operator &() {return &State;};
120    inline void UnGuard() { Guarded = false; };
121    AutoRestore(pkgDepCache &Cache)
122       : State(&Cache), Guarded(true) {};
123    ~AutoRestore() { if (Guarded) State.Restore(); };
124 };
125
126 class AutoReOpenCache
127 {
128    CacheFile **Cache;
129    bool Guarded;
130    public:
131    inline void UnGuard() { Guarded = false; };
132    AutoReOpenCache(CacheFile *&Cache)
133       : Cache(&Cache), Guarded(true) {};
134    ~AutoReOpenCache()
135    {
136       if (Guarded) {
137          delete *Cache;
138          *Cache = new CacheFile;
139          (*Cache)->Open();
140          if ((*Cache)->CheckDeps(true) == false) {
141             c1out << _("There are broken packages. ")
142                   << _("Run `check' to see them.") << endl;
143             c1out << _("You can try to fix them automatically with `install --fix-broken'0.") << endl;
144          }
145       }
146    };
147 };
148
149 void CommandHelp(const char *Name);
150 bool CheckHelp(CommandLine &CmdL, unsigned int MaxArgs=512)
151 {
152    if (CmdL.FileSize()-1 > MaxArgs) {
153       _error->Error(_("Excessive arguments"));
154       return true;
155    }
156    if (_config->FindB("help") == true) {
157       CommandHelp(CmdL.FileList[0]);
158       return true;
159    }
160    return false;
161 }
162
163 // ShowChanges - Show what would change between the saved state and the /*{{{*/
164 //               cache file state.
165 // ---------------------------------------------------------------------
166 /* */
167 bool ShowChanges(CacheFile &Cache,pkgDepCache::State *State=NULL)
168 {
169    ShowUpgraded(c1out,Cache,State);
170    ShowDel(c1out,Cache,State);
171    ShowNew(c1out,Cache,State);
172    if (State != NULL)
173       ShowKept(c1out,Cache,State);
174    ShowHold(c1out,Cache,State);
175    ShowDowngraded(c1out,Cache,State);
176    ShowEssential(c1out,Cache,State);
177    Stats(c1out,Cache,State);
178
179    if (State != NULL) {
180       double DebBytes = Cache->DebSize()-State->DebSize();
181       // Number of bytes
182       if (DebBytes >= 0)
183          ioprintf(c1out,_("Will need more %sB of archives.\n"),
184                   SizeToStr(DebBytes).c_str());
185       else
186          ioprintf(c1out,_("Will need less %sB of archives.\n"),
187                   SizeToStr(-1*DebBytes).c_str());
188
189       double UsrSize = Cache->UsrSize()-State->UsrSize();
190       // Size delta
191       if (UsrSize >= 0)
192          ioprintf(c1out,_("After unpacking will need more %sB of disk space.\n"),
193                   SizeToStr(UsrSize).c_str());
194       else
195          ioprintf(c1out,_("After unpacking will need less %sB of disk space.\n"),
196                   SizeToStr(-1*UsrSize).c_str());
197    } else {
198       double DebBytes = Cache->DebSize();
199       // Number of bytes
200       ioprintf(c1out,_("Will need %sB of archives.\n"),
201                SizeToStr(DebBytes).c_str());
202
203       // Size delta
204       if (Cache->UsrSize() >= 0)
205          ioprintf(c1out,_("After unpacking %sB of additional disk space will be used.\n"),
206                   SizeToStr(Cache->UsrSize()).c_str());
207       else
208          ioprintf(c1out,_("After unpacking %sB disk space will be freed.\n"),
209                   SizeToStr(-1*Cache->UsrSize()).c_str());
210    }
211    return true;
212 }
213                                                                         /*}}}*/
214
215 bool ConfirmChanges(CacheFile &Cache, AutoRestore &StateGuard)
216 {
217    if (StateGuard->Changed()) {
218       c2out << _("Unrequested changes are needed to execute this operation.")
219             << endl;
220       ShowChanges(Cache,&StateGuard);
221       c2out << _("Do you want to continue? [Y/n] ") << flush;
222       if (YnPrompt() == false) {
223          c2out << _("Abort.") << endl;
224          return false;
225       }
226    }
227    StateGuard.UnGuard();
228    return true;
229 }
230
231 // CacheFile::CheckDeps - Open the cache file                           /*{{{*/
232 // ---------------------------------------------------------------------
233 /* This routine generates the caches and then opens the dependency cache
234    and verifies that the system is OK. */
235 bool CacheFile::CheckDeps(bool AllowBroken)
236 {
237    if (_error->PendingError() == true)
238       return false;
239
240    // Check that the system is OK
241    //if (DCache->DelCount() != 0 || DCache->InstCount() != 0)
242    //   return _error->Error("Internal Error, non-zero counts");
243    
244    // Apply corrections for half-installed packages
245    if (pkgApplyStatus(*DCache) == false)
246       return false;
247    
248    // Nothing is broken
249    if (DCache->BrokenCount() == 0 || AllowBroken == true)
250       return true;
251
252    // Attempt to fix broken things
253    if (_config->FindB("APT::Get::Fix-Broken",false) == true)
254    {
255       c1out << _("Correcting dependencies...") << flush;
256       if (pkgFixBroken(*DCache) == false || DCache->BrokenCount() != 0)
257       {
258          c1out << _(" failed.") << endl;
259          ShowBroken(c1out,*this,true);
260
261          return _error->Error(_("Unable to correct dependencies"));
262       }
263       if (pkgMinimizeUpgrade(*DCache) == false)
264          return _error->Error(_("Unable to minimize the upgrade set"));
265       
266       c1out << _(" Done") << endl;
267    }
268    else
269    {
270       c1out << _("You might want to run `install --fix-broken' to correct these.") << endl;
271       ShowBroken(c1out,*this,true);
272
273       return _error->Error(_("Unmet dependencies. Try using --fix-broken."));
274    }
275       
276    return true;
277 }
278                                                                         /*}}}*/
279
280 bool DoClean(CommandLine &CmdL);
281 bool DoAutoClean(CommandLine &CmdL);
282
283 // InstallPackages - Actually download and install the packages         /*{{{*/
284 // ---------------------------------------------------------------------
285 /* This displays the informative messages describing what is going to 
286    happen and then calls the download routines */
287 bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
288                      bool Saftey = true)
289 {
290    if (_config->FindB("APT::Get::Purge",false) == true)
291    {
292       pkgCache::PkgIterator I = Cache->PkgBegin();
293       for (; I.end() == false; I++)
294       {
295          if (I.Purge() == false && Cache[I].Mode == pkgDepCache::ModeDelete)
296             Cache->MarkDelete(I,true);
297       }
298    }
299    
300    bool Fail = false;
301    bool Essential = false;
302    
303    // Show all the various warning indicators
304    // CNC:2002-03-06 - Change Show-Upgraded default to true, and move upwards.
305    if (_config->FindB("APT::Get::Show-Upgraded",true) == true)
306       ShowUpgraded(c1out,Cache);
307    ShowDel(c1out,Cache);
308    ShowNew(c1out,Cache);
309    if (ShwKept == true)
310       ShowKept(c1out,Cache);
311    Fail |= !ShowHold(c1out,Cache);
312    Fail |= !ShowDowngraded(c1out,Cache);
313    Essential = !ShowEssential(c1out,Cache);
314    Fail |= Essential;
315    Stats(c1out,Cache);
316    
317    // Sanity check
318    if (Cache->BrokenCount() != 0)
319    {
320       ShowBroken(c1out,Cache,false);
321       return _error->Error("Internal Error, InstallPackages was called with broken packages!");
322    }
323
324    if (Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
325        Cache->BadCount() == 0)
326       return true;
327
328    // No remove flag
329    if (Cache->DelCount() != 0 && _config->FindB("APT::Get::Remove",true) == false)
330       return _error->Error(_("Packages need to be removed but Remove is disabled."));
331        
332    // Run the simulator ..
333    if (_config->FindB("APT::Get::Simulate") == true)
334    {
335       pkgSimulate PM(Cache);
336       pkgPackageManager::OrderResult Res = PM.DoInstall();
337       if (Res == pkgPackageManager::Failed)
338          return false;
339       if (Res != pkgPackageManager::Completed)
340          return _error->Error("Internal Error, Ordering didn't finish");
341       return true;
342    }
343    
344    // Create the text record parser
345    pkgRecords Recs(Cache);
346    if (_error->PendingError() == true)
347       return false;
348    
349    // Lock the archive directory
350    FileFd Lock;
351    if (_config->FindB("Debug::NoLocking",false) == false &&
352        _config->FindB("APT::Get::Print-URIs") == false)
353    {
354       Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
355       if (_error->PendingError() == true)
356          return _error->Error(_("Unable to lock the download directory"));
357    }
358    
359    // Create the download object
360    AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));   
361    pkgAcquire Fetcher(&Stat);
362
363    // Read the source list
364    pkgSourceList List;
365    if (List.ReadMainList() == false)
366       return _error->Error(_("The list of sources could not be read."));
367    
368    // Create the package manager and prepare to download
369    SPtr<pkgPackageManager> PM= _system->CreatePM(Cache);
370    if (PM->GetArchives(&Fetcher,&List,&Recs) == false || 
371        _error->PendingError() == true)
372       return false;
373
374    // Display statistics
375    double FetchBytes = Fetcher.FetchNeeded();
376    double FetchPBytes = Fetcher.PartialPresent();
377    double DebBytes = Fetcher.TotalNeeded();
378    if (DebBytes != Cache->DebSize())
379    {
380       c0out << DebBytes << ',' << Cache->DebSize() << endl;
381       c0out << "How odd.. The sizes didn't match, email apt@packages.debian.org" << endl;
382    }
383    
384    // Number of bytes
385    if (DebBytes != FetchBytes)
386       ioprintf(c1out,_("Need to get %sB/%sB of archives.\n"),
387                SizeToStr(FetchBytes).c_str(),SizeToStr(DebBytes).c_str());
388    else
389       ioprintf(c1out,_("Need to get %sB of archives.\n"),
390                SizeToStr(DebBytes).c_str());
391
392    // Size delta
393    if (Cache->UsrSize() >= 0)
394       ioprintf(c1out,_("After unpacking %sB of additional disk space will be used.\n"),
395                SizeToStr(Cache->UsrSize()).c_str());
396    else
397       ioprintf(c1out,_("After unpacking %sB disk space will be freed.\n"),
398                SizeToStr(-1*Cache->UsrSize()).c_str());
399
400    if (_error->PendingError() == true)
401       return false;
402
403    /* Check for enough free space, but only if we are actually going to
404       download */
405    if (_config->FindB("APT::Get::Print-URIs") == false &&
406        _config->FindB("APT::Get::Download",true) == true)
407    {
408       struct statvfs Buf;
409       string OutputDir = _config->FindDir("Dir::Cache::Archives");
410       if (statvfs(OutputDir.c_str(),&Buf) != 0)
411          return _error->Errno("statvfs","Couldn't determine free space in %s",
412                               OutputDir.c_str());
413       // CNC:2002-07-11
414       if (unsigned(Buf.f_bavail) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
415          return _error->Error(_("You don't have enough free space in %s."),
416                               OutputDir.c_str());
417    }
418    
419    // Fail safe check
420    if (_config->FindI("quiet",0) >= 2 ||
421        _config->FindB("APT::Get::Assume-Yes",false) == true)
422    {
423       if (Fail == true && _config->FindB("APT::Get::Force-Yes",false) == false)
424          return _error->Error(_("There are problems and -y was used without --force-yes"));
425    }         
426
427    if (Essential == true && Saftey == true)
428    {
429       if (_config->FindB("APT::Get::Trivial-Only",false) == true)
430          return _error->Error(_("Trivial Only specified but this is not a trivial operation."));
431       
432       const char *Prompt = _("Yes, do as I say!");
433       ioprintf(c2out,
434                _("You are about to do something potentially harmful\n"
435                  "To continue type in the phrase '%s'\n"
436                  " ?] "),Prompt);
437       c2out << flush;
438       if (AnalPrompt(Prompt) == false)
439       {
440          c2out << _("Abort.") << endl;
441          exit(1);
442       }     
443    }
444    else
445    {      
446       // Prompt to continue
447       if (Ask == true || Fail == true)
448       {            
449          if (_config->FindB("APT::Get::Trivial-Only",false) == true)
450             return _error->Error(_("Trivial Only specified but this is not a trivial operation."));
451          
452          if (_config->FindI("quiet",0) < 2 &&
453              _config->FindB("APT::Get::Assume-Yes",false) == false)
454          {
455             c2out << _("Do you want to continue? [Y/n] ") << flush;
456          
457             if (YnPrompt() == false)
458             {
459                c2out << _("Abort.") << endl;
460                exit(1);
461             }     
462          }       
463       }      
464    }
465    
466    // Just print out the uris an exit if the --print-uris flag was used
467    if (_config->FindB("APT::Get::Print-URIs") == true)
468    {
469       pkgAcquire::UriIterator I = Fetcher.UriBegin();
470       for (; I != Fetcher.UriEnd(); I++)
471          cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' << 
472                I->Owner->FileSize << ' ' << I->Owner->MD5Sum() << endl;
473       return true;
474    }
475
476    /* Unlock the dpkg lock if we are not going to be doing an install
477       after. */
478    if (_config->FindB("APT::Get::Download-Only",false) == true)
479       _system->UnLock();
480
481    // CNC:2003-02-24
482    bool Ret = true;
483
484    AutoReOpenCache CacheGuard(GCache);
485    
486    // Run it
487    while (1)
488    {
489       bool Transient = false;
490       if (_config->FindB("APT::Get::Download",true) == false)
491       {
492          for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I < Fetcher.ItemsEnd();)
493          {
494             if ((*I)->Local == true)
495             {
496                I++;
497                continue;
498             }
499
500             // Close the item and check if it was found in cache
501             (*I)->Finished();
502             if ((*I)->Complete == false)
503                Transient = true;
504             
505             // Clear it out of the fetch list
506             delete *I;
507             I = Fetcher.ItemsBegin();
508          }       
509       }
510       
511       if (Fetcher.Run() == pkgAcquire::Failed)
512          return false;
513
514       // CNC:2003-02-24
515       _error->PopState();
516       
517       // Print out errors
518       bool Failed = false;
519       for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
520       {
521          if ((*I)->Status == pkgAcquire::Item::StatDone &&
522              (*I)->Complete == true)
523             continue;
524          
525          if ((*I)->Status == pkgAcquire::Item::StatIdle)
526          {
527             Transient = true;
528             // Failed = true;
529             continue;
530          }
531
532          fprintf(stderr,_("Failed to fetch %s  %s\n"),(*I)->DescURI().c_str(),
533                  (*I)->ErrorText.c_str());
534          Failed = true;
535       }
536
537       /* If we are in no download mode and missing files and there were
538          'failures' then the user must specify -m. Furthermore, there 
539          is no such thing as a transient error in no-download mode! */
540       if (Transient == true &&
541           _config->FindB("APT::Get::Download",true) == false)
542       {
543          Transient = false;
544          Failed = true;
545       }
546       
547       if (_config->FindB("APT::Get::Download-Only",false) == true)
548       {
549          if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
550             return _error->Error(_("Some files failed to download"));
551          c1out << _("Download complete and in download only mode") << endl;
552          return true;
553       }
554       
555       if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
556       {
557          return _error->Error(_("Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?"));
558       }
559       
560       if (Transient == true && Failed == true)
561          return _error->Error(_("--fix-missing and media swapping is not currently supported"));
562       
563       // Try to deal with missing package files
564       if (Failed == true && PM->FixMissing() == false)
565       {
566          cerr << _("Unable to correct missing packages.") << endl;
567          return _error->Error(_("Aborting Install."));
568       }
569
570       // CNC:2002-10-18
571       if (Transient == false || _config->FindB("Acquire::CDROM::Copy-All", false) == false) {
572          if (Transient == true) {
573             // We must do that in a system independent way. */
574             _config->Set("RPM::Install-Options::", "--nodeps");
575          }
576          _system->UnLock();
577          pkgPackageManager::OrderResult Res = PM->DoInstall();
578          if (Res == pkgPackageManager::Failed || _error->PendingError() == true)
579          {
580             if (Transient == false)
581                return false;
582             Ret = false;
583          }
584
585          // CNC:2002-07-06
586          if (Res == pkgPackageManager::Completed)
587          {
588             CommandLine *CmdL = NULL; // Watch out! If used will blow up!
589             if (_config->FindB("APT::Post-Install::Clean",false) == true) 
590                Ret &= DoClean(*CmdL);
591             else if (_config->FindB("APT::Post-Install::AutoClean",false) == true) 
592                Ret &= DoAutoClean(*CmdL);
593             return Ret;
594          }
595          
596          _system->Lock();
597       }
598
599       // CNC:2003-02-24
600       _error->PushState();
601       
602       // Reload the fetcher object and loop again for media swapping
603       Fetcher.Shutdown();
604       if (PM->GetArchives(&Fetcher,&List,&Recs) == false)
605          return false;
606    }   
607 }
608                                                                         /*}}}*/
609 #define MODE_INSTALL 0
610 #define MODE_REMOVE  1
611 #define MODE_KEEP    2
612 // TryToInstall - Try to install a single package                       /*{{{*/
613 // ---------------------------------------------------------------------
614 /* This used to be inlined in DoInstall, but with the advent of regex package
615    name matching it was split out.. */
616 bool TryToInstall(pkgCache::PkgIterator Pkg,pkgDepCache &Cache,
617                   pkgProblemResolver &Fix,int Mode,bool BrokenFix,
618                   unsigned int &ExpectedInst,bool AllowFail = true)
619 {
620    // CNC:2004-03-03 - Improved virtual package handling.
621    if (Cache[Pkg].CandidateVer == 0 && Pkg->ProvidesList != 0)
622    {
623       vector<pkgCache::Package *> GoodSolutions;
624       for (pkgCache::PrvIterator Prv = Pkg.ProvidesList();
625            Prv.end() == false; Prv++)
626       {
627          pkgCache::PkgIterator PrvPkg = Prv.OwnerPkg();
628          // Check if it's a different version of a package already
629          // considered as a good solution.
630          bool AlreadySeen = false;
631          for (vector<pkgCache::Package *>::size_type i = 0; i != GoodSolutions.size(); i++)
632          {
633             pkgCache::PkgIterator GoodPkg(Cache, GoodSolutions[i]);
634             if (PrvPkg == GoodPkg)
635             {
636                AlreadySeen = true;
637                break;
638             }
639          }
640          if (AlreadySeen)
641             continue;
642          // Is the current version the provides owner?
643          if (PrvPkg.CurrentVer() == Prv.OwnerVer())
644          {
645             // Already installed packages are good solutions, since
646             // the user might try to install something he already has
647             // without being aware.
648             GoodSolutions.push_back(PrvPkg);
649             continue;
650          }
651          pkgCache::VerIterator PrvPkgCandVer =
652                                  Cache[PrvPkg].CandidateVerIter(Cache);
653          if (PrvPkgCandVer.end() == true)
654          {
655             // Packages without a candidate version are not good solutions.
656             continue;
657          }
658          // Is the provides pointing to the candidate version?
659          if (PrvPkgCandVer == Prv.OwnerVer())
660          {
661             // Yes, it is. This is a good solution.
662             GoodSolutions.push_back(PrvPkg);
663             continue;
664          }
665       }
666       vector<string> GoodSolutionNames;
667       for (vector<string>::size_type i = 0; i != GoodSolutions.size(); i++)
668       {
669          pkgCache::PkgIterator GoodPkg(Cache, GoodSolutions[i]);
670          GoodSolutionNames.push_back(GoodPkg.Name());
671       }
672 #ifdef WITH_LUA
673       if (GoodSolutions.size() > 1)
674       {
675          vector<string> VS;
676          _lua->SetDepCache(&Cache);
677          _lua->SetDontFix();
678          _lua->SetGlobal("virtualname", Pkg.Name());
679          _lua->SetGlobal("packages", GoodSolutions);
680          _lua->SetGlobal("packagenames", GoodSolutionNames);
681          _lua->SetGlobal("selected");
682          _lua->RunScripts("Scripts::AptGet::Install::SelectPackage");
683          pkgCache::Package *selected = _lua->GetGlobalPkg("selected");
684          if (selected)
685          {
686             GoodSolutions.clear();
687             GoodSolutions.push_back(selected);
688          }
689          else
690          {
691             vector<string> Tmp = _lua->GetGlobalStrList("packagenames");
692             if (Tmp.size() == GoodSolutions.size())
693                GoodSolutionNames = Tmp;
694          }
695          _lua->ResetGlobals();
696          _lua->ResetCaches();
697       }
698 #endif
699       if (GoodSolutions.size() == 1)
700       {
701          pkgCache::PkgIterator GoodPkg(Cache, GoodSolutions[0]);
702          ioprintf(c1out,_("Selecting %s for '%s'\n"),
703                   GoodPkg.Name(), Pkg.Name());
704          Pkg = GoodPkg;
705       }
706       else if (GoodSolutions.size() == 0)
707       {
708          _error->Error(_("Package %s is a virtual package with no "
709                          "good providers.\n"), Pkg.Name());
710          return false;
711       }
712       else
713       {
714          ioprintf(c1out,_("Package %s is a virtual package provided by:\n"),
715                   Pkg.Name());
716          for (vector<pkgCache::Package *>::size_type i = 0; i != GoodSolutions.size(); i++)
717          {
718             pkgCache::PkgIterator GoodPkg(Cache, GoodSolutions[i]);
719             if (GoodPkg.CurrentVer().end() == false)
720                c1out << "  " << GoodSolutionNames[i]
721                      << " "  << Cache[GoodPkg].CandVersion
722                      << _(" [Installed]") << endl;
723             else
724                c1out << "  " << GoodSolutionNames[i]
725                      << " "  << Cache[GoodPkg].CandVersion << endl;
726          }
727          c1out << _("You should explicitly select one to install.") << endl;
728          _error->Error(_("Package %s is a virtual package with multiple "
729                          "good providers.\n"), Pkg.Name());
730          return false;
731       }
732    }
733    
734    // Handle the no-upgrade case
735    if (_config->FindB("APT::Get::upgrade",true) == false &&
736        Pkg->CurrentVer != 0)
737    {
738       if (AllowFail == true)
739          ioprintf(c1out,_("Skipping %s, it is already installed and upgrade is not set.\n"),
740                   Pkg.Name());
741       return true;
742    }
743    
744    // Check if there is something at all to install
745    pkgDepCache::StateCache &State = Cache[Pkg];
746    if (Mode == MODE_REMOVE && Pkg->CurrentVer == 0)
747    {
748       Fix.Clear(Pkg);
749       Fix.Protect(Pkg);
750       Fix.Remove(Pkg);
751       
752       /* We want to continue searching for regex hits, so we return false here
753          otherwise this is not really an error. */
754       if (AllowFail == false)
755          return false;
756       
757       ioprintf(c1out,_("Package %s is not installed, so not removed\n"),Pkg.Name());
758       return true;
759    }
760    
761    if (State.CandidateVer == 0 && Mode == MODE_INSTALL)
762    {
763       if (AllowFail == false)
764          return false;
765       
766 // CNC:2004-03-03 - Improved virtual package handling.
767 #if 0
768       if (Pkg->ProvidesList != 0)
769       {
770          ioprintf(c1out,_("Package %s is a virtual package provided by:\n"),
771                   Pkg.Name());
772          
773          pkgCache::PrvIterator I = Pkg.ProvidesList();
774          for (; I.end() == false; I++)
775          {
776             pkgCache::PkgIterator Pkg = I.OwnerPkg();
777             
778             if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer())
779             {
780                if (Cache[Pkg].Install() == true && Cache[Pkg].NewInstall() == false)
781                   c1out << "  " << Pkg.Name() << " " << I.OwnerVer().VerStr() <<
782                   _(" [Installed]") << endl;
783                else
784                   c1out << "  " << Pkg.Name() << " " << I.OwnerVer().VerStr() << endl;
785             }      
786          }
787          c1out << _("You should explicitly select one to install.") << endl;
788       }
789       else
790 #endif
791       {
792          ioprintf(c1out,
793          _("Package %s has no available version, but exists in the database.\n"
794            "This typically means that the package was mentioned in a dependency and\n"
795            "never uploaded, has been obsoleted or is not available with the contents\n"
796            "of sources.list\n"),Pkg.Name());
797          
798          string List;
799          string VersionsList;
800          SPtrArray<bool> Seen = new bool[Cache.Head().PackageCount];
801          memset(Seen,0,Cache.Head().PackageCount*sizeof(*Seen));
802          pkgCache::DepIterator Dep = Pkg.RevDependsList();
803          for (; Dep.end() == false; Dep++)
804          {
805             // CNC:2002-07-30
806             if (Dep->Type != pkgCache::Dep::Replaces &&
807                 Dep->Type != pkgCache::Dep::Obsoletes)
808                continue;
809             if (Seen[Dep.ParentPkg()->ID] == true)
810                continue;
811             Seen[Dep.ParentPkg()->ID] = true;
812             List += string(Dep.ParentPkg().Name()) + " ";
813             //VersionsList += string(Dep.ParentPkg().CurVersion) + "\n"; ???
814          }          
815          ShowList(c1out,_("However the following packages replace it:"),List,VersionsList);
816       }
817       
818       _error->Error(_("Package %s has no installation candidate"),Pkg.Name());
819       return false;
820    }
821
822    Fix.Clear(Pkg);
823    Fix.Protect(Pkg);   
824
825    if (Mode == MODE_KEEP) {
826       Cache.MarkKeep(Pkg);
827       return true;
828    }
829    
830    if (Mode == MODE_REMOVE)
831    {
832       Fix.Remove(Pkg);
833       Cache.MarkDelete(Pkg,_config->FindB("APT::Get::Purge",false));
834       return true;
835    }
836    
837    // Install it
838    Cache.MarkInstall(Pkg,false);
839    if (State.Install() == false)
840    {
841       if (_config->FindB("APT::Get::ReInstall",false) == true)
842       {
843          if (Pkg->CurrentVer == 0 || Pkg.CurrentVer().Downloadable() == false)
844             ioprintf(c1out,_("Reinstallation of %s is not possible, it cannot be downloaded.\n"),
845                      Pkg.Name());
846          else
847             Cache.SetReInstall(Pkg,true);
848       }      
849       else
850       {
851          if (AllowFail == true)
852             ioprintf(c1out,_("%s is already the newest version.\n"),
853                      Pkg.Name());
854       }      
855    }   
856    else
857       ExpectedInst++;
858    
859    // Install it with autoinstalling enabled.
860    if (State.InstBroken() == true && BrokenFix == false)
861       Cache.MarkInstall(Pkg,true);
862    return true;
863 }
864                                                                         /*}}}*/
865 // TryToChangeVer - Try to change a candidate version                   /*{{{*/
866 // ---------------------------------------------------------------------
867 // CNC:2003-11-11
868 bool TryToChangeVer(pkgCache::PkgIterator &Pkg,pkgDepCache &Cache,
869                     int VerOp,const char *VerTag,bool IsRel)
870 {
871    // CNC:2003-11-05
872    pkgVersionMatch Match(VerTag,(IsRel == true?pkgVersionMatch::Release : 
873                                  pkgVersionMatch::Version),VerOp);
874    
875    pkgCache::VerIterator Ver = Match.Find(Pkg);
876                          
877    if (Ver.end() == true)
878    {
879       // CNC:2003-11-05
880       if (IsRel == true)
881          return _error->Error(_("Release %s'%s' for '%s' was not found"),
882                               op2str(VerOp),VerTag,Pkg.Name());
883       return _error->Error(_("Version %s'%s' for '%s' was not found"),
884                            op2str(VerOp),VerTag,Pkg.Name());
885    }
886    
887    if (strcmp(VerTag,Ver.VerStr()) != 0)
888    {
889       // CNC:2003-11-11
890       if (IsRel == true)
891          ioprintf(c1out,_("Selected version %s (%s) for %s\n"),
892                   Ver.VerStr(),Ver.RelStr().c_str(),Pkg.Name());
893       else
894          ioprintf(c1out,_("Selected version %s for %s\n"),
895                   Ver.VerStr(),Pkg.Name());
896    }
897    
898    Cache.SetCandidateVersion(Ver);
899    // CNC:2003-11-11
900    Pkg = Ver.ParentPkg();
901    return true;
902 }
903                                                                         /*}}}*/
904
905 // DoUpdate - Update the package lists                                  /*{{{*/
906 // ---------------------------------------------------------------------
907 /* */
908
909 // CNC:2004-04-19
910 class UpdateLogCleaner : public pkgArchiveCleaner
911 {
912    protected:
913    virtual void Erase(const char *File,string Pkg,string Ver,struct stat &St) 
914    {
915       c1out << "Del " << Pkg << " " << Ver << " [" << SizeToStr(St.st_size) << "B]" << endl;
916       unlink(File);      
917    };
918 };
919
920 bool DoUpdate(CommandLine &CmdL)
921 {
922    if (CheckHelp(CmdL) == true)
923       return true;
924
925    bool Partial = false;
926    pkgSourceList List;
927
928    if (CmdL.FileSize() != 1)
929    {
930       List.ReadVendors();
931       for (const char **I = CmdL.FileList + 1; *I != 0; I++)
932       {
933          string Repo = _config->FindDir("Dir::Etc::sourceparts") + *I;
934          if (FileExists(Repo) == false)
935             Repo += ".list";
936          if (FileExists(Repo) == true)
937          {
938             if (List.ReadAppend(Repo) == true)
939                Partial = true;
940             else
941                return _error->Error(_("Sources list %s could not be read"),Repo.c_str());
942          }
943          else
944             return _error->Error(_("Sources list %s doesn't exist"),Repo.c_str());
945       }
946    }
947    else if (List.ReadMainList() == false)
948       return false;
949
950    // Lock the list directory
951    FileFd Lock;
952    if (_config->FindB("Debug::NoLocking",false) == false)
953    {
954       Lock.Fd(GetLock(_config->FindDir("Dir::State::Lists") + "lock"));
955       if (_error->PendingError() == true)
956          return _error->Error(_("Unable to lock the list directory"));
957    }
958
959 // CNC:2003-03-19
960 #ifdef WITH_LUA
961    _lua->SetDepCache(*GCache);
962    _lua->RunScripts("Scripts::AptGet::Update::Pre");
963    _lua->ResetCaches();
964 #endif
965    
966    // Create the download object
967    AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
968    pkgAcquire Fetcher(&Stat);
969
970    // CNC:2002-07-03
971    bool Failed = false;
972    // Populate it with release file URIs
973    if (List.GetReleases(&Fetcher) == false)
974       return false;
975    if (_config->FindB("APT::Get::Print-URIs") == false)
976    {
977       Fetcher.Run();
978       for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
979       {
980          if ((*I)->Status == pkgAcquire::Item::StatDone)
981             continue;
982          (*I)->Finished();
983          Failed = true;
984       }
985       if (Failed == true)
986          _error->Warning(_("Release files for some repositories could not be retrieved or authenticated. Such repositories are being ignored."));
987    }
988    
989    // Populate it with the source selection
990    if (List.GetIndexes(&Fetcher) == false)
991          return false;
992    
993    // Just print out the uris an exit if the --print-uris flag was used
994    if (_config->FindB("APT::Get::Print-URIs") == true)
995    {
996       pkgAcquire::UriIterator I = Fetcher.UriBegin();
997       for (; I != Fetcher.UriEnd(); I++)
998          cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' << 
999                I->Owner->FileSize << ' ' << I->Owner->MD5Sum() << endl;
1000       return true;
1001    }
1002    
1003    // Run it
1004    if (Fetcher.Run() == pkgAcquire::Failed)
1005       return false;
1006
1007    for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
1008    {
1009       if ((*I)->Status == pkgAcquire::Item::StatDone)
1010          continue;
1011
1012       (*I)->Finished();
1013       
1014       fprintf(stderr,_("Failed to fetch %s  %s\n"),(*I)->DescURI().c_str(),
1015               (*I)->ErrorText.c_str());
1016       Failed = true;
1017    }
1018    
1019    // Clean out any old list files
1020    if (_config->FindB("APT::Get::List-Cleanup",true) == true)
1021    {
1022       if (Fetcher.Clean(_config->FindDir("Dir::State::lists")) == false ||
1023           Fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/") == false)
1024          return false;
1025    }
1026
1027    {
1028       AutoReOpenCache CacheGuard(GCache);
1029    }
1030
1031 // CNC:2003-03-19
1032 #ifdef WITH_LUA
1033    _lua->SetDepCache(*GCache);
1034    _lua->RunScripts("Scripts::AptGet::Update::Post");
1035    _lua->ResetCaches();
1036 #endif
1037
1038    // CNC:2004-04-19
1039    if (Failed == false && _config->FindB("APT::Get::Archive-Cleanup",true) == true)
1040    {
1041       UpdateLogCleaner Cleaner;
1042       Cleaner.Go(_config->FindDir("Dir::Cache::archives"), *GCache);
1043       Cleaner.Go(_config->FindDir("Dir::Cache::archives") + "partial/",
1044                  *GCache);
1045    }
1046    
1047    if (Failed == true)
1048       return _error->Error(_("Some index files failed to download, they have been ignored, or old ones used instead."));
1049    
1050    return true;
1051 }
1052                                                                         /*}}}*/
1053 // DoUpgrade - Upgrade all packages                                     /*{{{*/
1054 // ---------------------------------------------------------------------
1055 /* Upgrade all packages without installing new packages or erasing old
1056    packages */
1057 bool DoUpgrade(CommandLine &CmdL)
1058 {
1059    if (CheckHelp(CmdL, 0) == true)
1060       return true;
1061    
1062    CacheFile &Cache = *GCache;
1063    if (GCache->CanCommit() == false) {
1064       _error->Error(_("You have no permissions for that"));
1065       return false;
1066    }
1067    
1068    AutoRestore StateGuard(Cache);
1069    
1070    if (GCache->CheckDeps() == false)
1071       return false;
1072
1073    // Do the upgrade
1074    if (pkgAllUpgrade(Cache) == false)
1075    {
1076       ShowBroken(c1out,Cache,false);
1077       return _error->Error(_("Internal Error, AllUpgrade broke stuff"));
1078    }
1079
1080 // CNC:2003-03-19
1081 #ifdef WITH_LUA
1082    _lua->SetDepCache(Cache);
1083    _lua->RunScripts("Scripts::AptGet::Upgrade");
1084    _lua->ResetCaches();
1085 #endif
1086
1087    ConfirmChanges(Cache, StateGuard);
1088    
1089    return true;
1090 }
1091                                                                         /*}}}*/
1092 // DoInstall - Install packages from the command line                   /*{{{*/
1093 // ---------------------------------------------------------------------
1094 /* Install named packages */
1095 bool DoInstall(CommandLine &CmdL)
1096 {
1097    if (CheckHelp(CmdL) == true)
1098       return true;
1099
1100    CacheFile &Cache = *GCache;
1101    if (GCache->CanCommit() == false) {
1102       _error->Error(_("You have no permissions for that"));
1103       return false;
1104    }
1105    if (Cache.CheckDeps(CmdL.FileSize() != 1) == false)
1106       return false;
1107
1108    // Enter the special broken fixing mode if the user specified arguments
1109    bool BrokenFix = false;
1110    if (Cache->BrokenCount() != 0)
1111       BrokenFix = true;
1112    
1113    unsigned int ExpectedInst = 0;
1114    unsigned int Packages = 0;
1115    pkgProblemResolver Fix(Cache);
1116    
1117    int DefMode = MODE_INSTALL;
1118    if (strcasecmp(CmdL.FileList[0],"remove") == 0)
1119       DefMode = MODE_REMOVE;
1120    else if (strcasecmp(CmdL.FileList[0],"keep") == 0)
1121       DefMode = MODE_KEEP;
1122
1123    AutoRestore StateGuard(Cache);
1124
1125    for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1126    {
1127       // Duplicate the string
1128       size_t Length = strlen(*I);
1129       char S[300];
1130       if (Length >= sizeof(S))
1131          continue;
1132       strcpy(S,*I);
1133       
1134       // CNC:2003-03-15
1135       char OrigS[300];
1136       strcpy(OrigS,S);
1137       
1138       // See if we are removing and special indicators..
1139       int Mode = DefMode;
1140       char *VerTag = 0;
1141       bool VerIsRel = false;
1142       // CNC:2003-11-05
1143       int VerOp = 0;
1144       while (Cache->FindPkg(S).end() == true)
1145       {
1146          // Handle an optional end tag indicating what to do
1147          if (Length >= 1 && S[Length - 1] == '-')
1148          {
1149             Mode = MODE_REMOVE;
1150             S[--Length] = 0;
1151             continue;
1152          }
1153          
1154          if (Length >= 1 && S[Length - 1] == '+')
1155          {
1156             Mode = MODE_INSTALL;
1157             S[--Length] = 0;
1158             continue;
1159          }
1160          
1161          // CNC:2003-11-05
1162          char *sep = strpbrk(S,"=><");
1163          if (sep)
1164          {
1165             char *p;
1166             int eq = 0, gt = 0, lt = 0;
1167
1168             VerIsRel = false;
1169             for (p = sep; *p && strchr("=><",*p); ++p)
1170                switch (*p)
1171                {
1172                   case '=': eq = 1; break;
1173                   case '>': gt = 1; break;
1174                   case '<': lt = 1; break;
1175                }
1176             if (eq)
1177             {
1178                if (lt && gt)
1179                   return _error->Error(_("Couldn't parse name '%s'"),S);
1180                else if (lt)
1181                   VerOp = pkgCache::Dep::LessEq;
1182                else if (gt)
1183                   VerOp = pkgCache::Dep::GreaterEq;
1184                else
1185                   VerOp = pkgCache::Dep::Equals;
1186             }
1187             else
1188             {
1189                if (lt && gt)
1190                   VerOp = pkgCache::Dep::NotEquals;
1191                else if (lt)
1192                   VerOp = pkgCache::Dep::Less;
1193                else if (gt)
1194                   VerOp = pkgCache::Dep::Greater;
1195                else
1196                   return _error->Error(_("Couldn't parse name '%s'"),S);
1197             }
1198             *sep = '\0';
1199             VerTag = p;
1200          }
1201          
1202          // CNC:2003-11-21 - Try to handle unknown file items.
1203          if (S[0] == '/')
1204          {
1205             pkgRecords Recs(Cache);
1206             if (_error->PendingError() == true)
1207                return false;
1208             pkgCache::PkgIterator Pkg = (*Cache).PkgBegin();
1209             for (; Pkg.end() == false; Pkg++)
1210             {
1211                // Should we try on all versions?
1212                pkgCache::VerIterator Ver = (*Cache)[Pkg].CandidateVerIter(*Cache);
1213                if (Ver.end() == false)
1214                {
1215                   pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList());
1216                   if (Parse.HasFile(S)) {
1217                      strcpy(S, Pkg.Name());
1218                      // Confirm the translation.
1219                      ExpectedInst += 1000;
1220                      break;
1221                   }
1222                }
1223             }
1224          }
1225
1226          char *Slash = strchr(S,'/');
1227          if (Slash != 0)
1228          {
1229             VerIsRel = true;
1230             *Slash = 0;
1231             VerTag = Slash + 1;
1232          }
1233          
1234          break;
1235       }
1236       
1237       // Locate the package
1238       pkgCache::PkgIterator Pkg = Cache->FindPkg(S);
1239       Packages++;
1240       if (Pkg.end() == true)
1241       {
1242          // Check if the name is a regex
1243          const char *I;
1244          for (I = S; *I != 0; I++)
1245             if (*I == '?' || *I == '*' || *I == '|' ||
1246                 *I == '[' || *I == '^' || *I == '$')
1247                break;
1248
1249          // CNC:2003-05-15
1250          if (*I == 0) {
1251 #ifdef WITH_LUA
1252             vector<string> VS;
1253             _lua->SetDepCache(Cache);
1254             _lua->SetDontFix();
1255             _lua->SetGlobal("argument", OrigS);
1256             _lua->SetGlobal("translated", VS);
1257             _lua->RunScripts("Scripts::AptGet::Install::TranslateArg");
1258             const char *name = _lua->GetGlobalStr("translated");
1259             if (name != NULL) {
1260                VS.push_back(name);
1261             } else {
1262                VS = _lua->GetGlobalStrList("translated");
1263             }
1264             _lua->ResetGlobals();
1265             _lua->ResetCaches();
1266
1267             // Translations must always be confirmed
1268             ExpectedInst += 1000;
1269
1270             // Run over the matches
1271             bool Hit = false;
1272             for (vector<string>::const_iterator I = VS.begin();
1273                  I != VS.end(); I++) {
1274
1275                Pkg = Cache->FindPkg(*I);
1276                if (Pkg.end() == true)
1277                   continue;
1278
1279                ioprintf(c1out,_("Selecting %s for '%s'\n"),
1280                         Pkg.Name(),OrigS);
1281             
1282                Hit |= TryToInstall(Pkg,Cache,Fix,Mode,BrokenFix,
1283                                    ExpectedInst,true);
1284             }
1285          
1286             if (Hit == true)
1287                continue;
1288 #endif
1289             return _error->Error(_("Couldn't find package %s"),S);
1290          }
1291
1292          // Regexs must always be confirmed
1293          ExpectedInst += 1000;
1294          
1295          // Compile the regex pattern
1296          regex_t Pattern;
1297          int Res;
1298          if ((Res = regcomp(&Pattern,S,REG_EXTENDED | REG_ICASE |
1299                      REG_NOSUB)) != 0)
1300          {
1301             char Error[300];        
1302             regerror(Res,&Pattern,Error,sizeof(Error));
1303             return _error->Error(_("Regex compilation error - %s"),Error);
1304          }
1305          
1306          // Run over the matches
1307          bool Hit = false;
1308          for (Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
1309          {
1310             if (regexec(&Pattern,Pkg.Name(),0,0,0) != 0)
1311                continue;
1312             
1313             // CNC:2003-11-23
1314             ioprintf(c1out,_("Selecting %s for '%s'\n"),
1315                      Pkg.Name(),S);
1316             StateGuard->Ignore(Pkg);
1317             
1318             if (VerTag != 0)
1319                // CNC:2003-11-05
1320                if (TryToChangeVer(Pkg,Cache,VerOp,VerTag,VerIsRel) == false)
1321                   return false;
1322             
1323             Hit |= TryToInstall(Pkg,Cache,Fix,Mode,BrokenFix,
1324                                 ExpectedInst,false);
1325          }
1326          regfree(&Pattern);
1327          
1328          if (Hit == false)
1329             return _error->Error(_("Couldn't find package %s"),S);
1330       }
1331       else
1332       {
1333          if (VerTag != 0)
1334             // CNC:2003-11-05
1335             if (TryToChangeVer(Pkg,Cache,VerOp,VerTag,VerIsRel) == false)
1336                return false;
1337          if (TryToInstall(Pkg,Cache,Fix,Mode,BrokenFix,ExpectedInst) == false)
1338             return false;
1339          StateGuard->Ignore(Pkg);
1340       }
1341    }
1342
1343 // CNC:2003-03-19
1344 #ifdef WITH_LUA
1345    _lua->SetDepCache(Cache);
1346    _lua->SetDontFix();
1347    _lua->RunScripts("Scripts::AptGet::Install::PreResolve");
1348    _lua->ResetCaches();
1349 #endif
1350
1351    // CNC:2002-08-01
1352    if (_config->FindB("APT::Remove-Depends",false) == true)
1353       Fix.RemoveDepends();
1354
1355    /* If we are in the Broken fixing mode we do not attempt to fix the
1356       problems. This is if the user invoked install without -f and gave
1357       packages */
1358    if (BrokenFix == true && Cache->BrokenCount() != 0)
1359    {
1360       ConfirmChanges(Cache, StateGuard);
1361       c1out << _("There are still broken packages. ")
1362             << _("Run `check' to see them.") << endl;
1363       c1out << _("You can try to fix them automatically with `install --fix-broken'.") << endl;
1364       return true;
1365    }
1366
1367    // Call the scored problem resolver
1368    if (DefMode != MODE_KEEP) {
1369       Fix.InstallProtect();
1370       if (Fix.Resolve(true) == false)
1371          _error->Discard();
1372    } else {
1373       if (Fix.Resolve(false) == false)
1374          _error->Discard();
1375    }
1376
1377 // CNC:2003-03-19
1378 #ifdef WITH_LUA
1379    if (Cache->BrokenCount() == 0) {
1380       _lua->SetDepCache(Cache);
1381       _lua->SetProblemResolver(&Fix);
1382       _lua->RunScripts("Scripts::AptGet::Install::PostResolve");
1383       _lua->ResetCaches();
1384    }
1385 #endif
1386
1387
1388    // Now we check the state of the packages,
1389    if (Cache->BrokenCount() != 0)
1390    {
1391       c1out << 
1392        _("Some packages could not be installed. This may mean that you have\n" 
1393          "requested an impossible situation or that some of the repositories\n"
1394          "in use are in an inconsistent state at the moment.") << endl;
1395       if (Packages == 1)
1396       {
1397          c1out << endl;
1398          c1out << 
1399           _("Since you only requested a single operation it is extremely likely that\n"
1400             "the package is simply not installable and a bug report against\n" 
1401             "that package should be filed.") << endl;
1402       }
1403
1404       c1out << _("The following information may help to resolve the situation:") << endl;
1405       c1out << endl;
1406       ShowBroken(c1out,Cache,false);
1407
1408       return _error->Error(_("Broken packages"));
1409    }
1410
1411    ConfirmChanges(Cache, StateGuard);
1412
1413    return true;
1414 }
1415                                                                         /*}}}*/
1416 // DoDistUpgrade - Automatic smart upgrader                             /*{{{*/
1417 // ---------------------------------------------------------------------
1418 /* Intelligent upgrader that will install and remove packages at will */
1419 bool DoDistUpgrade(CommandLine &CmdL)
1420 {
1421    if (CheckHelp(CmdL,0) == true)
1422       return true;
1423
1424    CacheFile &Cache = *GCache;
1425    if (GCache->CanCommit() == false) {
1426       _error->Error(_("You have no permissions for that"));
1427       return false;
1428    }
1429
1430    AutoRestore StateGuard(Cache);
1431
1432    if (GCache->CheckDeps() == false)
1433       return false;
1434
1435    c0out << _("Calculating Upgrade... ") << flush;
1436    if (pkgDistUpgrade(*Cache) == false)
1437    {
1438       c0out << _("Failed") << endl;
1439       ShowBroken(c1out,Cache,false);
1440       return false;
1441    }
1442
1443 // CNC:2003-03-19
1444 #ifdef WITH_LUA
1445    _lua->SetDepCache(Cache);
1446    _lua->RunScripts("Scripts::AptGet::DistUpgrade");
1447    _lua->ResetCaches();
1448 #endif
1449    
1450    c0out << _("Done") << endl;
1451    
1452    ConfirmChanges(Cache, StateGuard);
1453
1454    return true;
1455 }
1456                                                                         /*}}}*/
1457 // DoDSelectUpgrade - Do an upgrade by following dselects selections    /*{{{*/
1458 // ---------------------------------------------------------------------
1459 /* Follows dselect's selections */
1460 bool DoDSelectUpgrade(CommandLine &CmdL)
1461 {
1462    if (CheckHelp(CmdL,0) == true)
1463       return true;
1464
1465    CacheFile &Cache = *GCache;
1466    if (GCache->CanCommit() == false) {
1467       _error->Error(_("You have no permissions for that"));
1468       return false;
1469    }
1470    
1471    AutoRestore StateGuard(Cache);
1472    
1473    if (GCache->CheckDeps() == false)
1474       return false;
1475    
1476    // Install everything with the install flag set
1477    pkgCache::PkgIterator I = Cache->PkgBegin();
1478    for (;I.end() != true; I++)
1479    {
1480       /* Install the package only if it is a new install, the autoupgrader
1481          will deal with the rest */
1482       if (I->SelectedState == pkgCache::State::Install)
1483          Cache->MarkInstall(I,false);
1484    }
1485
1486    /* Now install their deps too, if we do this above then order of
1487       the status file is significant for | groups */
1488    for (I = Cache->PkgBegin();I.end() != true; I++)
1489    {
1490       /* Install the package only if it is a new install, the autoupgrader
1491          will deal with the rest */
1492       if (I->SelectedState == pkgCache::State::Install)
1493          Cache->MarkInstall(I,true);
1494    }
1495    
1496    // Apply erasures now, they override everything else.
1497    for (I = Cache->PkgBegin();I.end() != true; I++)
1498    {
1499       // Remove packages 
1500       if (I->SelectedState == pkgCache::State::DeInstall ||
1501           I->SelectedState == pkgCache::State::Purge)
1502          Cache->MarkDelete(I,I->SelectedState == pkgCache::State::Purge);
1503    }
1504
1505    /* Resolve any problems that dselect created, allupgrade cannot handle
1506       such things. We do so quite agressively too.. */
1507    if (Cache->BrokenCount() != 0)
1508    {      
1509       pkgProblemResolver Fix(Cache);
1510
1511       // Hold back held packages.
1512       if (_config->FindB("APT::Ignore-Hold",false) == false)
1513       {
1514          for (pkgCache::PkgIterator I = Cache->PkgBegin(); I.end() == false; I++)
1515          {
1516             if (I->SelectedState == pkgCache::State::Hold)
1517             {
1518                Fix.Protect(I);
1519                Cache->MarkKeep(I);
1520             }
1521          }
1522       }
1523    
1524       if (Fix.Resolve() == false)
1525       {
1526          ShowBroken(c1out,Cache,false);
1527          return _error->Error("Internal Error, problem resolver broke stuff");
1528       }
1529    }
1530
1531    // Now upgrade everything
1532    if (pkgAllUpgrade(Cache) == false)
1533    {
1534       ShowBroken(c1out,Cache,false);
1535       return _error->Error("Internal Error, problem resolver broke stuff");
1536    }
1537
1538    ConfirmChanges(Cache, StateGuard);
1539    
1540    return true;
1541 }
1542                                                                         /*}}}*/
1543 // DoClean - Remove download archives                                   /*{{{*/
1544 // ---------------------------------------------------------------------
1545 /* */
1546 bool DoClean(CommandLine &CmdL)
1547 {
1548    if (CheckHelp(CmdL,0) == true)
1549       return true;
1550
1551    return cmdDoClean(CmdL);
1552 }
1553                                                                         /*}}}*/
1554 bool DoAutoClean(CommandLine &CmdL)
1555 {
1556    if (CheckHelp(CmdL,0) == true)
1557       return true;
1558
1559    // Lock the archive directory
1560    FileFd Lock;
1561    if (_config->FindB("Debug::NoLocking",false) == false)
1562    {
1563       Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
1564       if (_error->PendingError() == true)
1565          return _error->Error(_("Unable to lock the download directory"));
1566    }
1567    
1568    CacheFile &Cache = *GCache;
1569 #if 0
1570    if (Cache.Open() == false)
1571       return false;
1572 #endif
1573    
1574    LogCleaner Cleaner;
1575    
1576    return Cleaner.Go(_config->FindDir("Dir::Cache::archives"),*Cache) &&
1577       Cleaner.Go(_config->FindDir("Dir::Cache::archives") + "partial/",*Cache);
1578 }
1579                                                                         /*}}}*/
1580 // DoCheck - Perform the check operation                                /*{{{*/
1581 // ---------------------------------------------------------------------
1582 /* Opening automatically checks the system, this command is mostly used
1583    for debugging */
1584 bool DoCheck(CommandLine &CmdL)
1585 {
1586    if (CheckHelp(CmdL,0) == true)
1587       return true;
1588
1589    CacheFile &Cache = *GCache;
1590    AutoRestore StateGuard(Cache);
1591
1592    if (GCache->CheckDeps() == false)
1593       return false;
1594    
1595    return true;
1596 }
1597                                                                         /*}}}*/
1598 // DoBuildDep - Install/removes packages to satisfy build dependencies  /*{{{*/
1599 // ---------------------------------------------------------------------
1600 /* This function will look at the build depends list of the given source 
1601    package and install the necessary packages to make it true, or fail. */
1602 bool DoBuildDep(CommandLine &CmdL)
1603 {
1604    if (CheckHelp(CmdL) == true)
1605       return true;
1606
1607    CacheFile &Cache = *GCache;
1608    if (GCache->CanCommit() == false) {
1609       _error->Error(_("You have no permissions for that"));
1610       return false;
1611    }
1612    
1613    AutoRestore StateGuard(Cache);
1614    
1615    if (GCache->CheckDeps() == false)
1616       return false;
1617
1618    if (CmdL.FileSize() <= 1)
1619       return _error->Error(_("Must specify at least one package to check builddeps for"));
1620    
1621    // Read the source list
1622    pkgSourceList List;
1623    if (List.ReadMainList() == false)
1624       return _error->Error(_("The list of sources could not be read."));
1625    
1626    // Create the text record parsers
1627    pkgRecords Recs(Cache);
1628    pkgSrcRecords SrcRecs(List);
1629    if (_error->PendingError() == true)
1630       return false;
1631
1632    // Create the download object
1633    AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));   
1634    pkgAcquire Fetcher(&Stat);
1635
1636    unsigned J = 0;
1637    for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++)
1638    {
1639       string Src;
1640       pkgSrcRecords::Parser *Last = FindSrc(*I,Recs,SrcRecs,Src,*Cache);
1641       if (Last == 0)
1642          return _error->Error(_("Unable to find a source package for %s"),Src.c_str());
1643             
1644       // Process the build-dependencies
1645       vector<pkgSrcRecords::Parser::BuildDepRec> BuildDeps;
1646       if (Last->BuildDepends(BuildDeps, _config->FindB("APT::Get::Arch-Only",false)) == false)
1647         return _error->Error(_("Unable to get build-dependency information for %s"),Src.c_str());
1648    
1649       // Also ensure that build-essential packages are present
1650       Configuration::Item const *Opts = _config->Tree("APT::Build-Essential");
1651       if (Opts) 
1652          Opts = Opts->Child;
1653       for (; Opts; Opts = Opts->Next)
1654       {
1655          if (Opts->Value.empty() == true)
1656             continue;
1657
1658          pkgSrcRecords::Parser::BuildDepRec rec;
1659          rec.Package = Opts->Value;
1660          rec.Type = pkgSrcRecords::Parser::BuildDependIndep;
1661          rec.Op = 0;
1662          BuildDeps.push_back(rec);
1663       }
1664
1665       if (BuildDeps.size() == 0)
1666       {
1667          ioprintf(c1out,_("%s has no build depends.\n"),Src.c_str());
1668          continue;
1669       }
1670       
1671       // Install the requested packages
1672       unsigned int ExpectedInst = 0;
1673       vector <pkgSrcRecords::Parser::BuildDepRec>::iterator D;
1674       pkgProblemResolver Fix(Cache);
1675       bool skipAlternatives = false; // skip remaining alternatives in an or group
1676       for (D = BuildDeps.begin(); D != BuildDeps.end(); D++)
1677       {
1678          bool hasAlternatives = (((*D).Op & pkgCache::Dep::Or) == pkgCache::Dep::Or);
1679
1680          if (skipAlternatives == true)
1681          {
1682             if (!hasAlternatives)
1683                skipAlternatives = false; // end of or group
1684             continue;
1685          }
1686
1687          if ((*D).Type == pkgSrcRecords::Parser::BuildConflict ||
1688              (*D).Type == pkgSrcRecords::Parser::BuildConflictIndep)
1689          {
1690             pkgCache::PkgIterator Pkg = Cache->FindPkg((*D).Package);
1691             // Build-conflicts on unknown packages are silently ignored
1692             if (Pkg.end() == true)
1693                continue;
1694
1695             pkgCache::VerIterator IV = (*Cache)[Pkg].InstVerIter(*Cache);
1696
1697             /* 
1698              * Remove if we have an installed version that satisfies the 
1699              * version criteria
1700              */
1701             if (IV.end() == false && 
1702                 Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
1703                TryToInstall(Pkg,Cache,Fix,MODE_REMOVE,false,ExpectedInst);
1704          }
1705          else // BuildDep || BuildDepIndep
1706          {
1707             if (_config->FindB("Debug::BuildDeps",false) == true)
1708                  cout << "Looking for " << (*D).Package << "...\n";
1709
1710             pkgCache::PkgIterator Pkg = Cache->FindPkg((*D).Package);
1711
1712             // CNC:2003-11-21 - Try to handle unknown file deps.
1713             if (Pkg.end() == true && (*D).Package[0] == '/')
1714             {
1715                const char *File = (*D).Package.c_str();
1716                Pkg = (*Cache).PkgBegin();
1717                for (; Pkg.end() == false; Pkg++)
1718                {
1719                   // Should we try on all versions?
1720                   pkgCache::VerIterator Ver = (*Cache)[Pkg].CandidateVerIter(*Cache);
1721                   if (Ver.end() == false)
1722                   {
1723                      pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList());
1724                      if (Parse.HasFile(File))
1725                         break;
1726                   }
1727                }
1728             }
1729
1730             if (Pkg.end() == true)
1731             {
1732                if (_config->FindB("Debug::BuildDeps",false) == true)
1733                     cout << " (not found)" << (*D).Package << endl;
1734
1735                if (hasAlternatives)
1736                   continue;
1737
1738                return _error->Error(_("%s dependency for %s cannot be satisfied "
1739                                       "because the package %s cannot be found"),
1740                                     Last->BuildDepType((*D).Type),Src.c_str(),
1741                                     (*D).Package.c_str());
1742             }
1743
1744             /*
1745              * if there are alternatives, we've already picked one, so skip
1746              * the rest
1747              *
1748              * TODO: this means that if there's a build-dep on A|B and B is
1749              * installed, we'll still try to install A; more importantly,
1750              * if A is currently broken, we cannot go back and try B. To fix 
1751              * this would require we do a Resolve cycle for each package we 
1752              * add to the install list. Ugh
1753              */
1754                        
1755             /* 
1756              * If this is a virtual package, we need to check the list of
1757              * packages that provide it and see if any of those are
1758              * installed
1759              */
1760             pkgCache::PrvIterator Prv = Pkg.ProvidesList();
1761             for (; Prv.end() != true; Prv++)
1762             {
1763                if (_config->FindB("Debug::BuildDeps",false) == true)
1764                     cout << "  Checking provider " << Prv.OwnerPkg().Name() << endl;
1765
1766                if ((*Cache)[Prv.OwnerPkg()].InstVerIter(*Cache).end() == false)
1767                   break;
1768             }
1769             
1770             // Get installed version and version we are going to install
1771             pkgCache::VerIterator IV = (*Cache)[Pkg].InstVerIter(*Cache);
1772
1773             if ((*D).Version[0] != '\0') {
1774                  // Versioned dependency
1775
1776                  pkgCache::VerIterator CV = (*Cache)[Pkg].CandidateVerIter(*Cache);
1777
1778                  for (; CV.end() != true; CV++)
1779                  {
1780                       if (Cache->VS().CheckDep(CV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
1781                            break;
1782                  }
1783                  if (CV.end() == true)
1784                    if (hasAlternatives)
1785                    {
1786                       continue;
1787                    }
1788                    else
1789                    {
1790                       return _error->Error(_("%s dependency for %s cannot be satisfied "
1791                                              "because no available versions of package %s "
1792                                              "can satisfy version requirements"),
1793                                            Last->BuildDepType((*D).Type),Src.c_str(),
1794                                            (*D).Package.c_str());
1795                    }
1796             }
1797             else
1798             {
1799                // Only consider virtual packages if there is no versioned dependency
1800                if (Prv.end() == false)
1801                {
1802                   if (_config->FindB("Debug::BuildDeps",false) == true)
1803                      cout << "  Is provided by installed package " << Prv.OwnerPkg().Name() << endl;
1804                   skipAlternatives = hasAlternatives;
1805                   continue;
1806                }
1807             }
1808             if (IV.end() == false)
1809             {
1810                if (_config->FindB("Debug::BuildDeps",false) == true)
1811                   cout << "  Is installed\n";
1812
1813                if (Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
1814                {
1815                   skipAlternatives = hasAlternatives;
1816                   continue;
1817                }
1818
1819                if (_config->FindB("Debug::BuildDeps",false) == true)
1820                   cout << "    ...but the installed version doesn't meet the version requirement\n";
1821
1822                if (((*D).Op & pkgCache::Dep::LessEq) == pkgCache::Dep::LessEq)
1823                {
1824                   return _error->Error(_("Failed to satisfy %s dependency for %s: Installed package %s is too new"),
1825                                        Last->BuildDepType((*D).Type),
1826                                        Src.c_str(),
1827                                        Pkg.Name());
1828                }
1829             }
1830
1831
1832             if (_config->FindB("Debug::BuildDeps",false) == true)
1833                cout << "  Trying to install " << (*D).Package << endl;
1834
1835             if (TryToInstall(Pkg,Cache,Fix,false,false,ExpectedInst) == true)
1836             {
1837                // We successfully installed something; skip remaining alternatives
1838                skipAlternatives = hasAlternatives;
1839                continue;
1840             }
1841             else if (hasAlternatives)
1842             {
1843                if (_config->FindB("Debug::BuildDeps",false) == true)
1844                   cout << "  Unsatisfiable, trying alternatives\n";
1845                continue;
1846             }
1847             else
1848             {
1849                return _error->Error(_("Failed to satisfy %s dependency for %s: %s"),
1850                                     Last->BuildDepType((*D).Type),
1851                                     Src.c_str(),
1852                                     (*D).Package.c_str());
1853             }
1854          }             
1855       }
1856       
1857       Fix.InstallProtect();
1858       if (Fix.Resolve(true) == false)
1859          _error->Discard();
1860       
1861       // Now we check the state of the packages,
1862       if (Cache->BrokenCount() != 0)
1863          return _error->Error(_("Some broken packages were found while trying to process build-dependencies for %s.\n"
1864                                 "You might want to run `apt-get --fix-broken install' to correct these."),*I);
1865    }
1866   
1867    ConfirmChanges(Cache, StateGuard);
1868
1869    return true;
1870 }
1871                                                                         /*}}}*/
1872 // * - Scripting stuff.                                                 /*{{{*/
1873 // ---------------------------------------------------------------------
1874 /* */
1875 bool DoScript(CommandLine &CmdL)
1876 {
1877    if (CheckHelp(CmdL) == true)
1878       return true;
1879
1880    CacheFile &Cache = *GCache;
1881    AutoRestore StateGuard(Cache);
1882
1883    for (const char **I = CmdL.FileList+1; *I != 0; I++)
1884       _config->Set("Scripts::AptShell::Script::", *I);
1885
1886 // CNC:2003-03-19
1887 #ifdef WITH_LUA
1888    _lua->SetDepCache(Cache);
1889    _lua->RunScripts("Scripts::AptShell::Script");
1890    _lua->RunScripts("Scripts::AptGet::Script");
1891    _lua->RunScripts("Scripts::AptCache::Script");
1892    _lua->ResetCaches();
1893 #endif
1894
1895    _config->Clear("Scripts::AptShell::Script");
1896
1897    ConfirmChanges(Cache, StateGuard);
1898
1899    return true;
1900 }
1901
1902                                                                         /*}}}*/
1903
1904 // --- Unchanged stuff from apt-cache.
1905
1906 // LocalitySort - Sort a version list by package file locality          /*{{{*/
1907 // ---------------------------------------------------------------------
1908 /* */
1909 int LocalityCompare(const void *a, const void *b)
1910 {
1911    pkgCache::VerFile *A = *(pkgCache::VerFile **)a;
1912    pkgCache::VerFile *B = *(pkgCache::VerFile **)b;
1913    
1914    if (A == 0 && B == 0)
1915       return 0;
1916    if (A == 0)
1917       return 1;
1918    if (B == 0)
1919       return -1;
1920    
1921    if (A->File == B->File)
1922       return A->Offset - B->Offset;
1923    return A->File - B->File;
1924 }
1925
1926 void LocalitySort(pkgCache::VerFile **begin,
1927                   unsigned long Count,size_t Size)
1928 {   
1929    qsort(begin,Count,Size,LocalityCompare);
1930 }
1931                                                                         /*}}}*/
1932
1933 // Depends - Print out a dependency tree                                /*{{{*/
1934 // ---------------------------------------------------------------------
1935 /* */
1936 bool Depends(CommandLine &CmdL)
1937 {
1938    if (CheckHelp(CmdL) == true)
1939       return true;
1940
1941    pkgCache &Cache = *GCache;
1942    SPtrArray<unsigned> Colours = new unsigned[Cache.Head().PackageCount];
1943    memset(Colours,0,sizeof(*Colours)*Cache.Head().PackageCount);
1944    
1945    for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1946    {
1947       pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
1948       if (Pkg.end() == true)
1949       {
1950          _error->Warning(_("Unable to locate package %s"),*I);
1951          continue;
1952       }
1953       Colours[Pkg->ID] = 1;
1954    }
1955    
1956    bool Recurse = _config->FindB("APT::Cache::RecurseDepends",false);
1957    bool Installed = _config->FindB("APT::Cache::Installed",false);
1958    bool DidSomething;
1959    do
1960    {
1961       DidSomething = false;
1962       for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
1963       {
1964          if (Colours[Pkg->ID] != 1)
1965             continue;
1966          Colours[Pkg->ID] = 2;
1967          DidSomething = true;
1968          
1969          pkgCache::VerIterator Ver = Pkg.VersionList();
1970          if (Ver.end() == true)
1971          {
1972             cout << '<' << Pkg.Name() << '>' << endl;
1973             continue;
1974          }
1975          
1976          // CNC:2003-03-03
1977          cout << Pkg.Name() << "-" << Ver.VerStr() << endl;
1978          
1979          for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
1980          {
1981
1982             pkgCache::PkgIterator Trg = D.TargetPkg();
1983
1984             if((Installed && Trg->CurrentVer != 0) || !Installed)
1985               {
1986
1987                 if ((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or)
1988                   cout << " |";
1989                 else
1990                   cout << "  ";
1991             
1992                 // Show the package
1993                 if (Trg->VersionList == 0)
1994                    cout << D.DepType() << ": <" << Trg.Name() << ">" << endl;
1995                 // CNC:2003-03-03
1996                 else if (D.TargetVer() == 0)
1997                    cout << D.DepType() << ": " << Trg.Name() << endl;
1998                 else
1999                    cout << D.DepType() << ": " << Trg.Name()
2000                         << " " << D.CompType() << " " << D.TargetVer() << endl;
2001             
2002                 if (Recurse == true)
2003                   Colours[D.TargetPkg()->ID]++;
2004
2005               }
2006             
2007             // Display all solutions
2008             SPtrArray<pkgCache::Version *> List = D.AllTargets();
2009             pkgPrioSortList(Cache,List);
2010             for (pkgCache::Version **I = List; *I != 0; I++)
2011             {
2012                pkgCache::VerIterator V(Cache,*I);
2013                if (V != Cache.VerP + V.ParentPkg()->VersionList ||
2014                    V->ParentPkg == D->Package)
2015                   continue;
2016                // CNC:2003-03-03
2017                cout << "    " << V.ParentPkg().Name()
2018                     << "-" << V.VerStr() << endl;
2019                
2020                if (Recurse == true)
2021                   Colours[D.ParentPkg()->ID]++;
2022             }
2023          }
2024       }      
2025    }   
2026    while (DidSomething == true);
2027    
2028    return true;
2029 }
2030                                                                         /*}}}*/
2031 // RDepends - Print out a reverse dependency tree - mbc                 /*{{{*/
2032 // ---------------------------------------------------------------------
2033 /* */
2034 bool RDepends(CommandLine &CmdL)
2035 {
2036    if (CheckHelp(CmdL) == true)
2037       return true;
2038
2039    pkgCache &Cache = *GCache;
2040    SPtrArray<unsigned> Colours = new unsigned[Cache.Head().PackageCount];
2041    memset(Colours,0,sizeof(*Colours)*Cache.Head().PackageCount);
2042    
2043    for (const char **I = CmdL.FileList + 1; *I != 0; I++)
2044    {
2045       pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
2046       if (Pkg.end() == true)
2047       {
2048          _error->Warning(_("Unable to locate package %s"),*I);
2049          continue;
2050       }
2051       Colours[Pkg->ID] = 1;
2052    }
2053    
2054    bool Recurse = _config->FindB("APT::Cache::RecurseDepends",false);
2055    bool Installed = _config->FindB("APT::Cache::Installed",false);
2056    bool DidSomething;
2057    do
2058    {
2059       DidSomething = false;
2060       for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
2061       {
2062          if (Colours[Pkg->ID] != 1)
2063             continue;
2064          Colours[Pkg->ID] = 2;
2065          DidSomething = true;
2066          
2067          pkgCache::VerIterator Ver = Pkg.VersionList();
2068          if (Ver.end() == true)
2069          {
2070             cout << '<' << Pkg.Name() << '>' << endl;
2071             continue;
2072          }
2073          
2074          cout << Pkg.Name() << endl;
2075          
2076          cout << "Reverse Depends:" << endl;
2077          for (pkgCache::DepIterator D = Pkg.RevDependsList(); D.end() == false; D++)
2078          {          
2079             // Show the package
2080             pkgCache::PkgIterator Trg = D.ParentPkg();
2081
2082             if((Installed && Trg->CurrentVer != 0) || !Installed)
2083               {
2084
2085                 if ((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or)
2086                   cout << " |";
2087                 else
2088                   cout << "  ";
2089
2090                 if (Trg->VersionList == 0)
2091                   cout << D.DepType() << ": <" << Trg.Name() << ">" << endl;
2092                 else
2093                   cout << Trg.Name() << endl;
2094
2095                 if (Recurse == true)
2096                   Colours[D.ParentPkg()->ID]++;
2097
2098               }
2099             
2100             // Display all solutions
2101             SPtrArray<pkgCache::Version *> List = D.AllTargets();
2102             pkgPrioSortList(Cache,List);
2103             for (pkgCache::Version **I = List; *I != 0; I++)
2104             {
2105                pkgCache::VerIterator V(Cache,*I);
2106                if (V != Cache.VerP + V.ParentPkg()->VersionList ||
2107                    V->ParentPkg == D->Package)
2108                   continue;
2109                cout << "    " << V.ParentPkg().Name() << endl;
2110                
2111                if (Recurse == true)
2112                   Colours[D.ParentPkg()->ID]++;
2113             }
2114          }
2115       }      
2116    }   
2117    while (DidSomething == true);
2118    
2119    return true;
2120 }
2121
2122                                                                         /*}}}*/
2123 // CNC:2003-02-19
2124 // WhatDepends - Print out a reverse dependency tree                    /*{{{*/
2125 // ---------------------------------------------------------------------
2126 /* */
2127 bool WhatDepends(CommandLine &CmdL)
2128 {
2129    if (CheckHelp(CmdL) == true)
2130       return true;
2131
2132    pkgCache &Cache = *GCache;
2133    SPtrArray<unsigned> Colours = new unsigned[Cache.Head().PackageCount];
2134    memset(Colours,0,sizeof(*Colours)*Cache.Head().PackageCount);
2135    
2136    for (const char **I = CmdL.FileList + 1; *I != 0; I++)
2137    {
2138       pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
2139       if (Pkg.end() == true)
2140       {
2141          _error->Warning(_("Unable to locate package %s"),*I);
2142          continue;
2143       }
2144       Colours[Pkg->ID] = 1;
2145    }
2146    
2147    bool Recurse = _config->FindB("APT::Cache::RecurseDepends",false);
2148    bool DidSomething;
2149    do
2150    {
2151       DidSomething = false;
2152       for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
2153       {
2154          if (Colours[Pkg->ID] != 1)
2155             continue;
2156          Colours[Pkg->ID] = 2;
2157          DidSomething = true;
2158          
2159          pkgCache::VerIterator Ver = Pkg.VersionList();
2160          if (Ver.end() == true)
2161             cout << '<' << Pkg.Name() << '>' << endl;
2162          else
2163             cout << Pkg.Name() << "-" << Ver.VerStr() << endl;
2164
2165          SPtrArray<unsigned> LocalColours = 
2166                      new unsigned[Cache.Head().PackageCount];
2167          memset(LocalColours,0,sizeof(*LocalColours)*Cache.Head().PackageCount);
2168             
2169          // Display all dependencies directly on the package.
2170          for (pkgCache::DepIterator RD = Pkg.RevDependsList();
2171               RD.end() == false; RD++)
2172          {
2173             pkgCache::PkgIterator Parent = RD.ParentPkg();
2174
2175             if (LocalColours[Parent->ID] == 1)
2176                continue;
2177             LocalColours[Parent->ID] = 1;
2178                
2179             if (Ver.end() == false && RD.TargetVer() &&
2180                 Cache.VS->CheckDep(Ver.VerStr(),RD) == false)
2181                continue;
2182
2183             if (Recurse == true && Colours[Parent->ID] == 0)
2184                Colours[Parent->ID] = 1;
2185
2186             pkgCache::VerIterator ParentVer = Parent.VersionList();
2187
2188             // Show the package
2189             cout << "  " << Parent.Name()
2190                  << "-" << ParentVer.VerStr() << endl;
2191
2192             // Display all dependencies from that package that relate
2193             // to the queried package.
2194             for (pkgCache::DepIterator D = ParentVer.DependsList();
2195                  D.end() == false; D++)
2196             {
2197                // If this is a virtual package, there's no provides.
2198                if (Ver.end() == true) {
2199                   // If it's not the same package, and there's no provides
2200                   // skip that package.
2201                   if (D.TargetPkg() != Pkg)
2202                      continue;
2203                } else if (D.TargetPkg() != Pkg ||
2204                           Cache.VS->CheckDep(Ver.VerStr(),D) == false) {
2205                   // Oops. Either it's not the same package, or the
2206                   // version didn't match. Check virtual provides from
2207                   // the queried package version and verify if this
2208                   // dependency matches one of those.
2209                   bool Hit = false;
2210                   for (pkgCache::PrvIterator Prv = Ver.ProvidesList();
2211                        Prv.end() == false; Prv++) {
2212                      if (Prv.ParentPkg() == D.TargetPkg() &&
2213                          (Prv.ParentPkg()->VersionList == 0 ||
2214                           Cache.VS->CheckDep(Prv.ProvideVersion(),D)==false)) {
2215                         Hit = true;
2216                         break;
2217                      }
2218                   }
2219                   if (Hit == false)
2220                      continue;
2221                }
2222
2223                // Bingo!
2224                pkgCache::PkgIterator Trg = D.TargetPkg();
2225                if (Trg->VersionList == 0)
2226                   cout << "    " << D.DepType()
2227                                  << ": <" << Trg.Name() << ">" << endl;
2228                else if (D.TargetVer() == 0)
2229                   cout << "    " << D.DepType()
2230                                  << ": " << Trg.Name() << endl;
2231                else
2232                   cout << "    " << D.DepType()
2233                                  << ": " << Trg.Name()
2234                                  << " " << D.CompType() << " "
2235                                  << D.TargetVer() << endl;
2236
2237                // Display all solutions
2238                SPtrArray<pkgCache::Version *> List = D.AllTargets();
2239                pkgPrioSortList(Cache,List);
2240                for (pkgCache::Version **I = List; *I != 0; I++)
2241                {
2242                   pkgCache::VerIterator V(Cache,*I);
2243                   if (V != Cache.VerP + V.ParentPkg()->VersionList ||
2244                       V->ParentPkg == D->Package)
2245                      continue;
2246                   cout << "      " << V.ParentPkg().Name()
2247                        << "-" << V.VerStr() << endl;
2248                   
2249                   if (Recurse == true)
2250                      Colours[D.ParentPkg()->ID]++;
2251                }
2252             }
2253          }
2254
2255          // Is this a virtual package the user queried directly?
2256          if (Ver.end())
2257             continue;
2258
2259          // Display all dependencies on virtual provides, which were not
2260          // yet shown in the step above.
2261          for (pkgCache::PrvIterator RDPrv = Ver.ProvidesList();
2262               RDPrv.end() == false; RDPrv++) {
2263             for (pkgCache::DepIterator RD = RDPrv.ParentPkg().RevDependsList();
2264                  RD.end() == false; RD++)
2265             {
2266                pkgCache::PkgIterator Parent = RD.ParentPkg();
2267
2268                if (LocalColours[Parent->ID] == 1)
2269                   continue;
2270                LocalColours[Parent->ID] = 1;
2271                   
2272                if (Ver.end() == false &&
2273                    Cache.VS->CheckDep(Ver.VerStr(),RD) == false)
2274                   continue;
2275
2276                if (Recurse == true && Colours[Parent->ID] == 0)
2277                   Colours[Parent->ID] = 1;
2278
2279                pkgCache::VerIterator ParentVer = Parent.VersionList();
2280
2281                // Show the package
2282                cout << "  " << Parent.Name()
2283                     << "-" << ParentVer.VerStr() << endl;
2284
2285                for (pkgCache::DepIterator D = ParentVer.DependsList();
2286                     D.end() == false; D++)
2287                {
2288                   // Go on if it's the same package and version or
2289                   // if it's the same package and has no versions
2290                   // (a virtual package).
2291                   if (D.TargetPkg() != RDPrv.ParentPkg() ||
2292                       (RDPrv.ProvideVersion() != 0 &&
2293                        Cache.VS->CheckDep(RDPrv.ProvideVersion(),D) == false))
2294                      continue;
2295
2296                   // Bingo!
2297                   pkgCache::PkgIterator Trg = D.TargetPkg();
2298                   if (Trg->VersionList == 0)
2299                      cout << "    " << D.DepType()
2300                                     << ": <" << Trg.Name() << ">" << endl;
2301                   else if (D.TargetVer() == 0)
2302                      cout << "    " << D.DepType()
2303                                     << ": " << Trg.Name() << endl;
2304                   else
2305                      cout << "    " << D.DepType()
2306                                     << ": " << Trg.Name()
2307                                     << " " << D.CompType() << " "
2308                                     << D.TargetVer() << endl;
2309
2310                   // Display all solutions
2311                   SPtrArray<pkgCache::Version *> List = D.AllTargets();
2312                   pkgPrioSortList(Cache,List);
2313                   for (pkgCache::Version **I = List; *I != 0; I++)
2314                   {
2315                      pkgCache::VerIterator V(Cache,*I);
2316                      if (V != Cache.VerP + V.ParentPkg()->VersionList ||
2317                          V->ParentPkg == D->Package)
2318                         continue;
2319                      cout << "      " << V.ParentPkg().Name()
2320                           << "-" << V.VerStr() << endl;
2321                      
2322                      if (Recurse == true)
2323                         Colours[D.ParentPkg()->ID]++;
2324                   }
2325                }
2326             }
2327          }
2328       } 
2329    }
2330    while (DidSomething == true);
2331    
2332    return true;
2333 }
2334                                                                         /*}}}*/
2335 // UnMet - Show unmet dependencies                                      /*{{{*/
2336 // ---------------------------------------------------------------------
2337 /* */
2338 bool UnMet(CommandLine &CmdL)
2339 {
2340    if (CheckHelp(CmdL,0) == true)
2341       return true;
2342
2343    pkgCache &Cache = *GCache;
2344    bool Important = _config->FindB("APT::Cache::Important",false);
2345    
2346    for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
2347    {
2348       for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
2349       {
2350          bool Header = false;
2351          for (pkgCache::DepIterator D = V.DependsList(); D.end() == false;)
2352          {
2353             // Collect or groups
2354             pkgCache::DepIterator Start;
2355             pkgCache::DepIterator End;
2356             D.GlobOr(Start,End);
2357             
2358             // Skip conflicts and replaces
2359             if (End->Type != pkgCache::Dep::PreDepends &&
2360                 End->Type != pkgCache::Dep::Depends && 
2361                 End->Type != pkgCache::Dep::Suggests &&
2362                 End->Type != pkgCache::Dep::Recommends)
2363                continue;
2364
2365             // Important deps only
2366             if (Important == true)
2367                if (End->Type != pkgCache::Dep::PreDepends &&
2368                    End->Type != pkgCache::Dep::Depends)
2369                   continue;
2370             
2371             // Verify the or group
2372             bool OK = false;
2373             pkgCache::DepIterator RealStart = Start;
2374             do
2375             {
2376                // See if this dep is Ok
2377                pkgCache::Version **VList = Start.AllTargets();
2378                if (*VList != 0)
2379                {
2380                   OK = true;
2381                   delete [] VList;
2382                   break;
2383                }
2384                delete [] VList;
2385                
2386                if (Start == End)
2387                   break;
2388                Start++;
2389             }
2390             while (1);
2391
2392             // The group is OK
2393             if (OK == true)
2394                continue;
2395             
2396             // Oops, it failed..
2397             if (Header == false)
2398                ioprintf(cout,_("Package %s version %s has an unmet dep:\n"),
2399                         P.Name(),V.VerStr());
2400             Header = true;
2401             
2402             // Print out the dep type
2403             cout << " " << End.DepType() << ": ";
2404
2405             // Show the group
2406             Start = RealStart;
2407             do
2408             {
2409                cout << Start.TargetPkg().Name();
2410                if (Start.TargetVer() != 0)
2411                   cout << " (" << Start.CompType() << " " << Start.TargetVer() <<
2412                   ")";
2413                if (Start == End)
2414                   break;
2415                cout << " | ";
2416                Start++;
2417             }
2418             while (1);
2419             
2420             cout << endl;
2421          }       
2422       }
2423    }   
2424    return true;
2425 }
2426                                                                         /*}}}*/
2427 // DumpPackage - Show a dump of a package record                        /*{{{*/
2428 // ---------------------------------------------------------------------
2429 /* */
2430 bool DumpPackage(CommandLine &CmdL)
2431 {   
2432    if (CheckHelp(CmdL) == true)
2433       return true;
2434
2435    pkgCache &Cache = *GCache;
2436    for (const char **I = CmdL.FileList + 1; *I != 0; I++)
2437    {
2438       pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
2439       if (Pkg.end() == true)
2440       {
2441          _error->Warning(_("Unable to locate package %s"),*I);
2442          continue;
2443       }
2444
2445       cout << "Package: " << Pkg.Name() << endl;
2446       cout << "Versions: " << endl;
2447       for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
2448       {
2449          cout << Cur.VerStr();
2450          for (pkgCache::VerFileIterator Vf = Cur.FileList(); Vf.end() == false; Vf++)
2451             cout << "(" << Vf.File().FileName() << ")";
2452          cout << endl;
2453       }
2454       
2455       cout << endl;
2456       
2457       cout << "Reverse Depends: " << endl;
2458       for (pkgCache::DepIterator D = Pkg.RevDependsList(); D.end() != true; D++)
2459       {
2460          cout << "  " << D.ParentPkg().Name() << ',' << D.TargetPkg().Name();
2461          if (D->Version != 0)
2462             cout << ' ' << DeNull(D.TargetVer()) << endl;
2463          else
2464             cout << endl;
2465       }
2466       
2467       cout << "Dependencies: " << endl;
2468       for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
2469       {
2470          cout << Cur.VerStr() << " - ";
2471          for (pkgCache::DepIterator Dep = Cur.DependsList(); Dep.end() != true; Dep++)
2472             cout << Dep.TargetPkg().Name() << " (" << (int)Dep->CompareOp << " " << DeNull(Dep.TargetVer()) << ") ";
2473          cout << endl;
2474       }      
2475
2476       cout << "Provides: " << endl;
2477       for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
2478       {
2479          cout << Cur.VerStr() << " - ";
2480          for (pkgCache::PrvIterator Prv = Cur.ProvidesList(); Prv.end() != true; Prv++)
2481             cout << Prv.ParentPkg().Name() << " ";
2482          cout << endl;
2483       }
2484       cout << "Reverse Provides: " << endl;
2485       for (pkgCache::PrvIterator Prv = Pkg.ProvidesList(); Prv.end() != true; Prv++)
2486          cout << Prv.OwnerPkg().Name() << " " << Prv.OwnerVer().VerStr() << endl;            
2487    }
2488
2489    return true;
2490 }
2491                                                                         /*}}}*/
2492 // DisplayRecord - Displays the complete record for the package         /*{{{*/
2493 // ---------------------------------------------------------------------
2494 /* This displays the package record from the proper package index file. 
2495    It is not used by DumpAvail for performance reasons. */
2496 bool DisplayRecord(pkgCache::VerIterator V)
2497 {
2498    // Find an appropriate file
2499    pkgCache::VerFileIterator Vf = V.FileList();
2500    for (; Vf.end() == false; Vf++)
2501       if ((Vf.File()->Flags & pkgCache::Flag::NotSource) == 0)
2502          break;
2503    if (Vf.end() == true)
2504       Vf = V.FileList();
2505       
2506 // CNC:2002-07-24
2507 #if HAVE_RPM
2508    pkgRecords Recs(*GCache);
2509    pkgRecords::Parser &P = Recs.Lookup(Vf);
2510    const char *Start;
2511    const char *End;
2512    P.GetRec(Start,End);
2513    cout << string(Start,End-Start) << endl;
2514 #else
2515    // Check and load the package list file
2516    pkgCache::PkgFileIterator I = Vf.File();
2517    if (I.IsOk() == false)
2518       return _error->Error(_("Package file %s is out of sync."),I.FileName());
2519    
2520    FileFd PkgF(I.FileName(),FileFd::ReadOnly);
2521    if (_error->PendingError() == true)
2522       return false;
2523    
2524    // Read the record and then write it out again.
2525    unsigned char *Buffer = new unsigned char[GCache->HeaderP->MaxVerFileSize+1];
2526    Buffer[V.FileList()->Size] = '\n';
2527    if (PkgF.Seek(V.FileList()->Offset) == false ||
2528        PkgF.Read(Buffer,V.FileList()->Size) == false ||
2529        fwrite(Buffer,1,V.FileList()->Size+1,stdout) < V.FileList()->Size+1)
2530    {
2531       delete [] Buffer;
2532       return false;
2533    }
2534    
2535    delete [] Buffer;
2536 #endif
2537
2538    return true;
2539 }
2540                                                                         /*}}}*/
2541 // Search - Perform a search                                            /*{{{*/
2542 // ---------------------------------------------------------------------
2543 /* This searches the package names and pacakge descriptions for a pattern */
2544 struct ExVerFile
2545 {
2546    pkgCache::VerFile *Vf;
2547    bool NameMatch;
2548 };
2549
2550 bool Search(CommandLine &CmdL)
2551 {
2552    if (CheckHelp(CmdL) == true)
2553       return true;
2554
2555    pkgCache &Cache = *GCache;
2556    bool ShowFull = _config->FindB("APT::Cache::ShowFull",false);
2557    bool NamesOnly = _config->FindB("APT::Cache::NamesOnly",false);
2558    unsigned NumPatterns = CmdL.FileSize() -1;
2559    
2560    pkgDepCache::Policy Plcy;
2561    
2562    // Make sure there is at least one argument
2563    if (NumPatterns < 1)
2564       return _error->Error(_("You must give exactly one pattern"));
2565    
2566    // Compile the regex pattern
2567    regex_t *Patterns = new regex_t[NumPatterns];
2568    memset(Patterns,0,sizeof(*Patterns)*NumPatterns);
2569    for (unsigned I = 0; I != NumPatterns; I++)
2570    {
2571       if (regcomp(&Patterns[I],CmdL.FileList[I+1],REG_EXTENDED | REG_ICASE | 
2572                   REG_NOSUB) != 0)
2573       {
2574          for (; I != 0; I--)
2575             regfree(&Patterns[I]);
2576          return _error->Error("Regex compilation error");
2577       }      
2578    }
2579    
2580    // Create the text record parser
2581    pkgRecords Recs(Cache);
2582    if (_error->PendingError() == true)
2583    {
2584       for (unsigned I = 0; I != NumPatterns; I++)
2585          regfree(&Patterns[I]);
2586       return false;
2587    }
2588    
2589    ExVerFile *VFList = new ExVerFile[Cache.HeaderP->PackageCount+1];
2590    memset(VFList,0,sizeof(*VFList)*Cache.HeaderP->PackageCount+1);
2591
2592    // Map versions that we want to write out onto the VerList array.
2593    for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
2594    {
2595       VFList[P->ID].NameMatch = NumPatterns != 0;
2596       for (unsigned I = 0; I != NumPatterns; I++)
2597       {
2598          if (regexec(&Patterns[I],P.Name(),0,0,0) == 0)
2599             VFList[P->ID].NameMatch &= true;
2600          else
2601             VFList[P->ID].NameMatch = false;
2602       }
2603         
2604       // Doing names only, drop any that dont match..
2605       if (NamesOnly == true && VFList[P->ID].NameMatch == false)
2606          continue;
2607          
2608       // Find the proper version to use. 
2609       pkgCache::VerIterator V = Plcy.GetCandidateVer(P);
2610       if (V.end() == false)
2611          VFList[P->ID].Vf = V.FileList();
2612    }
2613       
2614    // Include all the packages that provide matching names too
2615    for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
2616    {
2617       if (VFList[P->ID].NameMatch == false)
2618          continue;
2619
2620       for (pkgCache::PrvIterator Prv = P.ProvidesList() ; Prv.end() == false; Prv++)
2621       {
2622          pkgCache::VerIterator V = Plcy.GetCandidateVer(Prv.OwnerPkg());
2623          if (V.end() == false)
2624          {
2625             VFList[Prv.OwnerPkg()->ID].Vf = V.FileList();
2626             VFList[Prv.OwnerPkg()->ID].NameMatch = true;
2627          }
2628       }
2629    }
2630
2631    LocalitySort(&VFList->Vf,Cache.HeaderP->PackageCount,sizeof(*VFList));
2632
2633    // Iterate over all the version records and check them
2634    for (ExVerFile *J = VFList; J->Vf != 0; J++)
2635    {
2636       pkgRecords::Parser &P = Recs.Lookup(pkgCache::VerFileIterator(Cache,J->Vf));
2637
2638       bool Match = true;
2639       if (J->NameMatch == false)
2640       {
2641          string LongDesc = P.LongDesc();
2642          // CNC 2004-2004-04-10
2643          string ShortDesc = P.ShortDesc();
2644          Match = NumPatterns != 0;
2645          for (unsigned I = 0; I != NumPatterns; I++)
2646          {
2647             if (regexec(&Patterns[I],LongDesc.c_str(),0,0,0) == 0 ||
2648                 regexec(&Patterns[I],ShortDesc.c_str(),0,0,0) == 0)
2649                Match &= true;
2650             else
2651                Match = false;
2652          }
2653       }
2654       
2655       if (Match == true)
2656       {
2657          if (ShowFull == true)
2658          {
2659             const char *Start;
2660             const char *End;
2661             P.GetRec(Start,End);
2662             cout << string(Start,End-Start) << endl;
2663          }       
2664          else
2665             cout << P.Name() << " - " << P.ShortDesc() << endl;
2666       }
2667    }
2668    
2669    delete [] VFList;
2670    for (unsigned I = 0; I != NumPatterns; I++)
2671       regfree(&Patterns[I]);
2672    if (ferror(stdout))
2673        return _error->Error("Write to stdout failed");
2674    return true;
2675 }
2676
2677 // DoList - List packages.                                              /*{{{*/
2678 // ---------------------------------------------------------------------
2679 /* */
2680 bool DoList(CommandLine &CmdL)
2681 {
2682    if (CheckHelp(CmdL) == true)
2683       return true;
2684
2685    CacheFile &Cache = *GCache;
2686
2687    bool MatchAll = (CmdL.FileSize() == 1);
2688    bool ShowUpgradable = _config->FindB("APT::Cache::ShowUpgradable", false);
2689    bool ShowInstalled = _config->FindB("APT::Cache::ShowInstalled", false);
2690
2691    const char **PatternList = &CmdL.FileList[1];
2692    int NumPatterns = CmdL.FileSize()-1;
2693
2694    bool ShowVersion = _config->FindB("APT::Cache::ShowVersion", false);
2695    bool ShowSummary = _config->FindB("APT::Cache::ShowSummary", false);
2696
2697    const char *PkgName;
2698    vector<int> Matches(Cache->Head().PackageCount);
2699    size_t NumMatches = 0;
2700    size_t Len = 0, NameMaxLen = 0, VerMaxLen = 0;
2701    bool Matched;
2702    for (unsigned int J = 0; J < Cache->Head().PackageCount; J++)
2703    {
2704       Matched = false;
2705       pkgCache::PkgIterator Pkg(Cache,Cache.List[J]);
2706       if (Pkg->VersionList == 0)
2707          continue;
2708       if (ShowInstalled && Pkg->CurrentVer == 0)
2709          continue;
2710       if (ShowUpgradable &&
2711           (Pkg->CurrentVer == 0 || Cache[Pkg].Upgradable() == false))
2712          continue;
2713       PkgName = Pkg.Name();
2714       if (MatchAll == true)
2715          Matched = true;
2716       else for (int i=0; i != NumPatterns; i++) {
2717          if (fnmatch(PatternList[i], PkgName, 0) == 0) {
2718             Matched = true;
2719             break;
2720          }
2721       }
2722       if (Matched == true) {
2723          Matches[NumMatches++] = J;
2724          Len = strlen(PkgName);
2725          if (Len > NameMaxLen)
2726             NameMaxLen = Len;
2727          if (ShowVersion == true && Pkg->CurrentVer != 0) {
2728             Len = strlen(Pkg.CurrentVer().VerStr());
2729             if (Len > VerMaxLen)
2730                VerMaxLen = Len;
2731          }
2732       }
2733    }
2734
2735    if (NumMatches == 0)
2736       return true;
2737
2738    if (ShowVersion == true) {
2739       const char *NameLabel = _("Name");
2740       const char *InstalledLabel = _("Installed");
2741       const char *CandidateLabel = _("Candidate");
2742       size_t NameLen = strlen(NameLabel);
2743       size_t InstalledLen = strlen(InstalledLabel);
2744       size_t CandidateLen = strlen(CandidateLabel);
2745
2746       unsigned int FirstColumn = NameMaxLen+2;
2747       if (FirstColumn < NameLen+2)
2748          FirstColumn = NameLen+2;
2749
2750       unsigned int SecondColumn = VerMaxLen+2;
2751       if (SecondColumn < InstalledLen+2)
2752          SecondColumn = InstalledLen+2;
2753
2754       vector<char> BlankFirst(FirstColumn+1,' ');
2755       BlankFirst[FirstColumn] = 0;
2756
2757       vector<char> BlankSecond(SecondColumn+1,' ');
2758       BlankSecond[SecondColumn] = 0;
2759
2760       vector<char> Bar(ScreenWidth+1,'-');
2761       Bar[ScreenWidth] = 0;
2762
2763       c2out << NameLabel << &BlankFirst[NameLen]
2764             << InstalledLabel << &BlankSecond[InstalledLen]
2765             << CandidateLabel << endl;
2766       c2out << &Bar[ScreenWidth-NameLen] << &BlankFirst[NameLen]
2767             << &Bar[ScreenWidth-InstalledLen] << &BlankSecond[InstalledLen]
2768             << &Bar[ScreenWidth-CandidateLen] << endl;
2769
2770       const char *Str;
2771       size_t StrLen;
2772       for (unsigned int K = 0; K != NumMatches; K++) {
2773          pkgCache::PkgIterator Pkg(Cache,Cache.List[Matches[K]]);
2774          Str = Pkg.Name();
2775          StrLen = strlen(Str);
2776          c2out << Str << &BlankFirst[StrLen];
2777          if (Pkg->CurrentVer != 0) {
2778             Str = Pkg.CurrentVer().VerStr();
2779             StrLen = strlen(Str);
2780             if (Len < SecondColumn-1)
2781                c2out << Str << &BlankSecond[StrLen];
2782             else
2783                c2out << Str << " ";
2784          } else {
2785             c2out << "-" << &BlankSecond[1];
2786          }
2787          Str = "-";
2788          if (Cache[Pkg].CandidateVer != 0) {
2789             Str = Cache[Pkg].CandidateVerIter(Cache).VerStr();
2790             if (Pkg->CurrentVer != 0 &&
2791                 strcmp(Str, Pkg.CurrentVer().VerStr()) == 0)
2792                Str = "-";
2793          }
2794          c2out << Str << endl;
2795       }
2796    } else if (ShowSummary == true) {
2797       pkgRecords Recs(Cache);
2798       if (_error->PendingError() == true)
2799          return false;
2800       for (unsigned int K = 0; K != NumMatches; K++) {
2801          pkgCache::PkgIterator Pkg(Cache,Cache.List[Matches[K]]);
2802          pkgRecords::Parser &Parse = Recs.Lookup(Pkg.VersionList().FileList());
2803          c2out << Pkg.Name() << " - " << Parse.ShortDesc() << endl;
2804       }
2805    } else {
2806       unsigned int PerLine = ScreenWidth/(NameMaxLen+2);
2807       if (PerLine == 0) PerLine = 1;
2808       unsigned int ColumnLen = ScreenWidth/PerLine;
2809       unsigned int NumLines = (NumMatches+PerLine-1)/PerLine;
2810       vector<char> Blank(ColumnLen+1,' ');
2811       Blank[ColumnLen] = 0;
2812
2813       const char *Str;
2814       size_t StrLen;
2815       unsigned int K;
2816       for (unsigned int Line = 0; Line != NumLines; Line++) {
2817          for (unsigned int Entry = 0; Entry != PerLine; Entry++) {
2818             K = Line+(Entry*NumLines);
2819             if (K >= NumMatches)
2820                break;
2821             pkgCache::PkgIterator Pkg(Cache,Cache.List[Matches[K]]);
2822             Str = Pkg.Name();
2823             StrLen = strlen(Str);
2824             if (Len < ColumnLen-1)
2825                c2out << Str << &Blank[StrLen];
2826             else
2827                c2out << Str << " ";
2828          }
2829          c2out << endl;
2830       }
2831    }
2832    
2833    return true;
2834 }
2835                                                                         /*}}}*/
2836 // ShowPackage - Dump the package record to the screen                  /*{{{*/
2837 // ---------------------------------------------------------------------
2838 /* */
2839 bool ShowPackage(CommandLine &CmdL)
2840 {   
2841    if (CheckHelp(CmdL) == true)
2842       return true;
2843
2844    pkgCache &Cache = *GCache;
2845    pkgDepCache::Policy Plcy;
2846
2847    unsigned found = 0;
2848    
2849    for (const char **I = CmdL.FileList + 1; *I != 0; I++)
2850    {
2851       pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
2852       if (Pkg.end() == true)
2853       {
2854          _error->Warning(_("Unable to locate package %s"),*I);
2855          continue;
2856       }
2857
2858       ++found;
2859
2860       // Find the proper version to use.
2861       if (_config->FindB("APT::Cache::AllVersions","true") == true)
2862       {
2863          pkgCache::VerIterator V;
2864          for (V = Pkg.VersionList(); V.end() == false; V++)
2865          {
2866             if (DisplayRecord(V) == false)
2867                return false;
2868          }
2869       }
2870       else
2871       {
2872          pkgCache::VerIterator V = Plcy.GetCandidateVer(Pkg);
2873          if (V.end() == true || V.FileList().end() == true)
2874             continue;
2875          if (DisplayRecord(V) == false)
2876             return false;
2877       }      
2878    }
2879
2880    if (found > 0)
2881         return true;
2882    return _error->Error(_("No packages found"));
2883 }
2884                                                                         /*}}}*/
2885 // --- End of stuff from apt-cache.
2886
2887
2888 // ShowHelp - Show a help screen                                        /*{{{*/
2889 // ---------------------------------------------------------------------
2890 /* */
2891 bool ShowHelp(CommandLine &CmdL)
2892 {
2893    if (CheckHelp(CmdL) == true)
2894       return true;
2895
2896    if (CmdL.FileSize() > 1) {
2897       CommandHelp(CmdL.FileList[1]);
2898       return true;
2899    }
2900
2901    ioprintf(cout,_("%s %s for %s %s compiled on %s %s\n"),PACKAGE,VERSION,
2902             COMMON_OS,COMMON_CPU,__DATE__,__TIME__);
2903             
2904    if (_config->FindB("version") == true)
2905    {
2906       cout << _("Supported Modules:") << endl;
2907       
2908       for (unsigned I = 0; I != pkgVersioningSystem::GlobalListLen; I++)
2909       {
2910          pkgVersioningSystem *VS = pkgVersioningSystem::GlobalList[I];
2911          if (_system != 0 && _system->VS == VS)
2912             cout << '*';
2913          else
2914             cout << ' ';
2915          cout << "Ver: " << VS->Label << endl;
2916          
2917          /* Print out all the packaging systems that will work with 
2918             this VS */
2919          for (unsigned J = 0; J != pkgSystem::GlobalListLen; J++)
2920          {
2921             pkgSystem *Sys = pkgSystem::GlobalList[J];
2922             if (_system == Sys)
2923                cout << '*';
2924             else
2925                cout << ' ';
2926             if (Sys->VS->TestCompatibility(*VS) == true)
2927                cout << "Pkg:  " << Sys->Label << " (Priority " << Sys->Score(*_config) << ")" << endl;
2928          }
2929       }
2930       
2931       for (unsigned I = 0; I != pkgSourceList::Type::GlobalListLen; I++)
2932       {
2933          pkgSourceList::Type *Type = pkgSourceList::Type::GlobalList[I];
2934          cout << " S.L: '" << Type->Name << "' " << Type->Label << endl;
2935       }      
2936       
2937       for (unsigned I = 0; I != pkgIndexFile::Type::GlobalListLen; I++)
2938       {
2939          pkgIndexFile::Type *Type = pkgIndexFile::Type::GlobalList[I];
2940          cout << " Idx: " << Type->Label << endl;
2941       }      
2942       
2943       return true;
2944    }
2945    
2946    cout << 
2947     _("\n"
2948       "Main commands:\n"
2949       "   status - Show the current selections\n"
2950       "   install - Install new packages\n"
2951       "   remove - Remove packages\n"
2952       "   keep - Keep packages\n"
2953       "   upgrade - Perform a global upgrade\n"
2954       "   dist-upgrade - Perform a globla distribution upgrade\n"
2955       "   build-dep - Install build-dependencies for source packages\n"
2956 //      "   dselect-upgrade - Follow dselect selections\n"
2957       "   update - Retrieve new lists of packages\n"
2958       "   commit - Apply the changes in the system\n"
2959       "   quit - Leave the APT shell\n"
2960       "\n"
2961       "Auxiliar commands:\n"
2962       "   show - Show a readable record for the package\n"
2963       "   showpkg - Show some general information for a single package\n"
2964       "   list/ls - List packages\n"
2965       "   search - Search the package list for a regex pattern\n"
2966       "   script - Run scripts.\n"
2967       "   depends - Show raw dependency information for a package\n"
2968       "   whatdepends - Show raw dependency information on a package\n"
2969       // "   rdepends - Show reverse dependency information for a package\n"
2970       "   check - Verify that there are no broken dependencies\n"
2971       "   unmet - Show unmet dependencies\n"
2972       "   clean - Erase downloaded archive files\n"
2973       "   autoclean - Erase old downloaded archive files\n"
2974       "\n"
2975       "For more information type \"help <cmd>\" or \"<cmd> [-h|--help]\".\n"
2976       "\n"
2977       "                       This APT has Super Cow Powers.\n");
2978    return true;
2979 }
2980
2981 void CommandHelp(const char *Name)
2982 {
2983    unsigned long Hash = 0;
2984    for (const char *p=Name; *p; p++)
2985       Hash = 5*Hash + *p;
2986    switch (Hash%1000000) {
2987       case 73823: // install
2988          c2out << _(
2989             "Usage: install [options] pkg1[=ver] [pkg2 ...]\n"
2990             "\n"
2991             "Try to mark the given packages for installation (new packages,\n"
2992             "upgrades or downgrades) changing other packages if necessary.\n"
2993             "\n"
2994             "Options:\n"
2995             "  -h  This help text.\n"
2996             "  -y  Assume Yes to all queries and do not prompt\n"
2997             "  -f  Attempt to continue if the integrity check fails\n"
2998             "  -m  Attempt to continue if archives are unlocatable\n"
2999             "  -D  When removing packages, remove dependencies as possible\n"
3000             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
3001             "\n"
3002          );
3003          break;
3004
3005       case 436466: // remove
3006          c2out << _(
3007             "Usage: remove [options] pkg1 [pkg2 ...]\n"
3008             "\n"
3009             "Try to mark the given packages for deletion, changing other\n"
3010             "packages if necessary.\n"
3011             "\n"
3012             "Options:\n"
3013             "  -h  This help text.\n"
3014             "  -y  Assume Yes to all queries and do not prompt\n"
3015             "  -f  Attempt to continue if the integrity check fails\n"
3016             "  -m  Attempt to continue if archives are unlocatable\n"
3017             "  -D  When removing packages, remove dependencies as possible\n"
3018             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
3019             "\n"
3020          );
3021          break;
3022
3023       case 16517: // keep
3024          c2out << _(
3025             "Usage: keep [options] pkg1 [pkg2 ...]\n"
3026             "\n"
3027             "Try to keep the given packages, currently marked for deletion\n"
3028             "or installation, in the system, changing other packages if\n"
3029             "necessary.\n"
3030             "\n"
3031             "Options:\n"
3032             "  -h  This help text.\n"
3033             "  -y  Assume Yes to all queries and do not prompt\n"
3034             "  -f  Attempt to continue if the integrity check fails\n"
3035             "  -m  Attempt to continue if archives are unlocatable\n"
3036             "  -D  When removing packages, remove dependencies as possible\n"
3037             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
3038             "\n"
3039          );
3040          break;
3041
3042       case 259776: // upgrade
3043          c2out << _(
3044             "Usage: upgrade [options]\n"
3045             "\n"
3046             "Perform a global upgrade.\n"
3047             "\n"
3048             "Options:\n"
3049             "  -h  This help text.\n"
3050             "  -y  Assume Yes to all queries and do not prompt\n"
3051             "  -f  Attempt to continue if the integrity check fails\n"
3052             "  -m  Attempt to continue if archives are unlocatable\n"
3053             "  -D  When removing packages, remove dependencies as possible\n"
3054             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
3055             "\n"
3056          );
3057
3058       case 900401: // dist-upgrade
3059          c2out << _(
3060             "Usage: dist-upgrade [options]\n"
3061             "\n"
3062             "Perform a global distribution upgrade.\n"
3063             "\n"
3064             "Options:\n"
3065             "  -h  This help text.\n"
3066             "  -y  Assume Yes to all queries and do not prompt\n"
3067             "  -f  Attempt to continue if the integrity check fails\n"
3068             "  -m  Attempt to continue if archives are unlocatable\n"
3069             "  -D  When removing packages, remove dependencies as possible\n"
3070             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
3071             "\n"
3072          );
3073
3074       case 209563: // showpkg
3075          c2out << _(
3076             "Usage: showpkg [options] pkg1 [pkg2 ...]\n"
3077             "\n"
3078             "Show some general information for the given packages.\n"
3079             "\n"
3080             "Options:\n"
3081             "  -h  This help text.\n"
3082             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
3083             "\n"
3084          );
3085          break;
3086
3087       case 17649: // show
3088          c2out << _(
3089             "Usage: show [options] pkg1 [pkg2 ...]\n"
3090             "\n"
3091             "Show a readable record for the given packages.\n"
3092             "\n"
3093             "Options:\n"
3094             "  -h  This help text.\n"
3095             "  -a  Show information about all versions.\n"
3096             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
3097             "\n"
3098          );
3099          break;
3100
3101       case 964115: // depends
3102          c2out << _(
3103             "Usage: depends [options] pkg1 [pkg2 ...]\n"
3104             "\n"
3105             "Show dependency relations for the given packages.\n"
3106             "\n"
3107             "Options:\n"
3108             "  -h  This help text.\n"
3109             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
3110             "\n"
3111          );
3112          break;
3113
3114       case 151615: // whatdepends
3115          c2out << _(
3116             "Usage: whatdepends [options] pkg1 [pkg2 ...]\n"
3117             "\n"
3118             "Show dependency relations on the given packages.\n"
3119             "\n"
3120             "Options:\n"
3121             "  -h  This help text.\n"
3122             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
3123             "\n"
3124          );
3125          break;
3126
3127       case 90221: // unmet
3128          c2out << _(
3129             "Usage: unmet [options]\n"
3130             "\n"
3131             "Show unsolvable relations in the cache.\n"
3132             "\n"
3133             "Options:\n"
3134             "  -h  This help text.\n"
3135             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
3136             "\n"
3137          );
3138          break;
3139
3140       case 438074: // search
3141          c2out << _(
3142             "Usage: search [options] <regex>\n"
3143             "\n"
3144             "Search for the given regular expression in package names and\n"
3145             "descriptions.\n"
3146             "\n"
3147             "Options:\n"
3148             "  -h  This help text.\n"
3149             "  -n  Search only in package names.\n"
3150             "  -f  Show full records for found packages.\n"
3151             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
3152             "\n"
3153          );
3154          break;
3155
3156       case 16816: // list
3157       case 655: // ls
3158          c2out << _(
3159             "Usage: list/ls [options] [pattern ...]\n"
3160             "\n"
3161             "List packages matching the given patterns, or all packages if\n"
3162             "no pattern is given. Wildcards are accepted.\n"
3163             "\n"
3164             "Options:\n"
3165             "  -h  This help text.\n"
3166             "  -i  Show only installed packages.\n"
3167             "  -u  Show only installed packages that are upgradable.\n"
3168             "  -v  Show installed and candidate versions.\n"
3169             "  -s  Show summaries.\n"
3170             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
3171             "\n"
3172          );
3173          break;
3174
3175       case 395741: // commit
3176          c2out << _(
3177             "Usage: commit [options]\n"
3178             "\n"
3179             "Apply the changes in the system.\n"
3180             "\n"
3181             "Options:\n"
3182             "  -h  This help text.\n"
3183             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
3184             "\n"
3185          );
3186          break;
3187
3188       case 438801: // script
3189          c2out << _(
3190             "Usage: script [options] script1 [script2]\n"
3191             "\n"
3192             "Run the given scripts.\n"
3193             "\n"
3194             "Options:\n"
3195             "  -h  This help text.\n"
3196             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
3197             "\n"
3198          );
3199          break;
3200       default:
3201          _error->Error(_("No help for that"));
3202    }
3203 }
3204                                                                         /*}}}*/
3205
3206 bool DoQuit(CommandLine &CmdL)
3207 {
3208    _config->Set("quit", "true");
3209    return true;
3210 }
3211
3212 bool DoCommit(CommandLine &CmdL)
3213 {
3214    if (CheckHelp(CmdL,0) == true)
3215       return true;
3216
3217    if (GCache->CanCommit() == false) {
3218       _error->Error(_("You have no permissions for that"));
3219       return false;
3220    }
3221    return InstallPackages(*GCache,false);
3222 }
3223
3224 bool DoStatus(CommandLine &CmdL)
3225 {
3226    if (CheckHelp(CmdL,0) == true)
3227       return true;
3228
3229    ShowChanges(*GCache);
3230    return true;
3231 }
3232
3233 // GetInitialize - Initialize things for apt-get                        /*{{{*/
3234 // ---------------------------------------------------------------------
3235 /* */
3236 void GetInitialize()
3237 {
3238    _config->Set("quiet",0);
3239    _config->Set("help",false);
3240    _config->Set("APT::Get::Download-Only",false);
3241    _config->Set("APT::Get::Simulate",false);
3242    _config->Set("APT::Get::Assume-Yes",false);
3243    _config->Set("APT::Get::Fix-Broken",false);
3244    _config->Set("APT::Get::Force-Yes",false);
3245    _config->Set("APT::Get::APT::Get::No-List-Cleanup",true);
3246 }
3247                                                                         /*}}}*/
3248 // ReadLine* - readline library stuff                                   /*{{{*/
3249 // ---------------------------------------------------------------------
3250 /* */
3251 char *ReadLineCompCommands(const char *Text, int State)
3252 {
3253    static char *Commands[] =  {"update", "upgrade", "install", "remove",
3254          "keep", "dist-upgrade", "dselect-upgrade", "build-dep", "clean",
3255          "autoclean", "check", "help", "commit", "exit", "quit", "status",
3256          "showpkg", "unmet", "search", "depends", "whatdepends", "rdepends",
3257          "show", "script", 0};
3258    static int Last;
3259    static size_t Len;
3260    if (State == 0) {
3261       Last = 0;
3262       Len = strlen(Text);
3263    }
3264    const char *Cmd;
3265    while ((Cmd = Commands[Last++])) {
3266       if (strncmp(Cmd, Text, Len) == 0)
3267          return strdup(Cmd);
3268    }
3269    return NULL;
3270 }
3271
3272 static int CompPackagesMode;
3273
3274 char *ReadLineCompPackages(const char *Text, int State)
3275 {
3276    CacheFile &Cache = *GCache;
3277    static pkgCache::PkgIterator Pkg;
3278    static size_t Len;
3279    if (State == 0) {
3280       Pkg = Cache->PkgBegin();
3281       Len = strlen(Text);
3282    } else {
3283       Pkg++;
3284    }
3285    const char *Name;
3286    for (; Pkg.end() == false; Pkg++) {
3287       Name = Pkg.Name();
3288       if (Pkg->VersionList == 0) {
3289          continue;
3290       } else if (CompPackagesMode == MODE_REMOVE) {
3291          if (Pkg->CurrentVer == 0)
3292             continue;
3293       } else if (CompPackagesMode == MODE_KEEP) {
3294          if (Cache[Pkg].Delete() == false && Cache[Pkg].Install() == false)
3295             continue;
3296       }
3297       if (strncmp(Name, Text, Len) == 0)
3298          return strdup(Name);
3299    }
3300    return NULL;
3301 }
3302
3303 static const char *CompVersionName;
3304
3305 char *ReadLineCompVersion(const char *Text, int State)
3306 {
3307    CacheFile &Cache = *GCache;
3308    static pkgCache::VerIterator Ver;
3309    static int Len;
3310    if (State == 0) {
3311       pkgCache::PkgIterator Pkg = Cache->FindPkg(CompVersionName);
3312       if (Pkg.end() == true)
3313          return NULL;
3314       Ver = Pkg.VersionList();
3315       Len = strlen(Text);
3316    } else {
3317       Ver++;
3318    }
3319    const char *Version;
3320    for (; Ver.end() == false; Ver++) {
3321       Version = Ver.VerStr();
3322       if (strncmp(Version, Text, Len) == 0)
3323          return strdup(Version);
3324    }
3325    return NULL;
3326 }
3327
3328
3329 unsigned long ReadLineHashCmd(const char *Cmd, const char *CmdEnd)
3330 {
3331    unsigned long Hash = 0;
3332    for (; Cmd != CmdEnd; Cmd++)
3333       Hash = 5*Hash + *Cmd;
3334    return Hash;
3335 }
3336    
3337 char **ReadLineCompletion(const char *Text, int Start, int End)
3338 {
3339    char **Matches = (char **)NULL;
3340    char *Cmd = rl_line_buffer;
3341    int Pos = 0;
3342    for (; *Cmd != 0 && isspace(*Cmd); Pos++, Cmd++);
3343    rl_attempted_completion_over = 1;
3344    if (Start == Pos)
3345       Matches = rl_completion_matches(Text, ReadLineCompCommands);
3346    else {
3347       char *CmdEnd = Cmd;
3348       while (!isspace(*CmdEnd)) CmdEnd++;
3349       CompPackagesMode = -1;
3350       switch (ReadLineHashCmd(Cmd,CmdEnd)) {
3351          case 2073823: // install
3352             if (*(rl_line_buffer+Start-1) == '=') {
3353                const char *NameEnd = rl_line_buffer+Start-1;
3354                const char *NameStart = NameEnd-1;
3355                while (!isspace(*NameStart)) NameStart--;
3356                if (++NameStart == NameEnd)
3357                   return NULL;
3358                string PkgName(NameStart, NameEnd-NameStart);
3359                CompVersionName = PkgName.c_str();
3360                Matches = rl_completion_matches(Text, ReadLineCompVersion);
3361             } else {
3362                Matches = rl_completion_matches(Text, ReadLineCompPackages);
3363             }
3364             break;
3365
3366          case 436466: // remove
3367             CompPackagesMode = MODE_REMOVE;
3368          case 16517: // keep
3369             if (CompPackagesMode == -1)
3370                CompPackagesMode = MODE_KEEP;
3371          case 2209563: // showpkg
3372          case 17649: // show
3373          case 16816: // list
3374          case 655: // ls
3375          case 1964115: // depends
3376          case 1414151615: // whatdepends
3377          case 10870365: // rdepends
3378             Matches = rl_completion_matches(Text, ReadLineCompPackages);
3379             break;
3380
3381          default:
3382             break;
3383       }
3384    }
3385    return Matches;
3386 }
3387
3388 string ReadLineHistoryFile()
3389 {
3390    string Path;
3391    const char *Dir = getenv("HOME");
3392    if (Dir != NULL) {
3393       Path = Dir;
3394       Path += "/.apt_history";
3395    }
3396    return Path;
3397 }
3398
3399 void ReadLineInit()
3400 {
3401    rl_readline_name = "APTShell";
3402    rl_attempted_completion_function = ReadLineCompletion;
3403    string History = ReadLineHistoryFile();
3404    if (History.empty() == false)
3405       read_history_range(History.c_str(), 0, -1);
3406 }
3407
3408 void ReadLineFinish()
3409 {
3410    string History = ReadLineHistoryFile();
3411    if (History.empty() == false)
3412       write_history(History.c_str());
3413 }
3414                                                                         /*}}}*/
3415
3416 CommandLine::Args *CommandArgs(const char *Name)
3417 {
3418    static CommandLine::Args ChangeCacheArgs[] = {
3419       {'h',"help","help",0},
3420       {'q',"quiet","quiet",CommandLine::IntLevel},
3421       {'q',"silent","quiet",CommandLine::IntLevel},
3422       {'y',"yes","APT::Get::Assume-Yes",0},
3423       {'y',"assume-yes","APT::Get::Assume-Yes",0},      
3424       {'s',"simulate","APT::Get::Simulate",0},
3425       {'s',"just-print","APT::Get::Simulate",0},
3426       {'s',"recon","APT::Get::Simulate",0},
3427       {'s',"dry-run","APT::Get::Simulate",0},
3428       {'s',"no-act","APT::Get::Simulate",0},
3429       {'f',"fix-broken","APT::Get::Fix-Broken",0},
3430       {'D',"remove-deps","APT::Remove-Depends",0}, // CNC:2002-08-01
3431       {'V',"verbose-versions","APT::Get::Show-Versions",0},
3432       {'t',"target-release","APT::Default-Release",CommandLine::HasArg},
3433       {'t',"default-release","APT::Default-Release",CommandLine::HasArg},
3434       {0,"reinstall","APT::Get::ReInstall",0},
3435       {0,"upgrade","APT::Get::upgrade",0},
3436       {0,"force-yes","APT::Get::Force-Yes",0},
3437       {0,"ignore-hold","APT::Ignore-Hold",0},      
3438       {0,"purge","APT::Get::Purge",0},
3439       {0,"remove","APT::Get::Remove",0},
3440       {0,"arch-only","APT::Get::Arch-Only",0},
3441       {'c',"config-file",0,CommandLine::ConfigFile},
3442       {'o',"option",0,CommandLine::ArbItem},
3443       {0,0,0,0}};
3444
3445    static CommandLine::Args CommitArgs[] = {
3446       {'h',"help","help",0},
3447       {'q',"quiet","quiet",CommandLine::IntLevel},
3448       {'q',"silent","quiet",CommandLine::IntLevel},
3449       {'y',"yes","APT::Get::Assume-Yes",0},
3450       {'y',"assume-yes","APT::Get::Assume-Yes",0},      
3451       {'d',"download-only","APT::Get::Download-Only",0},
3452       {'s',"simulate","APT::Get::Simulate",0},
3453       {'s',"just-print","APT::Get::Simulate",0},
3454       {'s',"recon","APT::Get::Simulate",0},
3455       {'s',"dry-run","APT::Get::Simulate",0},
3456       {'s',"no-act","APT::Get::Simulate",0},
3457       {'m',"ignore-missing","APT::Get::Fix-Missing",0},
3458       {0,"trivial-only","APT::Get::Trivial-Only",0},
3459       {0,"print-uris","APT::Get::Print-URIs",0},
3460       {0,"force-yes","APT::Get::Force-Yes",0},
3461       {0,"download","APT::Get::Download",0},
3462       {0,"fix-missing","APT::Get::Fix-Missing",0},
3463       {'c',"config-file",0,CommandLine::ConfigFile},
3464       {'o',"option",0,CommandLine::ArbItem},
3465       {0,0,0,0}};
3466
3467    static CommandLine::Args ShowArgs[] = {
3468       {'h',"help","help",0},
3469       {'a',"all-versions","APT::Cache::AllVersions",0},
3470       {'n',"names-only","APT::Cache::NamesOnly",0},
3471       {'f',"show-full","APT::Cache::ShowFull",0},
3472       {'c',"config-file",0,CommandLine::ConfigFile},
3473       {'o',"option",0,CommandLine::ArbItem},
3474       {0,0,0,0}};
3475
3476    static CommandLine::Args SearchArgs[] = {
3477       {'h',"help","help",0},
3478       {'n',"names-only","APT::Cache::NamesOnly",0},
3479       {'f',"show-full","APT::Cache::ShowFull",0},
3480       {'c',"config-file",0,CommandLine::ConfigFile},
3481       {'o',"option",0,CommandLine::ArbItem},
3482       {0,0,0,0}};
3483
3484    static CommandLine::Args ListArgs[] = {
3485       {'h',"help","help",0},
3486       {'u',"upgradable","APT::Cache::ShowUpgradable",0},
3487       {'i',"installed","APT::Cache::ShowInstalled",0},
3488       {'v',"version","APT::Cache::ShowVersion",0},
3489       {'s',"summary","APT::Cache::ShowSummary",0},
3490       {'n',"installed","APT::Cache::Installed",0},
3491       {'c',"config-file",0,CommandLine::ConfigFile},
3492       {'o',"option",0,CommandLine::ArbItem},
3493       {0,0,0,0}};
3494
3495    static CommandLine::Args NoArgs[] = {
3496       {'h',"help","help",0},
3497       {'v',"version","version",0},
3498       {'c',"config-file",0,CommandLine::ConfigFile},
3499       {'o',"option",0,CommandLine::ArbItem},
3500       {0,0,0,0}};
3501
3502
3503    unsigned long Hash = 0;
3504    for (const char *p=Name; *p; p++)
3505       Hash = 5*Hash + *p;
3506    switch (Hash%1000000) {
3507       case 73823: // install
3508       case 436466: // remove
3509       case 16517: // keep
3510       case 259776: // upgrade
3511       case 900401: // dist-upgrade
3512          return ChangeCacheArgs;
3513
3514       case 395741: // commit
3515          return CommitArgs;
3516
3517       case 209563: // showpkg
3518       case 17649: // show
3519          return ShowArgs;
3520
3521       case 438074: // search
3522          return SearchArgs;
3523
3524       case 16816: // list
3525       case 655: // ls
3526          return ListArgs;
3527
3528       default:
3529          return NoArgs;
3530    }
3531 }
3532                                                                         /*}}}*/
3533 int main(int argc,const char *argv[])
3534 {
3535    CommandLine::Dispatch Cmds[] = {{"update",&DoUpdate},
3536                                    {"upgrade",&DoUpgrade},
3537                                    {"install",&DoInstall},
3538                                    {"remove",&DoInstall},
3539                                    {"keep",&DoInstall},
3540                                    {"dist-upgrade",&DoDistUpgrade},
3541                                    {"dselect-upgrade",&DoDSelectUpgrade},
3542                                    {"build-dep",&DoBuildDep},
3543                                    {"clean",&DoClean},
3544                                    {"autoclean",&DoAutoClean},
3545                                    {"check",&DoCheck},
3546                                    {"help",&ShowHelp},
3547                                    {"commit",&DoCommit},
3548                                    {"quit",&DoQuit},
3549                                    {"exit",&DoQuit},
3550                                    {"status",&DoStatus},
3551                                    {"script",&DoScript},
3552                                    // apt-cache
3553                                    {"showpkg",&DumpPackage},
3554                                    {"unmet",&UnMet},
3555                                    {"search",&Search},
3556                                    {"list",&DoList},
3557                                    {"ls",&DoList},
3558                                    {"depends",&Depends},
3559                                    {"whatdepends",&WhatDepends},
3560                                    {"rdepends",&RDepends},
3561                                    {"show",&ShowPackage},
3562                                    {0,0}};
3563
3564    // Set up gettext support
3565    setlocale(LC_ALL,"");
3566    textdomain(PACKAGE);
3567
3568    // Parse the command line and initialize the package library
3569    CommandLine CmdL(CommandArgs(""),_config);
3570    if (pkgInitConfig(*_config) == false ||
3571        CmdL.Parse(argc,argv) == false ||
3572        pkgInitSystem(*_config,_system) == false)
3573    {
3574       if (_config->FindB("version") == true)
3575          ShowHelp(CmdL);
3576          
3577       _error->DumpErrors();
3578       return 100;
3579    }
3580
3581    // Deal with stdout not being a tty
3582    if (ttyname(STDOUT_FILENO) == 0 && _config->FindI("quiet",0) < 1)
3583       _config->Set("quiet","1");
3584
3585    // Setup the output streams
3586    c0out.rdbuf(cout.rdbuf());
3587    c1out.rdbuf(cout.rdbuf());
3588    c2out.rdbuf(cout.rdbuf());
3589    if (_config->FindI("quiet",0) > 0)
3590       c0out.rdbuf(devnull.rdbuf());
3591    if (_config->FindI("quiet",0) > 1)
3592       c1out.rdbuf(devnull.rdbuf());
3593
3594    // Setup the signals
3595    signal(SIGPIPE,SIG_IGN);
3596    signal(SIGINT,SIG_IGN);
3597    signal(SIGWINCH,SigWinch);
3598    SigWinch(0);
3599
3600    // Prepare the cache
3601    GCache = new CacheFile();
3602    GCache->Open();
3603
3604    // CNC:2004-02-18
3605    if (_error->empty() == false)
3606    {
3607       bool Errors = _error->PendingError();
3608       _error->DumpErrors();
3609       return Errors == true?100:0;
3610    }
3611
3612    if (GCache->CheckDeps(true) == false) {
3613       c1out << _("There are broken packages. ")
3614             << _("Run `check' to see them.") << endl;
3615       c1out << _("You can try to fix them automatically with `install --fix-broken'.") << endl;
3616    }
3617
3618    // Make a copy of the configuration. Each command will modify its
3619    // own copy of the whole configuration.
3620    Configuration GlobalConfig(*_config);
3621
3622    ReadLineInit();
3623    c1out << _("Welcome to the APT shell. Type \"help\" for more information.") << endl;
3624
3625 // CNC:2003-03-19
3626 #ifdef WITH_LUA
3627    _lua->SetDepCache(*GCache);
3628    _lua->RunScripts("Scripts::AptShell::Init");
3629    _lua->ResetCaches();
3630    bool HasCmdScripts = (_lua->HasScripts("Scripts::AptGet::Command") ||
3631                          _lua->HasScripts("Scripts::AptCache::Command"));
3632 #endif
3633
3634    size_t largc;
3635    const char *largv[1024];
3636    char *line, *p, *q;
3637    largv[0] = "";
3638    while (_config->FindB("quit") == false)
3639    {
3640       if (_error->empty() == false)
3641       {
3642          _error->DumpErrors();
3643          continue;
3644       }
3645       
3646       line = readline(_config->Find("APT::Shell::Prompt", "apt> ").c_str());
3647       if (!line || !*line) {
3648          free(line);
3649          continue;
3650       }
3651       add_history(line);
3652
3653       largc = 1; // CommandLine.Parse() ignores the first option.
3654
3655       // Split the line into arguments, handling quotes.
3656       p = q = line;
3657       // *p = parsed contents, assigned from *q
3658       // *q = buffer checker, copying valid stuff to *p
3659       while (*q != 0)
3660       {
3661          if (largc > sizeof(largv)/sizeof(*largv))
3662          {
3663             _error->Error(_("Exceeded maximum number of command arguments"));
3664             break;
3665          }
3666          while (isspace(*q)) q++;
3667          if (*q == 0)
3668             break;
3669          largv[largc++] = p = q;
3670          while (*q != 0 && !isspace(*q)) {
3671             if (*q == '"' || *q == '\'') {
3672                char quote = *q++;
3673                while (*q != 0) {
3674                   if (*q == quote) {
3675                      q++;
3676                      break;
3677                   } else if (*q == '\\') {
3678                      switch (*(++q)) {
3679                         case '\0':
3680                            break;
3681                         case '\\':
3682                            *p++ = '\\';
3683                            break;
3684                         default:
3685                            *p++ = *q;
3686                            break;
3687                      }
3688                      q++;
3689                   } else {
3690                      *p++ = *q++;
3691                   }
3692                }
3693             } else {
3694                *p++ = *q++;
3695             }
3696          }
3697          if (*q != 0)
3698             q++;
3699          *p++ = 0;
3700       }
3701       if (largc == 1 || _error->empty() == false)
3702          continue;
3703       largv[largc] = 0;
3704       
3705       // Make our own copy of the configuration.
3706       delete _config;
3707       _config = new Configuration(GlobalConfig);
3708
3709       // Prepare the command line
3710       CommandLine CmdL(CommandArgs(largv[1]),_config);
3711       CmdL.Parse(largc,largv);
3712
3713 // CNC:2003-03-19
3714 #ifdef WITH_LUA
3715       if (HasCmdScripts == true && _error->PendingError() == false) {
3716          _lua->SetDepCache(*GCache);
3717          _lua->SetGlobal("command_args", CmdL.FileList);
3718          _lua->SetGlobal("command_consume", 0.0);
3719          _lua->RunScripts("Scripts::AptGet::Command", true);
3720          _lua->RunScripts("Scripts::AptCache::Command", true);
3721          double Consume = _lua->GetGlobalNum("command_consume");
3722          _lua->ResetGlobals();
3723          _lua->ResetCaches();
3724          if (Consume == 1) {
3725             free(line);
3726             continue;
3727          }
3728       }
3729 #endif
3730
3731       if (_error->PendingError() == false)
3732          CmdL.DispatchArg(Cmds);
3733       
3734       free(line);
3735    }
3736
3737    ReadLineFinish();
3738
3739    delete GCache;
3740
3741    // Print any errors or warnings found during parsing
3742    if (_error->empty() == false)
3743    {
3744       bool Errors = _error->PendingError();
3745       _error->DumpErrors();
3746       return Errors == true?100:0;
3747    }
3748    
3749    return 0;   
3750 }
3751
3752 // vim:sts=3:sw=3