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