- we dont have dselect so we dont need dselect-upgrade either
[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 // DoClean - Remove download archives                                   /*{{{*/
1458 // ---------------------------------------------------------------------
1459 /* */
1460 bool DoClean(CommandLine &CmdL)
1461 {
1462    if (CheckHelp(CmdL,0) == true)
1463       return true;
1464
1465    return cmdDoClean(CmdL);
1466 }
1467                                                                         /*}}}*/
1468 bool DoAutoClean(CommandLine &CmdL)
1469 {
1470    if (CheckHelp(CmdL,0) == true)
1471       return true;
1472
1473    // Lock the archive directory
1474    FileFd Lock;
1475    if (_config->FindB("Debug::NoLocking",false) == false)
1476    {
1477       Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
1478       if (_error->PendingError() == true)
1479          return _error->Error(_("Unable to lock the download directory"));
1480    }
1481    
1482    CacheFile &Cache = *GCache;
1483 #if 0
1484    if (Cache.Open() == false)
1485       return false;
1486 #endif
1487    
1488    LogCleaner Cleaner;
1489    
1490    return Cleaner.Go(_config->FindDir("Dir::Cache::archives"),*Cache) &&
1491       Cleaner.Go(_config->FindDir("Dir::Cache::archives") + "partial/",*Cache);
1492 }
1493                                                                         /*}}}*/
1494 // DoCheck - Perform the check operation                                /*{{{*/
1495 // ---------------------------------------------------------------------
1496 /* Opening automatically checks the system, this command is mostly used
1497    for debugging */
1498 bool DoCheck(CommandLine &CmdL)
1499 {
1500    if (CheckHelp(CmdL,0) == true)
1501       return true;
1502
1503    CacheFile &Cache = *GCache;
1504    AutoRestore StateGuard(Cache);
1505
1506    if (GCache->CheckDeps() == false)
1507       return false;
1508    
1509    return true;
1510 }
1511                                                                         /*}}}*/
1512 // DoBuildDep - Install/removes packages to satisfy build dependencies  /*{{{*/
1513 // ---------------------------------------------------------------------
1514 /* This function will look at the build depends list of the given source 
1515    package and install the necessary packages to make it true, or fail. */
1516 bool DoBuildDep(CommandLine &CmdL)
1517 {
1518    if (CheckHelp(CmdL) == true)
1519       return true;
1520
1521    CacheFile &Cache = *GCache;
1522    if (GCache->CanCommit() == false) {
1523       _error->Error(_("You have no permissions for that"));
1524       return false;
1525    }
1526    
1527    AutoRestore StateGuard(Cache);
1528    
1529    if (GCache->CheckDeps() == false)
1530       return false;
1531
1532    if (CmdL.FileSize() <= 1)
1533       return _error->Error(_("Must specify at least one package to check builddeps for"));
1534    
1535    // Read the source list
1536    pkgSourceList List;
1537    if (List.ReadMainList() == false)
1538       return _error->Error(_("The list of sources could not be read."));
1539    
1540    // Create the text record parsers
1541    pkgRecords Recs(Cache);
1542    pkgSrcRecords SrcRecs(List);
1543    if (_error->PendingError() == true)
1544       return false;
1545
1546    // Create the download object
1547    AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));   
1548    pkgAcquire Fetcher(&Stat);
1549
1550    unsigned J = 0;
1551    for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++)
1552    {
1553       string Src;
1554       pkgSrcRecords::Parser *Last = FindSrc(*I,Recs,SrcRecs,Src,*Cache);
1555       if (Last == 0)
1556          return _error->Error(_("Unable to find a source package for %s"),Src.c_str());
1557             
1558       // Process the build-dependencies
1559       vector<pkgSrcRecords::Parser::BuildDepRec> BuildDeps;
1560       if (Last->BuildDepends(BuildDeps, _config->FindB("APT::Get::Arch-Only",false)) == false)
1561         return _error->Error(_("Unable to get build-dependency information for %s"),Src.c_str());
1562    
1563       // Also ensure that build-essential packages are present
1564       Configuration::Item const *Opts = _config->Tree("APT::Build-Essential");
1565       if (Opts) 
1566          Opts = Opts->Child;
1567       for (; Opts; Opts = Opts->Next)
1568       {
1569          if (Opts->Value.empty() == true)
1570             continue;
1571
1572          pkgSrcRecords::Parser::BuildDepRec rec;
1573          rec.Package = Opts->Value;
1574          rec.Type = pkgSrcRecords::Parser::BuildDependIndep;
1575          rec.Op = 0;
1576          BuildDeps.push_back(rec);
1577       }
1578
1579       if (BuildDeps.size() == 0)
1580       {
1581          ioprintf(c1out,_("%s has no build depends.\n"),Src.c_str());
1582          continue;
1583       }
1584       
1585       // Install the requested packages
1586       unsigned int ExpectedInst = 0;
1587       vector <pkgSrcRecords::Parser::BuildDepRec>::iterator D;
1588       pkgProblemResolver Fix(Cache);
1589       bool skipAlternatives = false; // skip remaining alternatives in an or group
1590       for (D = BuildDeps.begin(); D != BuildDeps.end(); D++)
1591       {
1592          bool hasAlternatives = (((*D).Op & pkgCache::Dep::Or) == pkgCache::Dep::Or);
1593
1594          if (skipAlternatives == true)
1595          {
1596             if (!hasAlternatives)
1597                skipAlternatives = false; // end of or group
1598             continue;
1599          }
1600
1601          if ((*D).Type == pkgSrcRecords::Parser::BuildConflict ||
1602              (*D).Type == pkgSrcRecords::Parser::BuildConflictIndep)
1603          {
1604             pkgCache::PkgIterator Pkg = Cache->FindPkg((*D).Package);
1605             // Build-conflicts on unknown packages are silently ignored
1606             if (Pkg.end() == true)
1607                continue;
1608
1609             pkgCache::VerIterator IV = (*Cache)[Pkg].InstVerIter(*Cache);
1610
1611             /* 
1612              * Remove if we have an installed version that satisfies the 
1613              * version criteria
1614              */
1615             if (IV.end() == false && 
1616                 Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
1617                TryToInstall(Pkg,Cache,Fix,MODE_REMOVE,false,ExpectedInst);
1618          }
1619          else // BuildDep || BuildDepIndep
1620          {
1621             if (_config->FindB("Debug::BuildDeps",false) == true)
1622                  cout << "Looking for " << (*D).Package << "...\n";
1623
1624             pkgCache::PkgIterator Pkg = Cache->FindPkg((*D).Package);
1625
1626             // CNC:2003-11-21 - Try to handle unknown file deps.
1627             if (Pkg.end() == true && (*D).Package[0] == '/')
1628             {
1629                const char *File = (*D).Package.c_str();
1630                Pkg = (*Cache).PkgBegin();
1631                for (; Pkg.end() == false; Pkg++)
1632                {
1633                   // Should we try on all versions?
1634                   pkgCache::VerIterator Ver = (*Cache)[Pkg].CandidateVerIter(*Cache);
1635                   if (Ver.end() == false)
1636                   {
1637                      pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList());
1638                      if (Parse.HasFile(File))
1639                         break;
1640                   }
1641                }
1642             }
1643
1644             if (Pkg.end() == true)
1645             {
1646                if (_config->FindB("Debug::BuildDeps",false) == true)
1647                     cout << " (not found)" << (*D).Package << endl;
1648
1649                if (hasAlternatives)
1650                   continue;
1651
1652                return _error->Error(_("%s dependency for %s cannot be satisfied "
1653                                       "because the package %s cannot be found"),
1654                                     Last->BuildDepType((*D).Type),Src.c_str(),
1655                                     (*D).Package.c_str());
1656             }
1657
1658             /*
1659              * if there are alternatives, we've already picked one, so skip
1660              * the rest
1661              *
1662              * TODO: this means that if there's a build-dep on A|B and B is
1663              * installed, we'll still try to install A; more importantly,
1664              * if A is currently broken, we cannot go back and try B. To fix 
1665              * this would require we do a Resolve cycle for each package we 
1666              * add to the install list. Ugh
1667              */
1668                        
1669             /* 
1670              * If this is a virtual package, we need to check the list of
1671              * packages that provide it and see if any of those are
1672              * installed
1673              */
1674             pkgCache::PrvIterator Prv = Pkg.ProvidesList();
1675             for (; Prv.end() != true; Prv++)
1676             {
1677                if (_config->FindB("Debug::BuildDeps",false) == true)
1678                     cout << "  Checking provider " << Prv.OwnerPkg().Name() << endl;
1679
1680                if ((*Cache)[Prv.OwnerPkg()].InstVerIter(*Cache).end() == false)
1681                   break;
1682             }
1683             
1684             // Get installed version and version we are going to install
1685             pkgCache::VerIterator IV = (*Cache)[Pkg].InstVerIter(*Cache);
1686
1687             if ((*D).Version[0] != '\0') {
1688                  // Versioned dependency
1689
1690                  pkgCache::VerIterator CV = (*Cache)[Pkg].CandidateVerIter(*Cache);
1691
1692                  for (; CV.end() != true; CV++)
1693                  {
1694                       if (Cache->VS().CheckDep(CV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
1695                            break;
1696                  }
1697                  if (CV.end() == true)
1698                    if (hasAlternatives)
1699                    {
1700                       continue;
1701                    }
1702                    else
1703                    {
1704                       return _error->Error(_("%s dependency for %s cannot be satisfied "
1705                                              "because no available versions of package %s "
1706                                              "can satisfy version requirements"),
1707                                            Last->BuildDepType((*D).Type),Src.c_str(),
1708                                            (*D).Package.c_str());
1709                    }
1710             }
1711             else
1712             {
1713                // Only consider virtual packages if there is no versioned dependency
1714                if (Prv.end() == false)
1715                {
1716                   if (_config->FindB("Debug::BuildDeps",false) == true)
1717                      cout << "  Is provided by installed package " << Prv.OwnerPkg().Name() << endl;
1718                   skipAlternatives = hasAlternatives;
1719                   continue;
1720                }
1721             }
1722             if (IV.end() == false)
1723             {
1724                if (_config->FindB("Debug::BuildDeps",false) == true)
1725                   cout << "  Is installed\n";
1726
1727                if (Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
1728                {
1729                   skipAlternatives = hasAlternatives;
1730                   continue;
1731                }
1732
1733                if (_config->FindB("Debug::BuildDeps",false) == true)
1734                   cout << "    ...but the installed version doesn't meet the version requirement\n";
1735
1736                if (((*D).Op & pkgCache::Dep::LessEq) == pkgCache::Dep::LessEq)
1737                {
1738                   return _error->Error(_("Failed to satisfy %s dependency for %s: Installed package %s is too new"),
1739                                        Last->BuildDepType((*D).Type),
1740                                        Src.c_str(),
1741                                        Pkg.Name());
1742                }
1743             }
1744
1745
1746             if (_config->FindB("Debug::BuildDeps",false) == true)
1747                cout << "  Trying to install " << (*D).Package << endl;
1748
1749             if (TryToInstall(Pkg,Cache,Fix,false,false,ExpectedInst) == true)
1750             {
1751                // We successfully installed something; skip remaining alternatives
1752                skipAlternatives = hasAlternatives;
1753                continue;
1754             }
1755             else if (hasAlternatives)
1756             {
1757                if (_config->FindB("Debug::BuildDeps",false) == true)
1758                   cout << "  Unsatisfiable, trying alternatives\n";
1759                continue;
1760             }
1761             else
1762             {
1763                return _error->Error(_("Failed to satisfy %s dependency for %s: %s"),
1764                                     Last->BuildDepType((*D).Type),
1765                                     Src.c_str(),
1766                                     (*D).Package.c_str());
1767             }
1768          }             
1769       }
1770       
1771       Fix.InstallProtect();
1772       if (Fix.Resolve(true) == false)
1773          _error->Discard();
1774       
1775       // Now we check the state of the packages,
1776       if (Cache->BrokenCount() != 0)
1777          return _error->Error(_("Some broken packages were found while trying to process build-dependencies for %s.\n"
1778                                 "You might want to run `apt-get --fix-broken install' to correct these."),*I);
1779    }
1780   
1781    ConfirmChanges(Cache, StateGuard);
1782
1783    return true;
1784 }
1785                                                                         /*}}}*/
1786 // * - Scripting stuff.                                                 /*{{{*/
1787 // ---------------------------------------------------------------------
1788 /* */
1789 bool DoScript(CommandLine &CmdL)
1790 {
1791    if (CheckHelp(CmdL) == true)
1792       return true;
1793
1794    CacheFile &Cache = *GCache;
1795    AutoRestore StateGuard(Cache);
1796
1797    for (const char **I = CmdL.FileList+1; *I != 0; I++)
1798       _config->Set("Scripts::AptShell::Script::", *I);
1799
1800 // CNC:2003-03-19
1801 #ifdef WITH_LUA
1802    _lua->SetDepCache(Cache);
1803    _lua->RunScripts("Scripts::AptShell::Script");
1804    _lua->RunScripts("Scripts::AptGet::Script");
1805    _lua->RunScripts("Scripts::AptCache::Script");
1806    _lua->ResetCaches();
1807 #endif
1808
1809    _config->Clear("Scripts::AptShell::Script");
1810
1811    ConfirmChanges(Cache, StateGuard);
1812
1813    return true;
1814 }
1815
1816                                                                         /*}}}*/
1817
1818 // --- Unchanged stuff from apt-cache.
1819
1820 // LocalitySort - Sort a version list by package file locality          /*{{{*/
1821 // ---------------------------------------------------------------------
1822 /* */
1823 int LocalityCompare(const void *a, const void *b)
1824 {
1825    pkgCache::VerFile *A = *(pkgCache::VerFile **)a;
1826    pkgCache::VerFile *B = *(pkgCache::VerFile **)b;
1827    
1828    if (A == 0 && B == 0)
1829       return 0;
1830    if (A == 0)
1831       return 1;
1832    if (B == 0)
1833       return -1;
1834    
1835    if (A->File == B->File)
1836       return A->Offset - B->Offset;
1837    return A->File - B->File;
1838 }
1839
1840 void LocalitySort(pkgCache::VerFile **begin,
1841                   unsigned long Count,size_t Size)
1842 {   
1843    qsort(begin,Count,Size,LocalityCompare);
1844 }
1845                                                                         /*}}}*/
1846
1847 // Depends - Print out a dependency tree                                /*{{{*/
1848 // ---------------------------------------------------------------------
1849 /* */
1850 bool Depends(CommandLine &CmdL)
1851 {
1852    if (CheckHelp(CmdL) == true)
1853       return true;
1854
1855    pkgCache &Cache = *GCache;
1856    SPtrArray<unsigned> Colours = new unsigned[Cache.Head().PackageCount];
1857    memset(Colours,0,sizeof(*Colours)*Cache.Head().PackageCount);
1858    
1859    for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1860    {
1861       pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
1862       if (Pkg.end() == true)
1863       {
1864          _error->Warning(_("Unable to locate package %s"),*I);
1865          continue;
1866       }
1867       Colours[Pkg->ID] = 1;
1868    }
1869    
1870    bool Recurse = _config->FindB("APT::Cache::RecurseDepends",false);
1871    bool Installed = _config->FindB("APT::Cache::Installed",false);
1872    bool DidSomething;
1873    do
1874    {
1875       DidSomething = false;
1876       for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
1877       {
1878          if (Colours[Pkg->ID] != 1)
1879             continue;
1880          Colours[Pkg->ID] = 2;
1881          DidSomething = true;
1882          
1883          pkgCache::VerIterator Ver = Pkg.VersionList();
1884          if (Ver.end() == true)
1885          {
1886             cout << '<' << Pkg.Name() << '>' << endl;
1887             continue;
1888          }
1889          
1890          // CNC:2003-03-03
1891          cout << Pkg.Name() << "-" << Ver.VerStr() << endl;
1892          
1893          for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
1894          {
1895
1896             pkgCache::PkgIterator Trg = D.TargetPkg();
1897
1898             if((Installed && Trg->CurrentVer != 0) || !Installed)
1899               {
1900
1901                 if ((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or)
1902                   cout << " |";
1903                 else
1904                   cout << "  ";
1905             
1906                 // Show the package
1907                 if (Trg->VersionList == 0)
1908                    cout << D.DepType() << ": <" << Trg.Name() << ">" << endl;
1909                 // CNC:2003-03-03
1910                 else if (D.TargetVer() == 0)
1911                    cout << D.DepType() << ": " << Trg.Name() << endl;
1912                 else
1913                    cout << D.DepType() << ": " << Trg.Name()
1914                         << " " << D.CompType() << " " << D.TargetVer() << endl;
1915             
1916                 if (Recurse == true)
1917                   Colours[D.TargetPkg()->ID]++;
1918
1919               }
1920             
1921             // Display all solutions
1922             SPtrArray<pkgCache::Version *> List = D.AllTargets();
1923             pkgPrioSortList(Cache,List);
1924             for (pkgCache::Version **I = List; *I != 0; I++)
1925             {
1926                pkgCache::VerIterator V(Cache,*I);
1927                if (V != Cache.VerP + V.ParentPkg()->VersionList ||
1928                    V->ParentPkg == D->Package)
1929                   continue;
1930                // CNC:2003-03-03
1931                cout << "    " << V.ParentPkg().Name()
1932                     << "-" << V.VerStr() << endl;
1933                
1934                if (Recurse == true)
1935                   Colours[D.ParentPkg()->ID]++;
1936             }
1937          }
1938       }      
1939    }   
1940    while (DidSomething == true);
1941    
1942    return true;
1943 }
1944                                                                         /*}}}*/
1945 // RDepends - Print out a reverse dependency tree - mbc                 /*{{{*/
1946 // ---------------------------------------------------------------------
1947 /* */
1948 bool RDepends(CommandLine &CmdL)
1949 {
1950    if (CheckHelp(CmdL) == true)
1951       return true;
1952
1953    pkgCache &Cache = *GCache;
1954    SPtrArray<unsigned> Colours = new unsigned[Cache.Head().PackageCount];
1955    memset(Colours,0,sizeof(*Colours)*Cache.Head().PackageCount);
1956    
1957    for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1958    {
1959       pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
1960       if (Pkg.end() == true)
1961       {
1962          _error->Warning(_("Unable to locate package %s"),*I);
1963          continue;
1964       }
1965       Colours[Pkg->ID] = 1;
1966    }
1967    
1968    bool Recurse = _config->FindB("APT::Cache::RecurseDepends",false);
1969    bool Installed = _config->FindB("APT::Cache::Installed",false);
1970    bool DidSomething;
1971    do
1972    {
1973       DidSomething = false;
1974       for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
1975       {
1976          if (Colours[Pkg->ID] != 1)
1977             continue;
1978          Colours[Pkg->ID] = 2;
1979          DidSomething = true;
1980          
1981          pkgCache::VerIterator Ver = Pkg.VersionList();
1982          if (Ver.end() == true)
1983          {
1984             cout << '<' << Pkg.Name() << '>' << endl;
1985             continue;
1986          }
1987          
1988          cout << Pkg.Name() << endl;
1989          
1990          cout << "Reverse Depends:" << endl;
1991          for (pkgCache::DepIterator D = Pkg.RevDependsList(); D.end() == false; D++)
1992          {          
1993             // Show the package
1994             pkgCache::PkgIterator Trg = D.ParentPkg();
1995
1996             if((Installed && Trg->CurrentVer != 0) || !Installed)
1997               {
1998
1999                 if ((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or)
2000                   cout << " |";
2001                 else
2002                   cout << "  ";
2003
2004                 if (Trg->VersionList == 0)
2005                   cout << D.DepType() << ": <" << Trg.Name() << ">" << endl;
2006                 else
2007                   cout << Trg.Name() << endl;
2008
2009                 if (Recurse == true)
2010                   Colours[D.ParentPkg()->ID]++;
2011
2012               }
2013             
2014             // Display all solutions
2015             SPtrArray<pkgCache::Version *> List = D.AllTargets();
2016             pkgPrioSortList(Cache,List);
2017             for (pkgCache::Version **I = List; *I != 0; I++)
2018             {
2019                pkgCache::VerIterator V(Cache,*I);
2020                if (V != Cache.VerP + V.ParentPkg()->VersionList ||
2021                    V->ParentPkg == D->Package)
2022                   continue;
2023                cout << "    " << V.ParentPkg().Name() << endl;
2024                
2025                if (Recurse == true)
2026                   Colours[D.ParentPkg()->ID]++;
2027             }
2028          }
2029       }      
2030    }   
2031    while (DidSomething == true);
2032    
2033    return true;
2034 }
2035
2036                                                                         /*}}}*/
2037 // CNC:2003-02-19
2038 // WhatDepends - Print out a reverse dependency tree                    /*{{{*/
2039 // ---------------------------------------------------------------------
2040 /* */
2041 bool WhatDepends(CommandLine &CmdL)
2042 {
2043    if (CheckHelp(CmdL) == true)
2044       return true;
2045
2046    pkgCache &Cache = *GCache;
2047    SPtrArray<unsigned> Colours = new unsigned[Cache.Head().PackageCount];
2048    memset(Colours,0,sizeof(*Colours)*Cache.Head().PackageCount);
2049    
2050    for (const char **I = CmdL.FileList + 1; *I != 0; I++)
2051    {
2052       pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
2053       if (Pkg.end() == true)
2054       {
2055          _error->Warning(_("Unable to locate package %s"),*I);
2056          continue;
2057       }
2058       Colours[Pkg->ID] = 1;
2059    }
2060    
2061    bool Recurse = _config->FindB("APT::Cache::RecurseDepends",false);
2062    bool DidSomething;
2063    do
2064    {
2065       DidSomething = false;
2066       for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
2067       {
2068          if (Colours[Pkg->ID] != 1)
2069             continue;
2070          Colours[Pkg->ID] = 2;
2071          DidSomething = true;
2072          
2073          pkgCache::VerIterator Ver = Pkg.VersionList();
2074          if (Ver.end() == true)
2075             cout << '<' << Pkg.Name() << '>' << endl;
2076          else
2077             cout << Pkg.Name() << "-" << Ver.VerStr() << endl;
2078
2079          SPtrArray<unsigned> LocalColours = 
2080                      new unsigned[Cache.Head().PackageCount];
2081          memset(LocalColours,0,sizeof(*LocalColours)*Cache.Head().PackageCount);
2082             
2083          // Display all dependencies directly on the package.
2084          for (pkgCache::DepIterator RD = Pkg.RevDependsList();
2085               RD.end() == false; RD++)
2086          {
2087             pkgCache::PkgIterator Parent = RD.ParentPkg();
2088
2089             if (LocalColours[Parent->ID] == 1)
2090                continue;
2091             LocalColours[Parent->ID] = 1;
2092                
2093             if (Ver.end() == false && RD.TargetVer() &&
2094                 Cache.VS->CheckDep(Ver.VerStr(),RD) == false)
2095                continue;
2096
2097             if (Recurse == true && Colours[Parent->ID] == 0)
2098                Colours[Parent->ID] = 1;
2099
2100             pkgCache::VerIterator ParentVer = Parent.VersionList();
2101
2102             // Show the package
2103             cout << "  " << Parent.Name()
2104                  << "-" << ParentVer.VerStr() << endl;
2105
2106             // Display all dependencies from that package that relate
2107             // to the queried package.
2108             for (pkgCache::DepIterator D = ParentVer.DependsList();
2109                  D.end() == false; D++)
2110             {
2111                // If this is a virtual package, there's no provides.
2112                if (Ver.end() == true) {
2113                   // If it's not the same package, and there's no provides
2114                   // skip that package.
2115                   if (D.TargetPkg() != Pkg)
2116                      continue;
2117                } else if (D.TargetPkg() != Pkg ||
2118                           Cache.VS->CheckDep(Ver.VerStr(),D) == false) {
2119                   // Oops. Either it's not the same package, or the
2120                   // version didn't match. Check virtual provides from
2121                   // the queried package version and verify if this
2122                   // dependency matches one of those.
2123                   bool Hit = false;
2124                   for (pkgCache::PrvIterator Prv = Ver.ProvidesList();
2125                        Prv.end() == false; Prv++) {
2126                      if (Prv.ParentPkg() == D.TargetPkg() &&
2127                          (Prv.ParentPkg()->VersionList == 0 ||
2128                           Cache.VS->CheckDep(Prv.ProvideVersion(),D)==false)) {
2129                         Hit = true;
2130                         break;
2131                      }
2132                   }
2133                   if (Hit == false)
2134                      continue;
2135                }
2136
2137                // Bingo!
2138                pkgCache::PkgIterator Trg = D.TargetPkg();
2139                if (Trg->VersionList == 0)
2140                   cout << "    " << D.DepType()
2141                                  << ": <" << Trg.Name() << ">" << endl;
2142                else if (D.TargetVer() == 0)
2143                   cout << "    " << D.DepType()
2144                                  << ": " << Trg.Name() << endl;
2145                else
2146                   cout << "    " << D.DepType()
2147                                  << ": " << Trg.Name()
2148                                  << " " << D.CompType() << " "
2149                                  << D.TargetVer() << endl;
2150
2151                // Display all solutions
2152                SPtrArray<pkgCache::Version *> List = D.AllTargets();
2153                pkgPrioSortList(Cache,List);
2154                for (pkgCache::Version **I = List; *I != 0; I++)
2155                {
2156                   pkgCache::VerIterator V(Cache,*I);
2157                   if (V != Cache.VerP + V.ParentPkg()->VersionList ||
2158                       V->ParentPkg == D->Package)
2159                      continue;
2160                   cout << "      " << V.ParentPkg().Name()
2161                        << "-" << V.VerStr() << endl;
2162                   
2163                   if (Recurse == true)
2164                      Colours[D.ParentPkg()->ID]++;
2165                }
2166             }
2167          }
2168
2169          // Is this a virtual package the user queried directly?
2170          if (Ver.end())
2171             continue;
2172
2173          // Display all dependencies on virtual provides, which were not
2174          // yet shown in the step above.
2175          for (pkgCache::PrvIterator RDPrv = Ver.ProvidesList();
2176               RDPrv.end() == false; RDPrv++) {
2177             for (pkgCache::DepIterator RD = RDPrv.ParentPkg().RevDependsList();
2178                  RD.end() == false; RD++)
2179             {
2180                pkgCache::PkgIterator Parent = RD.ParentPkg();
2181
2182                if (LocalColours[Parent->ID] == 1)
2183                   continue;
2184                LocalColours[Parent->ID] = 1;
2185                   
2186                if (Ver.end() == false &&
2187                    Cache.VS->CheckDep(Ver.VerStr(),RD) == false)
2188                   continue;
2189
2190                if (Recurse == true && Colours[Parent->ID] == 0)
2191                   Colours[Parent->ID] = 1;
2192
2193                pkgCache::VerIterator ParentVer = Parent.VersionList();
2194
2195                // Show the package
2196                cout << "  " << Parent.Name()
2197                     << "-" << ParentVer.VerStr() << endl;
2198
2199                for (pkgCache::DepIterator D = ParentVer.DependsList();
2200                     D.end() == false; D++)
2201                {
2202                   // Go on if it's the same package and version or
2203                   // if it's the same package and has no versions
2204                   // (a virtual package).
2205                   if (D.TargetPkg() != RDPrv.ParentPkg() ||
2206                       (RDPrv.ProvideVersion() != 0 &&
2207                        Cache.VS->CheckDep(RDPrv.ProvideVersion(),D) == false))
2208                      continue;
2209
2210                   // Bingo!
2211                   pkgCache::PkgIterator Trg = D.TargetPkg();
2212                   if (Trg->VersionList == 0)
2213                      cout << "    " << D.DepType()
2214                                     << ": <" << Trg.Name() << ">" << endl;
2215                   else if (D.TargetVer() == 0)
2216                      cout << "    " << D.DepType()
2217                                     << ": " << Trg.Name() << endl;
2218                   else
2219                      cout << "    " << D.DepType()
2220                                     << ": " << Trg.Name()
2221                                     << " " << D.CompType() << " "
2222                                     << D.TargetVer() << endl;
2223
2224                   // Display all solutions
2225                   SPtrArray<pkgCache::Version *> List = D.AllTargets();
2226                   pkgPrioSortList(Cache,List);
2227                   for (pkgCache::Version **I = List; *I != 0; I++)
2228                   {
2229                      pkgCache::VerIterator V(Cache,*I);
2230                      if (V != Cache.VerP + V.ParentPkg()->VersionList ||
2231                          V->ParentPkg == D->Package)
2232                         continue;
2233                      cout << "      " << V.ParentPkg().Name()
2234                           << "-" << V.VerStr() << endl;
2235                      
2236                      if (Recurse == true)
2237                         Colours[D.ParentPkg()->ID]++;
2238                   }
2239                }
2240             }
2241          }
2242       } 
2243    }
2244    while (DidSomething == true);
2245    
2246    return true;
2247 }
2248                                                                         /*}}}*/
2249 // UnMet - Show unmet dependencies                                      /*{{{*/
2250 // ---------------------------------------------------------------------
2251 /* */
2252 bool UnMet(CommandLine &CmdL)
2253 {
2254    if (CheckHelp(CmdL,0) == true)
2255       return true;
2256
2257    pkgCache &Cache = *GCache;
2258    bool Important = _config->FindB("APT::Cache::Important",false);
2259    
2260    for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
2261    {
2262       for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
2263       {
2264          bool Header = false;
2265          for (pkgCache::DepIterator D = V.DependsList(); D.end() == false;)
2266          {
2267             // Collect or groups
2268             pkgCache::DepIterator Start;
2269             pkgCache::DepIterator End;
2270             D.GlobOr(Start,End);
2271             
2272             // Skip conflicts and replaces
2273             if (End->Type != pkgCache::Dep::PreDepends &&
2274                 End->Type != pkgCache::Dep::Depends && 
2275                 End->Type != pkgCache::Dep::Suggests &&
2276                 End->Type != pkgCache::Dep::Recommends)
2277                continue;
2278
2279             // Important deps only
2280             if (Important == true)
2281                if (End->Type != pkgCache::Dep::PreDepends &&
2282                    End->Type != pkgCache::Dep::Depends)
2283                   continue;
2284             
2285             // Verify the or group
2286             bool OK = false;
2287             pkgCache::DepIterator RealStart = Start;
2288             do
2289             {
2290                // See if this dep is Ok
2291                pkgCache::Version **VList = Start.AllTargets();
2292                if (*VList != 0)
2293                {
2294                   OK = true;
2295                   delete [] VList;
2296                   break;
2297                }
2298                delete [] VList;
2299                
2300                if (Start == End)
2301                   break;
2302                Start++;
2303             }
2304             while (1);
2305
2306             // The group is OK
2307             if (OK == true)
2308                continue;
2309             
2310             // Oops, it failed..
2311             if (Header == false)
2312                ioprintf(cout,_("Package %s version %s has an unmet dep:\n"),
2313                         P.Name(),V.VerStr());
2314             Header = true;
2315             
2316             // Print out the dep type
2317             cout << " " << End.DepType() << ": ";
2318
2319             // Show the group
2320             Start = RealStart;
2321             do
2322             {
2323                cout << Start.TargetPkg().Name();
2324                if (Start.TargetVer() != 0)
2325                   cout << " (" << Start.CompType() << " " << Start.TargetVer() <<
2326                   ")";
2327                if (Start == End)
2328                   break;
2329                cout << " | ";
2330                Start++;
2331             }
2332             while (1);
2333             
2334             cout << endl;
2335          }       
2336       }
2337    }   
2338    return true;
2339 }
2340                                                                         /*}}}*/
2341 // DumpPackage - Show a dump of a package record                        /*{{{*/
2342 // ---------------------------------------------------------------------
2343 /* */
2344 bool DumpPackage(CommandLine &CmdL)
2345 {   
2346    if (CheckHelp(CmdL) == true)
2347       return true;
2348
2349    pkgCache &Cache = *GCache;
2350    for (const char **I = CmdL.FileList + 1; *I != 0; I++)
2351    {
2352       pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
2353       if (Pkg.end() == true)
2354       {
2355          _error->Warning(_("Unable to locate package %s"),*I);
2356          continue;
2357       }
2358
2359       cout << "Package: " << Pkg.Name() << endl;
2360       cout << "Versions: " << endl;
2361       for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
2362       {
2363          cout << Cur.VerStr();
2364          for (pkgCache::VerFileIterator Vf = Cur.FileList(); Vf.end() == false; Vf++)
2365             cout << "(" << Vf.File().FileName() << ")";
2366          cout << endl;
2367       }
2368       
2369       cout << endl;
2370       
2371       cout << "Reverse Depends: " << endl;
2372       for (pkgCache::DepIterator D = Pkg.RevDependsList(); D.end() != true; D++)
2373       {
2374          cout << "  " << D.ParentPkg().Name() << ',' << D.TargetPkg().Name();
2375          if (D->Version != 0)
2376             cout << ' ' << DeNull(D.TargetVer()) << endl;
2377          else
2378             cout << endl;
2379       }
2380       
2381       cout << "Dependencies: " << endl;
2382       for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
2383       {
2384          cout << Cur.VerStr() << " - ";
2385          for (pkgCache::DepIterator Dep = Cur.DependsList(); Dep.end() != true; Dep++)
2386             cout << Dep.TargetPkg().Name() << " (" << (int)Dep->CompareOp << " " << DeNull(Dep.TargetVer()) << ") ";
2387          cout << endl;
2388       }      
2389
2390       cout << "Provides: " << endl;
2391       for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
2392       {
2393          cout << Cur.VerStr() << " - ";
2394          for (pkgCache::PrvIterator Prv = Cur.ProvidesList(); Prv.end() != true; Prv++)
2395             cout << Prv.ParentPkg().Name() << " ";
2396          cout << endl;
2397       }
2398       cout << "Reverse Provides: " << endl;
2399       for (pkgCache::PrvIterator Prv = Pkg.ProvidesList(); Prv.end() != true; Prv++)
2400          cout << Prv.OwnerPkg().Name() << " " << Prv.OwnerVer().VerStr() << endl;            
2401    }
2402
2403    return true;
2404 }
2405                                                                         /*}}}*/
2406 // DisplayRecord - Displays the complete record for the package         /*{{{*/
2407 // ---------------------------------------------------------------------
2408 /* This displays the package record from the proper package index file. 
2409    It is not used by DumpAvail for performance reasons. */
2410 bool DisplayRecord(pkgCache::VerIterator V)
2411 {
2412    // Find an appropriate file
2413    pkgCache::VerFileIterator Vf = V.FileList();
2414    for (; Vf.end() == false; Vf++)
2415       if ((Vf.File()->Flags & pkgCache::Flag::NotSource) == 0)
2416          break;
2417    if (Vf.end() == true)
2418       Vf = V.FileList();
2419       
2420 // CNC:2002-07-24
2421 #if HAVE_RPM
2422    pkgRecords Recs(*GCache);
2423    pkgRecords::Parser &P = Recs.Lookup(Vf);
2424    const char *Start;
2425    const char *End;
2426    P.GetRec(Start,End);
2427    cout << string(Start,End-Start) << endl;
2428 #else
2429    // Check and load the package list file
2430    pkgCache::PkgFileIterator I = Vf.File();
2431    if (I.IsOk() == false)
2432       return _error->Error(_("Package file %s is out of sync."),I.FileName());
2433    
2434    FileFd PkgF(I.FileName(),FileFd::ReadOnly);
2435    if (_error->PendingError() == true)
2436       return false;
2437    
2438    // Read the record and then write it out again.
2439    unsigned char *Buffer = new unsigned char[GCache->HeaderP->MaxVerFileSize+1];
2440    Buffer[V.FileList()->Size] = '\n';
2441    if (PkgF.Seek(V.FileList()->Offset) == false ||
2442        PkgF.Read(Buffer,V.FileList()->Size) == false ||
2443        fwrite(Buffer,1,V.FileList()->Size+1,stdout) < V.FileList()->Size+1)
2444    {
2445       delete [] Buffer;
2446       return false;
2447    }
2448    
2449    delete [] Buffer;
2450 #endif
2451
2452    return true;
2453 }
2454                                                                         /*}}}*/
2455 // Search - Perform a search                                            /*{{{*/
2456 // ---------------------------------------------------------------------
2457 /* This searches the package names and pacakge descriptions for a pattern */
2458 struct ExVerFile
2459 {
2460    pkgCache::VerFile *Vf;
2461    bool NameMatch;
2462 };
2463
2464 bool Search(CommandLine &CmdL)
2465 {
2466    if (CheckHelp(CmdL) == true)
2467       return true;
2468
2469    pkgCache &Cache = *GCache;
2470    bool ShowFull = _config->FindB("APT::Cache::ShowFull",false);
2471    bool NamesOnly = _config->FindB("APT::Cache::NamesOnly",false);
2472    unsigned NumPatterns = CmdL.FileSize() -1;
2473    
2474    pkgDepCache::Policy Plcy;
2475    
2476    // Make sure there is at least one argument
2477    if (NumPatterns < 1)
2478       return _error->Error(_("You must give exactly one pattern"));
2479    
2480    // Compile the regex pattern
2481    regex_t *Patterns = new regex_t[NumPatterns];
2482    memset(Patterns,0,sizeof(*Patterns)*NumPatterns);
2483    for (unsigned I = 0; I != NumPatterns; I++)
2484    {
2485       if (regcomp(&Patterns[I],CmdL.FileList[I+1],REG_EXTENDED | REG_ICASE | 
2486                   REG_NOSUB) != 0)
2487       {
2488          for (; I != 0; I--)
2489             regfree(&Patterns[I]);
2490          return _error->Error("Regex compilation error");
2491       }      
2492    }
2493    
2494    // Create the text record parser
2495    pkgRecords Recs(Cache);
2496    if (_error->PendingError() == true)
2497    {
2498       for (unsigned I = 0; I != NumPatterns; I++)
2499          regfree(&Patterns[I]);
2500       return false;
2501    }
2502    
2503    ExVerFile *VFList = new ExVerFile[Cache.HeaderP->PackageCount+1];
2504    memset(VFList,0,sizeof(*VFList)*Cache.HeaderP->PackageCount+1);
2505
2506    // Map versions that we want to write out onto the VerList array.
2507    for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
2508    {
2509       VFList[P->ID].NameMatch = NumPatterns != 0;
2510       for (unsigned I = 0; I != NumPatterns; I++)
2511       {
2512          if (regexec(&Patterns[I],P.Name(),0,0,0) == 0)
2513             VFList[P->ID].NameMatch &= true;
2514          else
2515             VFList[P->ID].NameMatch = false;
2516       }
2517         
2518       // Doing names only, drop any that dont match..
2519       if (NamesOnly == true && VFList[P->ID].NameMatch == false)
2520          continue;
2521          
2522       // Find the proper version to use. 
2523       pkgCache::VerIterator V = Plcy.GetCandidateVer(P);
2524       if (V.end() == false)
2525          VFList[P->ID].Vf = V.FileList();
2526    }
2527       
2528    // Include all the packages that provide matching names too
2529    for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
2530    {
2531       if (VFList[P->ID].NameMatch == false)
2532          continue;
2533
2534       for (pkgCache::PrvIterator Prv = P.ProvidesList() ; Prv.end() == false; Prv++)
2535       {
2536          pkgCache::VerIterator V = Plcy.GetCandidateVer(Prv.OwnerPkg());
2537          if (V.end() == false)
2538          {
2539             VFList[Prv.OwnerPkg()->ID].Vf = V.FileList();
2540             VFList[Prv.OwnerPkg()->ID].NameMatch = true;
2541          }
2542       }
2543    }
2544
2545    LocalitySort(&VFList->Vf,Cache.HeaderP->PackageCount,sizeof(*VFList));
2546
2547    // Iterate over all the version records and check them
2548    for (ExVerFile *J = VFList; J->Vf != 0; J++)
2549    {
2550       pkgRecords::Parser &P = Recs.Lookup(pkgCache::VerFileIterator(Cache,J->Vf));
2551
2552       bool Match = true;
2553       if (J->NameMatch == false)
2554       {
2555          string LongDesc = P.LongDesc();
2556          // CNC 2004-2004-04-10
2557          string ShortDesc = P.ShortDesc();
2558          Match = NumPatterns != 0;
2559          for (unsigned I = 0; I != NumPatterns; I++)
2560          {
2561             if (regexec(&Patterns[I],LongDesc.c_str(),0,0,0) == 0 ||
2562                 regexec(&Patterns[I],ShortDesc.c_str(),0,0,0) == 0)
2563                Match &= true;
2564             else
2565                Match = false;
2566          }
2567       }
2568       
2569       if (Match == true)
2570       {
2571          if (ShowFull == true)
2572          {
2573             const char *Start;
2574             const char *End;
2575             P.GetRec(Start,End);
2576             cout << string(Start,End-Start) << endl;
2577          }       
2578          else
2579             cout << P.Name() << " - " << P.ShortDesc() << endl;
2580       }
2581    }
2582    
2583    delete [] VFList;
2584    for (unsigned I = 0; I != NumPatterns; I++)
2585       regfree(&Patterns[I]);
2586    if (ferror(stdout))
2587        return _error->Error("Write to stdout failed");
2588    return true;
2589 }
2590
2591 // DoList - List packages.                                              /*{{{*/
2592 // ---------------------------------------------------------------------
2593 /* */
2594 bool DoList(CommandLine &CmdL)
2595 {
2596    if (CheckHelp(CmdL) == true)
2597       return true;
2598
2599    CacheFile &Cache = *GCache;
2600
2601    bool MatchAll = (CmdL.FileSize() == 1);
2602    bool ShowUpgradable = _config->FindB("APT::Cache::ShowUpgradable", false);
2603    bool ShowInstalled = _config->FindB("APT::Cache::ShowInstalled", false);
2604
2605    const char **PatternList = &CmdL.FileList[1];
2606    int NumPatterns = CmdL.FileSize()-1;
2607
2608    bool ShowVersion = _config->FindB("APT::Cache::ShowVersion", false);
2609    bool ShowSummary = _config->FindB("APT::Cache::ShowSummary", false);
2610
2611    const char *PkgName;
2612    vector<int> Matches(Cache->Head().PackageCount);
2613    size_t NumMatches = 0;
2614    size_t Len = 0, NameMaxLen = 0, VerMaxLen = 0;
2615    bool Matched;
2616    for (unsigned int J = 0; J < Cache->Head().PackageCount; J++)
2617    {
2618       Matched = false;
2619       pkgCache::PkgIterator Pkg(Cache,Cache.List[J]);
2620       if (Pkg->VersionList == 0)
2621          continue;
2622       if (ShowInstalled && Pkg->CurrentVer == 0)
2623          continue;
2624       if (ShowUpgradable &&
2625           (Pkg->CurrentVer == 0 || Cache[Pkg].Upgradable() == false))
2626          continue;
2627       PkgName = Pkg.Name();
2628       if (MatchAll == true)
2629          Matched = true;
2630       else for (int i=0; i != NumPatterns; i++) {
2631          if (fnmatch(PatternList[i], PkgName, 0) == 0) {
2632             Matched = true;
2633             break;
2634          }
2635       }
2636       if (Matched == true) {
2637          Matches[NumMatches++] = J;
2638          Len = strlen(PkgName);
2639          if (Len > NameMaxLen)
2640             NameMaxLen = Len;
2641          if (ShowVersion == true && Pkg->CurrentVer != 0) {
2642             Len = strlen(Pkg.CurrentVer().VerStr());
2643             if (Len > VerMaxLen)
2644                VerMaxLen = Len;
2645          }
2646       }
2647    }
2648
2649    if (NumMatches == 0)
2650       return true;
2651
2652    if (ShowVersion == true) {
2653       const char *NameLabel = _("Name");
2654       const char *InstalledLabel = _("Installed");
2655       const char *CandidateLabel = _("Candidate");
2656       size_t NameLen = strlen(NameLabel);
2657       size_t InstalledLen = strlen(InstalledLabel);
2658       size_t CandidateLen = strlen(CandidateLabel);
2659
2660       unsigned int FirstColumn = NameMaxLen+2;
2661       if (FirstColumn < NameLen+2)
2662          FirstColumn = NameLen+2;
2663
2664       unsigned int SecondColumn = VerMaxLen+2;
2665       if (SecondColumn < InstalledLen+2)
2666          SecondColumn = InstalledLen+2;
2667
2668       vector<char> BlankFirst(FirstColumn+1,' ');
2669       BlankFirst[FirstColumn] = 0;
2670
2671       vector<char> BlankSecond(SecondColumn+1,' ');
2672       BlankSecond[SecondColumn] = 0;
2673
2674       vector<char> Bar(ScreenWidth+1,'-');
2675       Bar[ScreenWidth] = 0;
2676
2677       c2out << NameLabel << &BlankFirst[NameLen]
2678             << InstalledLabel << &BlankSecond[InstalledLen]
2679             << CandidateLabel << endl;
2680       c2out << &Bar[ScreenWidth-NameLen] << &BlankFirst[NameLen]
2681             << &Bar[ScreenWidth-InstalledLen] << &BlankSecond[InstalledLen]
2682             << &Bar[ScreenWidth-CandidateLen] << endl;
2683
2684       const char *Str;
2685       size_t StrLen;
2686       for (unsigned int K = 0; K != NumMatches; K++) {
2687          pkgCache::PkgIterator Pkg(Cache,Cache.List[Matches[K]]);
2688          Str = Pkg.Name();
2689          StrLen = strlen(Str);
2690          c2out << Str << &BlankFirst[StrLen];
2691          if (Pkg->CurrentVer != 0) {
2692             Str = Pkg.CurrentVer().VerStr();
2693             StrLen = strlen(Str);
2694             if (Len < SecondColumn-1)
2695                c2out << Str << &BlankSecond[StrLen];
2696             else
2697                c2out << Str << " ";
2698          } else {
2699             c2out << "-" << &BlankSecond[1];
2700          }
2701          Str = "-";
2702          if (Cache[Pkg].CandidateVer != 0) {
2703             Str = Cache[Pkg].CandidateVerIter(Cache).VerStr();
2704             if (Pkg->CurrentVer != 0 &&
2705                 strcmp(Str, Pkg.CurrentVer().VerStr()) == 0)
2706                Str = "-";
2707          }
2708          c2out << Str << endl;
2709       }
2710    } else if (ShowSummary == true) {
2711       pkgRecords Recs(Cache);
2712       if (_error->PendingError() == true)
2713          return false;
2714       for (unsigned int K = 0; K != NumMatches; K++) {
2715          pkgCache::PkgIterator Pkg(Cache,Cache.List[Matches[K]]);
2716          pkgRecords::Parser &Parse = Recs.Lookup(Pkg.VersionList().FileList());
2717          c2out << Pkg.Name() << " - " << Parse.ShortDesc() << endl;
2718       }
2719    } else {
2720       unsigned int PerLine = ScreenWidth/(NameMaxLen+2);
2721       if (PerLine == 0) PerLine = 1;
2722       unsigned int ColumnLen = ScreenWidth/PerLine;
2723       unsigned int NumLines = (NumMatches+PerLine-1)/PerLine;
2724       vector<char> Blank(ColumnLen+1,' ');
2725       Blank[ColumnLen] = 0;
2726
2727       const char *Str;
2728       size_t StrLen;
2729       unsigned int K;
2730       for (unsigned int Line = 0; Line != NumLines; Line++) {
2731          for (unsigned int Entry = 0; Entry != PerLine; Entry++) {
2732             K = Line+(Entry*NumLines);
2733             if (K >= NumMatches)
2734                break;
2735             pkgCache::PkgIterator Pkg(Cache,Cache.List[Matches[K]]);
2736             Str = Pkg.Name();
2737             StrLen = strlen(Str);
2738             if (Len < ColumnLen-1)
2739                c2out << Str << &Blank[StrLen];
2740             else
2741                c2out << Str << " ";
2742          }
2743          c2out << endl;
2744       }
2745    }
2746    
2747    return true;
2748 }
2749                                                                         /*}}}*/
2750 // ShowPackage - Dump the package record to the screen                  /*{{{*/
2751 // ---------------------------------------------------------------------
2752 /* */
2753 bool ShowPackage(CommandLine &CmdL)
2754 {   
2755    if (CheckHelp(CmdL) == true)
2756       return true;
2757
2758    pkgCache &Cache = *GCache;
2759    pkgDepCache::Policy Plcy;
2760
2761    unsigned found = 0;
2762    
2763    for (const char **I = CmdL.FileList + 1; *I != 0; I++)
2764    {
2765       pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
2766       if (Pkg.end() == true)
2767       {
2768          _error->Warning(_("Unable to locate package %s"),*I);
2769          continue;
2770       }
2771
2772       ++found;
2773
2774       // Find the proper version to use.
2775       if (_config->FindB("APT::Cache::AllVersions","true") == true)
2776       {
2777          pkgCache::VerIterator V;
2778          for (V = Pkg.VersionList(); V.end() == false; V++)
2779          {
2780             if (DisplayRecord(V) == false)
2781                return false;
2782          }
2783       }
2784       else
2785       {
2786          pkgCache::VerIterator V = Plcy.GetCandidateVer(Pkg);
2787          if (V.end() == true || V.FileList().end() == true)
2788             continue;
2789          if (DisplayRecord(V) == false)
2790             return false;
2791       }      
2792    }
2793
2794    if (found > 0)
2795         return true;
2796    return _error->Error(_("No packages found"));
2797 }
2798                                                                         /*}}}*/
2799 // --- End of stuff from apt-cache.
2800
2801
2802 // ShowHelp - Show a help screen                                        /*{{{*/
2803 // ---------------------------------------------------------------------
2804 /* */
2805 bool ShowHelp(CommandLine &CmdL)
2806 {
2807    if (CheckHelp(CmdL) == true)
2808       return true;
2809
2810    if (CmdL.FileSize() > 1) {
2811       CommandHelp(CmdL.FileList[1]);
2812       return true;
2813    }
2814
2815    ioprintf(cout,_("%s %s for %s %s compiled on %s %s\n"),PACKAGE,VERSION,
2816             COMMON_OS,COMMON_CPU,__DATE__,__TIME__);
2817             
2818    if (_config->FindB("version") == true)
2819    {
2820       cout << _("Supported Modules:") << endl;
2821       
2822       for (unsigned I = 0; I != pkgVersioningSystem::GlobalListLen; I++)
2823       {
2824          pkgVersioningSystem *VS = pkgVersioningSystem::GlobalList[I];
2825          if (_system != 0 && _system->VS == VS)
2826             cout << '*';
2827          else
2828             cout << ' ';
2829          cout << "Ver: " << VS->Label << endl;
2830          
2831          /* Print out all the packaging systems that will work with 
2832             this VS */
2833          for (unsigned J = 0; J != pkgSystem::GlobalListLen; J++)
2834          {
2835             pkgSystem *Sys = pkgSystem::GlobalList[J];
2836             if (_system == Sys)
2837                cout << '*';
2838             else
2839                cout << ' ';
2840             if (Sys->VS->TestCompatibility(*VS) == true)
2841                cout << "Pkg:  " << Sys->Label << " (Priority " << Sys->Score(*_config) << ")" << endl;
2842          }
2843       }
2844       
2845       for (unsigned I = 0; I != pkgSourceList::Type::GlobalListLen; I++)
2846       {
2847          pkgSourceList::Type *Type = pkgSourceList::Type::GlobalList[I];
2848          cout << " S.L: '" << Type->Name << "' " << Type->Label << endl;
2849       }      
2850       
2851       for (unsigned I = 0; I != pkgIndexFile::Type::GlobalListLen; I++)
2852       {
2853          pkgIndexFile::Type *Type = pkgIndexFile::Type::GlobalList[I];
2854          cout << " Idx: " << Type->Label << endl;
2855       }      
2856       
2857       return true;
2858    }
2859    
2860    cout << 
2861     _("\n"
2862       "Main commands:\n"
2863       "   status - Show the current selections\n"
2864       "   install - Install new packages\n"
2865       "   remove - Remove packages\n"
2866       "   keep - Keep packages\n"
2867       "   upgrade - Perform a global upgrade\n"
2868       "   dist-upgrade - Perform a globla distribution upgrade\n"
2869       "   build-dep - Install build-dependencies for source packages\n"
2870 //      "   dselect-upgrade - Follow dselect selections\n"
2871       "   update - Retrieve new lists of packages\n"
2872       "   commit - Apply the changes in the system\n"
2873       "   quit - Leave the APT shell\n"
2874       "\n"
2875       "Auxiliar commands:\n"
2876       "   show - Show a readable record for the package\n"
2877       "   showpkg - Show some general information for a single package\n"
2878       "   list/ls - List packages\n"
2879       "   search - Search the package list for a regex pattern\n"
2880       "   script - Run scripts.\n"
2881       "   depends - Show raw dependency information for a package\n"
2882       "   whatdepends - Show raw dependency information on a package\n"
2883       // "   rdepends - Show reverse dependency information for a package\n"
2884       "   check - Verify that there are no broken dependencies\n"
2885       "   unmet - Show unmet dependencies\n"
2886       "   clean - Erase downloaded archive files\n"
2887       "   autoclean - Erase old downloaded archive files\n"
2888       "\n"
2889       "For more information type \"help <cmd>\" or \"<cmd> [-h|--help]\".\n"
2890       "\n"
2891       "                       This APT has Super Cow Powers.\n");
2892    return true;
2893 }
2894
2895 void CommandHelp(const char *Name)
2896 {
2897    unsigned long Hash = 0;
2898    for (const char *p=Name; *p; p++)
2899       Hash = 5*Hash + *p;
2900    switch (Hash%1000000) {
2901       case 73823: // install
2902          c2out << _(
2903             "Usage: install [options] pkg1[=ver] [pkg2 ...]\n"
2904             "\n"
2905             "Try to mark the given packages for installation (new packages,\n"
2906             "upgrades or downgrades) changing other packages if necessary.\n"
2907             "\n"
2908             "Options:\n"
2909             "  -h  This help text.\n"
2910             "  -y  Assume Yes to all queries and do not prompt\n"
2911             "  -f  Attempt to continue if the integrity check fails\n"
2912             "  -m  Attempt to continue if archives are unlocatable\n"
2913             "  -D  When removing packages, remove dependencies as possible\n"
2914             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
2915             "\n"
2916          );
2917          break;
2918
2919       case 436466: // remove
2920          c2out << _(
2921             "Usage: remove [options] pkg1 [pkg2 ...]\n"
2922             "\n"
2923             "Try to mark the given packages for deletion, changing other\n"
2924             "packages if necessary.\n"
2925             "\n"
2926             "Options:\n"
2927             "  -h  This help text.\n"
2928             "  -y  Assume Yes to all queries and do not prompt\n"
2929             "  -f  Attempt to continue if the integrity check fails\n"
2930             "  -m  Attempt to continue if archives are unlocatable\n"
2931             "  -D  When removing packages, remove dependencies as possible\n"
2932             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
2933             "\n"
2934          );
2935          break;
2936
2937       case 16517: // keep
2938          c2out << _(
2939             "Usage: keep [options] pkg1 [pkg2 ...]\n"
2940             "\n"
2941             "Try to keep the given packages, currently marked for deletion\n"
2942             "or installation, in the system, changing other packages if\n"
2943             "necessary.\n"
2944             "\n"
2945             "Options:\n"
2946             "  -h  This help text.\n"
2947             "  -y  Assume Yes to all queries and do not prompt\n"
2948             "  -f  Attempt to continue if the integrity check fails\n"
2949             "  -m  Attempt to continue if archives are unlocatable\n"
2950             "  -D  When removing packages, remove dependencies as possible\n"
2951             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
2952             "\n"
2953          );
2954          break;
2955
2956       case 259776: // upgrade
2957          c2out << _(
2958             "Usage: upgrade [options]\n"
2959             "\n"
2960             "Perform a global upgrade.\n"
2961             "\n"
2962             "Options:\n"
2963             "  -h  This help text.\n"
2964             "  -y  Assume Yes to all queries and do not prompt\n"
2965             "  -f  Attempt to continue if the integrity check fails\n"
2966             "  -m  Attempt to continue if archives are unlocatable\n"
2967             "  -D  When removing packages, remove dependencies as possible\n"
2968             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
2969             "\n"
2970          );
2971
2972       case 900401: // dist-upgrade
2973          c2out << _(
2974             "Usage: dist-upgrade [options]\n"
2975             "\n"
2976             "Perform a global distribution upgrade.\n"
2977             "\n"
2978             "Options:\n"
2979             "  -h  This help text.\n"
2980             "  -y  Assume Yes to all queries and do not prompt\n"
2981             "  -f  Attempt to continue if the integrity check fails\n"
2982             "  -m  Attempt to continue if archives are unlocatable\n"
2983             "  -D  When removing packages, remove dependencies as possible\n"
2984             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
2985             "\n"
2986          );
2987
2988       case 209563: // showpkg
2989          c2out << _(
2990             "Usage: showpkg [options] pkg1 [pkg2 ...]\n"
2991             "\n"
2992             "Show some general information for the given packages.\n"
2993             "\n"
2994             "Options:\n"
2995             "  -h  This help text.\n"
2996             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
2997             "\n"
2998          );
2999          break;
3000
3001       case 17649: // show
3002          c2out << _(
3003             "Usage: show [options] pkg1 [pkg2 ...]\n"
3004             "\n"
3005             "Show a readable record for the given packages.\n"
3006             "\n"
3007             "Options:\n"
3008             "  -h  This help text.\n"
3009             "  -a  Show information about all versions.\n"
3010             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
3011             "\n"
3012          );
3013          break;
3014
3015       case 964115: // depends
3016          c2out << _(
3017             "Usage: depends [options] pkg1 [pkg2 ...]\n"
3018             "\n"
3019             "Show dependency relations for the given packages.\n"
3020             "\n"
3021             "Options:\n"
3022             "  -h  This help text.\n"
3023             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
3024             "\n"
3025          );
3026          break;
3027
3028       case 151615: // whatdepends
3029          c2out << _(
3030             "Usage: whatdepends [options] pkg1 [pkg2 ...]\n"
3031             "\n"
3032             "Show dependency relations on the given packages.\n"
3033             "\n"
3034             "Options:\n"
3035             "  -h  This help text.\n"
3036             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
3037             "\n"
3038          );
3039          break;
3040
3041       case 90221: // unmet
3042          c2out << _(
3043             "Usage: unmet [options]\n"
3044             "\n"
3045             "Show unsolvable relations in the cache.\n"
3046             "\n"
3047             "Options:\n"
3048             "  -h  This help text.\n"
3049             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
3050             "\n"
3051          );
3052          break;
3053
3054       case 438074: // search
3055          c2out << _(
3056             "Usage: search [options] <regex>\n"
3057             "\n"
3058             "Search for the given regular expression in package names and\n"
3059             "descriptions.\n"
3060             "\n"
3061             "Options:\n"
3062             "  -h  This help text.\n"
3063             "  -n  Search only in package names.\n"
3064             "  -f  Show full records for found packages.\n"
3065             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
3066             "\n"
3067          );
3068          break;
3069
3070       case 16816: // list
3071       case 655: // ls
3072          c2out << _(
3073             "Usage: list/ls [options] [pattern ...]\n"
3074             "\n"
3075             "List packages matching the given patterns, or all packages if\n"
3076             "no pattern is given. Wildcards are accepted.\n"
3077             "\n"
3078             "Options:\n"
3079             "  -h  This help text.\n"
3080             "  -i  Show only installed packages.\n"
3081             "  -u  Show only installed packages that are upgradable.\n"
3082             "  -v  Show installed and candidate versions.\n"
3083             "  -s  Show summaries.\n"
3084             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
3085             "\n"
3086          );
3087          break;
3088
3089       case 395741: // commit
3090          c2out << _(
3091             "Usage: commit [options]\n"
3092             "\n"
3093             "Apply the changes in the system.\n"
3094             "\n"
3095             "Options:\n"
3096             "  -h  This help text.\n"
3097             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
3098             "\n"
3099          );
3100          break;
3101
3102       case 438801: // script
3103          c2out << _(
3104             "Usage: script [options] script1 [script2]\n"
3105             "\n"
3106             "Run the given scripts.\n"
3107             "\n"
3108             "Options:\n"
3109             "  -h  This help text.\n"
3110             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
3111             "\n"
3112          );
3113          break;
3114       default:
3115          _error->Error(_("No help for that"));
3116    }
3117 }
3118                                                                         /*}}}*/
3119
3120 bool DoQuit(CommandLine &CmdL)
3121 {
3122    _config->Set("quit", "true");
3123    return true;
3124 }
3125
3126 bool DoCommit(CommandLine &CmdL)
3127 {
3128    if (CheckHelp(CmdL,0) == true)
3129       return true;
3130
3131    if (GCache->CanCommit() == false) {
3132       _error->Error(_("You have no permissions for that"));
3133       return false;
3134    }
3135    return InstallPackages(*GCache,false);
3136 }
3137
3138 bool DoStatus(CommandLine &CmdL)
3139 {
3140    if (CheckHelp(CmdL,0) == true)
3141       return true;
3142
3143    ShowChanges(*GCache);
3144    return true;
3145 }
3146
3147 // GetInitialize - Initialize things for apt-get                        /*{{{*/
3148 // ---------------------------------------------------------------------
3149 /* */
3150 void GetInitialize()
3151 {
3152    _config->Set("quiet",0);
3153    _config->Set("help",false);
3154    _config->Set("APT::Get::Download-Only",false);
3155    _config->Set("APT::Get::Simulate",false);
3156    _config->Set("APT::Get::Assume-Yes",false);
3157    _config->Set("APT::Get::Fix-Broken",false);
3158    _config->Set("APT::Get::Force-Yes",false);
3159    _config->Set("APT::Get::APT::Get::No-List-Cleanup",true);
3160 }
3161                                                                         /*}}}*/
3162 // ReadLine* - readline library stuff                                   /*{{{*/
3163 // ---------------------------------------------------------------------
3164 /* */
3165 char *ReadLineCompCommands(const char *Text, int State)
3166 {
3167    static char *Commands[] =  {"update", "upgrade", "install", "remove",
3168          "keep", "dist-upgrade", "dselect-upgrade", "build-dep", "clean",
3169          "autoclean", "check", "help", "commit", "exit", "quit", "status",
3170          "showpkg", "unmet", "search", "depends", "whatdepends", "rdepends",
3171          "show", "script", 0};
3172    static int Last;
3173    static size_t Len;
3174    if (State == 0) {
3175       Last = 0;
3176       Len = strlen(Text);
3177    }
3178    const char *Cmd;
3179    while ((Cmd = Commands[Last++])) {
3180       if (strncmp(Cmd, Text, Len) == 0)
3181          return strdup(Cmd);
3182    }
3183    return NULL;
3184 }
3185
3186 static int CompPackagesMode;
3187
3188 char *ReadLineCompPackages(const char *Text, int State)
3189 {
3190    CacheFile &Cache = *GCache;
3191    static pkgCache::PkgIterator Pkg;
3192    static size_t Len;
3193    if (State == 0) {
3194       Pkg = Cache->PkgBegin();
3195       Len = strlen(Text);
3196    } else {
3197       Pkg++;
3198    }
3199    const char *Name;
3200    for (; Pkg.end() == false; Pkg++) {
3201       Name = Pkg.Name();
3202       if (Pkg->VersionList == 0) {
3203          continue;
3204       } else if (CompPackagesMode == MODE_REMOVE) {
3205          if (Pkg->CurrentVer == 0)
3206             continue;
3207       } else if (CompPackagesMode == MODE_KEEP) {
3208          if (Cache[Pkg].Delete() == false && Cache[Pkg].Install() == false)
3209             continue;
3210       }
3211       if (strncmp(Name, Text, Len) == 0)
3212          return strdup(Name);
3213    }
3214    return NULL;
3215 }
3216
3217 static const char *CompVersionName;
3218
3219 char *ReadLineCompVersion(const char *Text, int State)
3220 {
3221    CacheFile &Cache = *GCache;
3222    static pkgCache::VerIterator Ver;
3223    static int Len;
3224    if (State == 0) {
3225       pkgCache::PkgIterator Pkg = Cache->FindPkg(CompVersionName);
3226       if (Pkg.end() == true)
3227          return NULL;
3228       Ver = Pkg.VersionList();
3229       Len = strlen(Text);
3230    } else {
3231       Ver++;
3232    }
3233    const char *Version;
3234    for (; Ver.end() == false; Ver++) {
3235       Version = Ver.VerStr();
3236       if (strncmp(Version, Text, Len) == 0)
3237          return strdup(Version);
3238    }
3239    return NULL;
3240 }
3241
3242
3243 unsigned long ReadLineHashCmd(const char *Cmd, const char *CmdEnd)
3244 {
3245    unsigned long Hash = 0;
3246    for (; Cmd != CmdEnd; Cmd++)
3247       Hash = 5*Hash + *Cmd;
3248    return Hash;
3249 }
3250    
3251 char **ReadLineCompletion(const char *Text, int Start, int End)
3252 {
3253    char **Matches = (char **)NULL;
3254    char *Cmd = rl_line_buffer;
3255    int Pos = 0;
3256    for (; *Cmd != 0 && isspace(*Cmd); Pos++, Cmd++);
3257    rl_attempted_completion_over = 1;
3258    if (Start == Pos)
3259       Matches = rl_completion_matches(Text, ReadLineCompCommands);
3260    else {
3261       char *CmdEnd = Cmd;
3262       while (!isspace(*CmdEnd)) CmdEnd++;
3263       CompPackagesMode = -1;
3264       switch (ReadLineHashCmd(Cmd,CmdEnd)) {
3265          case 2073823: // install
3266             if (*(rl_line_buffer+Start-1) == '=') {
3267                const char *NameEnd = rl_line_buffer+Start-1;
3268                const char *NameStart = NameEnd-1;
3269                while (!isspace(*NameStart)) NameStart--;
3270                if (++NameStart == NameEnd)
3271                   return NULL;
3272                string PkgName(NameStart, NameEnd-NameStart);
3273                CompVersionName = PkgName.c_str();
3274                Matches = rl_completion_matches(Text, ReadLineCompVersion);
3275             } else {
3276                Matches = rl_completion_matches(Text, ReadLineCompPackages);
3277             }
3278             break;
3279
3280          case 436466: // remove
3281             CompPackagesMode = MODE_REMOVE;
3282          case 16517: // keep
3283             if (CompPackagesMode == -1)
3284                CompPackagesMode = MODE_KEEP;
3285          case 2209563: // showpkg
3286          case 17649: // show
3287          case 16816: // list
3288          case 655: // ls
3289          case 1964115: // depends
3290          case 1414151615: // whatdepends
3291          case 10870365: // rdepends
3292             Matches = rl_completion_matches(Text, ReadLineCompPackages);
3293             break;
3294
3295          default:
3296             break;
3297       }
3298    }
3299    return Matches;
3300 }
3301
3302 string ReadLineHistoryFile()
3303 {
3304    string Path;
3305    const char *Dir = getenv("HOME");
3306    if (Dir != NULL) {
3307       Path = Dir;
3308       Path += "/.apt_history";
3309    }
3310    return Path;
3311 }
3312
3313 void ReadLineInit()
3314 {
3315    rl_readline_name = "APTShell";
3316    rl_attempted_completion_function = ReadLineCompletion;
3317    string History = ReadLineHistoryFile();
3318    if (History.empty() == false)
3319       read_history_range(History.c_str(), 0, -1);
3320 }
3321
3322 void ReadLineFinish()
3323 {
3324    string History = ReadLineHistoryFile();
3325    if (History.empty() == false)
3326       write_history(History.c_str());
3327 }
3328                                                                         /*}}}*/
3329
3330 CommandLine::Args *CommandArgs(const char *Name)
3331 {
3332    static CommandLine::Args ChangeCacheArgs[] = {
3333       {'h',"help","help",0},
3334       {'q',"quiet","quiet",CommandLine::IntLevel},
3335       {'q',"silent","quiet",CommandLine::IntLevel},
3336       {'y',"yes","APT::Get::Assume-Yes",0},
3337       {'y',"assume-yes","APT::Get::Assume-Yes",0},      
3338       {'s',"simulate","APT::Get::Simulate",0},
3339       {'s',"just-print","APT::Get::Simulate",0},
3340       {'s',"recon","APT::Get::Simulate",0},
3341       {'s',"dry-run","APT::Get::Simulate",0},
3342       {'s',"no-act","APT::Get::Simulate",0},
3343       {'f',"fix-broken","APT::Get::Fix-Broken",0},
3344       {'D',"remove-deps","APT::Remove-Depends",0}, // CNC:2002-08-01
3345       {'V',"verbose-versions","APT::Get::Show-Versions",0},
3346       {'t',"target-release","APT::Default-Release",CommandLine::HasArg},
3347       {'t',"default-release","APT::Default-Release",CommandLine::HasArg},
3348       {0,"reinstall","APT::Get::ReInstall",0},
3349       {0,"upgrade","APT::Get::upgrade",0},
3350       {0,"force-yes","APT::Get::Force-Yes",0},
3351       {0,"ignore-hold","APT::Ignore-Hold",0},      
3352       {0,"purge","APT::Get::Purge",0},
3353       {0,"remove","APT::Get::Remove",0},
3354       {0,"arch-only","APT::Get::Arch-Only",0},
3355       {'c',"config-file",0,CommandLine::ConfigFile},
3356       {'o',"option",0,CommandLine::ArbItem},
3357       {0,0,0,0}};
3358
3359    static CommandLine::Args CommitArgs[] = {
3360       {'h',"help","help",0},
3361       {'q',"quiet","quiet",CommandLine::IntLevel},
3362       {'q',"silent","quiet",CommandLine::IntLevel},
3363       {'y',"yes","APT::Get::Assume-Yes",0},
3364       {'y',"assume-yes","APT::Get::Assume-Yes",0},      
3365       {'d',"download-only","APT::Get::Download-Only",0},
3366       {'s',"simulate","APT::Get::Simulate",0},
3367       {'s',"just-print","APT::Get::Simulate",0},
3368       {'s',"recon","APT::Get::Simulate",0},
3369       {'s',"dry-run","APT::Get::Simulate",0},
3370       {'s',"no-act","APT::Get::Simulate",0},
3371       {'m',"ignore-missing","APT::Get::Fix-Missing",0},
3372       {0,"trivial-only","APT::Get::Trivial-Only",0},
3373       {0,"print-uris","APT::Get::Print-URIs",0},
3374       {0,"force-yes","APT::Get::Force-Yes",0},
3375       {0,"download","APT::Get::Download",0},
3376       {0,"fix-missing","APT::Get::Fix-Missing",0},
3377       {'c',"config-file",0,CommandLine::ConfigFile},
3378       {'o',"option",0,CommandLine::ArbItem},
3379       {0,0,0,0}};
3380
3381    static CommandLine::Args ShowArgs[] = {
3382       {'h',"help","help",0},
3383       {'a',"all-versions","APT::Cache::AllVersions",0},
3384       {'n',"names-only","APT::Cache::NamesOnly",0},
3385       {'f',"show-full","APT::Cache::ShowFull",0},
3386       {'c',"config-file",0,CommandLine::ConfigFile},
3387       {'o',"option",0,CommandLine::ArbItem},
3388       {0,0,0,0}};
3389
3390    static CommandLine::Args SearchArgs[] = {
3391       {'h',"help","help",0},
3392       {'n',"names-only","APT::Cache::NamesOnly",0},
3393       {'f',"show-full","APT::Cache::ShowFull",0},
3394       {'c',"config-file",0,CommandLine::ConfigFile},
3395       {'o',"option",0,CommandLine::ArbItem},
3396       {0,0,0,0}};
3397
3398    static CommandLine::Args ListArgs[] = {
3399       {'h',"help","help",0},
3400       {'u',"upgradable","APT::Cache::ShowUpgradable",0},
3401       {'i',"installed","APT::Cache::ShowInstalled",0},
3402       {'v',"version","APT::Cache::ShowVersion",0},
3403       {'s',"summary","APT::Cache::ShowSummary",0},
3404       {'n',"installed","APT::Cache::Installed",0},
3405       {'c',"config-file",0,CommandLine::ConfigFile},
3406       {'o',"option",0,CommandLine::ArbItem},
3407       {0,0,0,0}};
3408
3409    static CommandLine::Args NoArgs[] = {
3410       {'h',"help","help",0},
3411       {'v',"version","version",0},
3412       {'c',"config-file",0,CommandLine::ConfigFile},
3413       {'o',"option",0,CommandLine::ArbItem},
3414       {0,0,0,0}};
3415
3416
3417    unsigned long Hash = 0;
3418    for (const char *p=Name; *p; p++)
3419       Hash = 5*Hash + *p;
3420    switch (Hash%1000000) {
3421       case 73823: // install
3422       case 436466: // remove
3423       case 16517: // keep
3424       case 259776: // upgrade
3425       case 900401: // dist-upgrade
3426          return ChangeCacheArgs;
3427
3428       case 395741: // commit
3429          return CommitArgs;
3430
3431       case 209563: // showpkg
3432       case 17649: // show
3433          return ShowArgs;
3434
3435       case 438074: // search
3436          return SearchArgs;
3437
3438       case 16816: // list
3439       case 655: // ls
3440          return ListArgs;
3441
3442       default:
3443          return NoArgs;
3444    }
3445 }
3446                                                                         /*}}}*/
3447 int main(int argc,const char *argv[])
3448 {
3449    CommandLine::Dispatch Cmds[] = {{"update",&DoUpdate},
3450                                    {"upgrade",&DoUpgrade},
3451                                    {"install",&DoInstall},
3452                                    {"remove",&DoInstall},
3453                                    {"keep",&DoInstall},
3454                                    {"dist-upgrade",&DoDistUpgrade},
3455                                    {"build-dep",&DoBuildDep},
3456                                    {"clean",&DoClean},
3457                                    {"autoclean",&DoAutoClean},
3458                                    {"check",&DoCheck},
3459                                    {"help",&ShowHelp},
3460                                    {"commit",&DoCommit},
3461                                    {"quit",&DoQuit},
3462                                    {"exit",&DoQuit},
3463                                    {"status",&DoStatus},
3464                                    {"script",&DoScript},
3465                                    // apt-cache
3466                                    {"showpkg",&DumpPackage},
3467                                    {"unmet",&UnMet},
3468                                    {"search",&Search},
3469                                    {"list",&DoList},
3470                                    {"ls",&DoList},
3471                                    {"depends",&Depends},
3472                                    {"whatdepends",&WhatDepends},
3473                                    {"rdepends",&RDepends},
3474                                    {"show",&ShowPackage},
3475                                    {0,0}};
3476
3477    // Set up gettext support
3478    setlocale(LC_ALL,"");
3479    textdomain(PACKAGE);
3480
3481    // Parse the command line and initialize the package library
3482    CommandLine CmdL(CommandArgs(""),_config);
3483    if (pkgInitConfig(*_config) == false ||
3484        CmdL.Parse(argc,argv) == false ||
3485        pkgInitSystem(*_config,_system) == false)
3486    {
3487       if (_config->FindB("version") == true)
3488          ShowHelp(CmdL);
3489          
3490       _error->DumpErrors();
3491       return 100;
3492    }
3493
3494    // Deal with stdout not being a tty
3495    if (ttyname(STDOUT_FILENO) == 0 && _config->FindI("quiet",0) < 1)
3496       _config->Set("quiet","1");
3497
3498    // Setup the output streams
3499    c0out.rdbuf(cout.rdbuf());
3500    c1out.rdbuf(cout.rdbuf());
3501    c2out.rdbuf(cout.rdbuf());
3502    if (_config->FindI("quiet",0) > 0)
3503       c0out.rdbuf(devnull.rdbuf());
3504    if (_config->FindI("quiet",0) > 1)
3505       c1out.rdbuf(devnull.rdbuf());
3506
3507    // Setup the signals
3508    signal(SIGPIPE,SIG_IGN);
3509    signal(SIGINT,SIG_IGN);
3510    signal(SIGWINCH,SigWinch);
3511    SigWinch(0);
3512
3513    // Prepare the cache
3514    GCache = new CacheFile();
3515    GCache->Open();
3516
3517    // CNC:2004-02-18
3518    if (_error->empty() == false)
3519    {
3520       bool Errors = _error->PendingError();
3521       _error->DumpErrors();