Add bunch of missing includes to fix build with gcc 4.7
[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 ostream c0out(0);
77 ostream c1out(0);
78 ostream c2out(0);
79 ofstream devnull("/dev/null");
80 unsigned int ScreenWidth = 80;
81
82
83 // class CacheFile - Cover class for some dependency cache functions    /*{{{*/
84 // ---------------------------------------------------------------------
85 /* */
86 class CacheFile : public cmdCacheFile
87 {
88    bool IsRoot;
89    
90    public:
91    bool CheckDeps(bool AllowBroken = false);
92    bool BuildCaches()
93    {
94       OpTextProgress Prog(*_config);
95       if (pkgCacheFile::BuildCaches(Prog,IsRoot) == false)
96          return false;
97       return true;
98    }
99    bool Open() 
100    {
101       OpTextProgress Prog(*_config);
102       if (pkgCacheFile::Open(Prog,IsRoot) == false)
103          return false;
104       Sort();
105       return true;
106    }
107    bool CanCommit()
108    {
109       return IsRoot;
110    }
111    CacheFile() : cmdCacheFile()
112    {
113       IsRoot = (getuid() == 0);
114    }
115 };
116                                                                         /*}}}*/
117
118 static CacheFile *GCache = NULL;
119
120 class AutoRestore
121 {
122    pkgDepCache::State State;
123    bool Guarded;
124    public:
125    inline pkgDepCache::State *operator ->() {return &State;}
126    inline pkgDepCache::State *operator &() {return &State;}
127    inline void UnGuard() { Guarded = false; }
128    AutoRestore(pkgDepCache &Cache)
129       : State(&Cache), Guarded(true) {}
130    ~AutoRestore() { if (Guarded) State.Restore(); }
131 };
132
133 class AutoReOpenCache
134 {
135    CacheFile **Cache;
136    bool Guarded;
137    public:
138    inline void UnGuard() { Guarded = false; }
139    AutoReOpenCache(CacheFile *&Cache)
140       : Cache(&Cache), Guarded(true) {}
141    ~AutoReOpenCache()
142    {
143       if (Guarded) {
144          delete *Cache;
145          *Cache = new CacheFile;
146          (*Cache)->Open();
147          if ((*Cache)->CheckDeps(true) == false) {
148             c1out << _("There are broken packages. ")
149                   << _("Run `check' to see them.") << endl;
150             c1out << _("You can try to fix them automatically with `install --fix-broken'.") << endl;
151          }
152       }
153    }
154 };
155
156 void CommandHelp(const char *Name);
157 bool CheckHelp(CommandLine &CmdL, unsigned int MaxArgs=512)
158 {
159    if (CmdL.FileSize()-1 > MaxArgs) {
160       _error->Error(_("Excessive arguments"));
161       return true;
162    }
163    if (_config->FindB("help") == true) {
164       CommandHelp(CmdL.FileList[0]);
165       return true;
166    }
167    return false;
168 }
169
170 // ShowChanges - Show what would change between the saved state and the /*{{{*/
171 //               cache file state.
172 // ---------------------------------------------------------------------
173 /* */
174 bool ShowChanges(CacheFile &Cache,pkgDepCache::State *State=NULL)
175 {
176    ShowUpgraded(c1out,Cache,State);
177    ShowDel(c1out,Cache,State);
178    ShowNew(c1out,Cache,State);
179    if (State != NULL)
180       ShowKept(c1out,Cache,State);
181    ShowHold(c1out,Cache,State);
182    ShowDowngraded(c1out,Cache,State);
183    ShowEssential(c1out,Cache,State);
184    Stats(c1out,Cache,State);
185
186    if (State != NULL) {
187       double DebBytes = Cache->DebSize()-State->DebSize();
188       // Number of bytes
189       if (DebBytes >= 0)
190          ioprintf(c1out,_("Will need more %sB of archives.\n"),
191                   SizeToStr(DebBytes).c_str());
192       else
193          ioprintf(c1out,_("Will need less %sB of archives.\n"),
194                   SizeToStr(-1*DebBytes).c_str());
195
196       double UsrSize = Cache->UsrSize()-State->UsrSize();
197       // Size delta
198       if (UsrSize >= 0)
199          ioprintf(c1out,_("After unpacking will need more %sB of disk space.\n"),
200                   SizeToStr(UsrSize).c_str());
201       else
202          ioprintf(c1out,_("After unpacking will need less %sB of disk space.\n"),
203                   SizeToStr(-1*UsrSize).c_str());
204    } else {
205       double DebBytes = Cache->DebSize();
206       // Number of bytes
207       ioprintf(c1out,_("Will need %sB of archives.\n"),
208                SizeToStr(DebBytes).c_str());
209
210       // Size delta
211       if (Cache->UsrSize() >= 0)
212          ioprintf(c1out,_("After unpacking %sB of additional disk space will be used.\n"),
213                   SizeToStr(Cache->UsrSize()).c_str());
214       else
215          ioprintf(c1out,_("After unpacking %sB disk space will be freed.\n"),
216                   SizeToStr(-1*Cache->UsrSize()).c_str());
217    }
218    return true;
219 }
220                                                                         /*}}}*/
221
222 bool ConfirmChanges(CacheFile &Cache, AutoRestore &StateGuard)
223 {
224    if (StateGuard->Changed()) {
225       c2out << _("Unrequested changes are needed to execute this operation.")
226             << endl;
227       ShowChanges(Cache,&StateGuard);
228       c2out << _("Do you want to continue? [Y/n] ") << flush;
229       if (YnPrompt() == false) {
230          c2out << _("Abort.") << endl;
231          return false;
232       }
233    }
234    StateGuard.UnGuard();
235    return true;
236 }
237
238 // CacheFile::CheckDeps - Open the cache file                           /*{{{*/
239 // ---------------------------------------------------------------------
240 /* This routine generates the caches and then opens the dependency cache
241    and verifies that the system is OK. */
242 bool CacheFile::CheckDeps(bool AllowBroken)
243 {
244    if (_error->PendingError() == true)
245       return false;
246
247    // Check that the system is OK
248    //if (DCache->DelCount() != 0 || DCache->InstCount() != 0)
249    //   return _error->Error("Internal Error, non-zero counts");
250    
251    // Apply corrections for half-installed packages
252    if (pkgApplyStatus(*DCache) == false)
253       return false;
254    
255    // Nothing is broken
256    if (DCache->BrokenCount() == 0 || AllowBroken == true)
257       return true;
258
259    // Attempt to fix broken things
260    if (_config->FindB("APT::Get::Fix-Broken",false) == true)
261    {
262       c1out << _("Correcting dependencies...") << flush;
263       if (pkgFixBroken(*DCache) == false || DCache->BrokenCount() != 0)
264       {
265          c1out << _(" failed.") << endl;
266          ShowBroken(c1out,*this,true);
267
268          return _error->Error(_("Unable to correct dependencies"));
269       }
270       if (pkgMinimizeUpgrade(*DCache) == false)
271          return _error->Error(_("Unable to minimize the upgrade set"));
272       
273       c1out << _(" Done") << endl;
274    }
275    else
276    {
277       c1out << _("You might want to run `install --fix-broken' to correct these.") << endl;
278       ShowBroken(c1out,*this,true);
279
280       return _error->Error(_("Unmet dependencies. Try using --fix-broken."));
281    }
282       
283    return true;
284 }
285                                                                         /*}}}*/
286
287 bool DoClean(CommandLine &CmdL);
288 bool DoAutoClean(CommandLine &CmdL);
289
290 // InstallPackages - Actually download and install the packages         /*{{{*/
291 // ---------------------------------------------------------------------
292 /* This displays the informative messages describing what is going to 
293    happen and then calls the download routines */
294 bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
295                      bool Saftey = true)
296 {
297    if (_config->FindB("APT::Get::Purge",false) == true)
298    {
299       pkgCache::PkgIterator I = Cache->PkgBegin();
300       for (; I.end() == false; I++)
301       {
302          if (I.Purge() == false && Cache[I].Mode == pkgDepCache::ModeDelete)
303             Cache->MarkDelete(I,true);
304       }
305    }
306    
307    bool Fail = false;
308    bool Essential = false;
309    
310    // Show all the various warning indicators
311    // CNC:2002-03-06 - Change Show-Upgraded default to true, and move upwards.
312    if (_config->FindB("APT::Get::Show-Upgraded",true) == true)
313       ShowUpgraded(c1out,Cache);
314    ShowDel(c1out,Cache);
315    ShowNew(c1out,Cache);
316    if (ShwKept == true)
317       ShowKept(c1out,Cache);
318    Fail |= !ShowHold(c1out,Cache);
319    Fail |= !ShowDowngraded(c1out,Cache);
320    Essential = !ShowEssential(c1out,Cache);
321    Fail |= Essential;
322    Stats(c1out,Cache);
323    
324    // Sanity check
325    if (Cache->BrokenCount() != 0)
326    {
327       ShowBroken(c1out,Cache,false);
328       return _error->Error("Internal Error, InstallPackages was called with broken packages!");
329    }
330
331    if (Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
332        Cache->BadCount() == 0)
333       return true;
334
335    // No remove flag
336    if (Cache->DelCount() != 0 && _config->FindB("APT::Get::Remove",true) == false)
337       return _error->Error(_("Packages need to be removed but Remove is disabled."));
338        
339    // Run the simulator ..
340    if (_config->FindB("APT::Get::Simulate") == true)
341    {
342       pkgSimulate PM(Cache);
343       pkgPackageManager::OrderResult Res = PM.DoInstall();
344       if (Res == pkgPackageManager::Failed)
345          return false;
346       if (Res != pkgPackageManager::Completed)
347          return _error->Error("Internal Error, Ordering didn't finish");
348       return true;
349    }
350    
351    // Create the text record parser
352    pkgRecords Recs(Cache);
353    if (_error->PendingError() == true)
354       return false;
355    
356    // Lock the archive directory
357    FileFd Lock;
358    if (_config->FindB("Debug::NoLocking",false) == false &&
359        _config->FindB("APT::Get::Print-URIs") == false)
360    {
361       Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
362       if (_error->PendingError() == true)
363          return _error->Error(_("Unable to lock the download directory"));
364    }
365    
366    // Create the download object
367    AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));   
368    pkgAcquire Fetcher(&Stat);
369
370    // Read the source list
371    pkgSourceList List;
372    if (List.ReadMainList() == false)
373       return _error->Error(_("The list of sources could not be read."));
374    
375    // Create the package manager and prepare to download
376    SPtr<pkgPackageManager> PM= _system->CreatePM(Cache);
377    if (PM->GetArchives(&Fetcher,&List,&Recs) == false || 
378        _error->PendingError() == true)
379       return false;
380
381    // Display statistics
382    double FetchBytes = Fetcher.FetchNeeded();
383    double FetchPBytes = Fetcher.PartialPresent();
384    double DebBytes = Fetcher.TotalNeeded();
385    if (DebBytes != Cache->DebSize())
386    {
387       c0out << DebBytes << ',' << Cache->DebSize() << endl;
388       c0out << "How odd.. The sizes didn't match, email apt@packages.debian.org" << endl;
389    }
390    
391    // Number of bytes
392    if (DebBytes != FetchBytes)
393       ioprintf(c1out,_("Need to get %sB/%sB of archives.\n"),
394                SizeToStr(FetchBytes).c_str(),SizeToStr(DebBytes).c_str());
395    else
396       ioprintf(c1out,_("Need to get %sB of archives.\n"),
397                SizeToStr(DebBytes).c_str());
398
399    // Size delta
400    if (Cache->UsrSize() >= 0)
401       ioprintf(c1out,_("After unpacking %sB of additional disk space will be used.\n"),
402                SizeToStr(Cache->UsrSize()).c_str());
403    else
404       ioprintf(c1out,_("After unpacking %sB disk space will be freed.\n"),
405                SizeToStr(-1*Cache->UsrSize()).c_str());
406
407    if (_error->PendingError() == true)
408       return false;
409
410    /* Check for enough free space, but only if we are actually going to
411       download */
412    if (_config->FindB("APT::Get::Print-URIs") == false &&
413        _config->FindB("APT::Get::Download",true) == true)
414    {
415       struct statvfs Buf;
416       string OutputDir = _config->FindDir("Dir::Cache::Archives");
417       if (statvfs(OutputDir.c_str(),&Buf) != 0)
418          return _error->Errno("statvfs","Couldn't determine free space in %s",
419                               OutputDir.c_str());
420       // CNC:2002-07-11
421       if (unsigned(Buf.f_bavail) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
422          return _error->Error(_("You don't have enough free space in %s."),
423                               OutputDir.c_str());
424    }
425    
426    // Fail safe check
427    if (_config->FindI("quiet",0) >= 2 ||
428        _config->FindB("APT::Get::Assume-Yes",false) == true)
429    {
430       if (Fail == true && _config->FindB("APT::Get::Force-Yes",false) == false)
431          return _error->Error(_("There are problems and -y was used without --force-yes"));
432    }         
433
434    if (Essential == true && Saftey == true)
435    {
436       if (_config->FindB("APT::Get::Trivial-Only",false) == true)
437          return _error->Error(_("Trivial Only specified but this is not a trivial operation."));
438       
439       const char *Prompt = _("Yes, do as I say!");
440       ioprintf(c2out,
441                _("You are about to do something potentially harmful\n"
442                  "To continue type in the phrase '%s'\n"
443                  " ?] "),Prompt);
444       c2out << flush;
445       if (AnalPrompt(Prompt) == false)
446       {
447          c2out << _("Abort.") << endl;
448          exit(1);
449       }     
450    }
451    else
452    {      
453       // Prompt to continue
454       if (Ask == true || Fail == true)
455       {            
456          if (_config->FindB("APT::Get::Trivial-Only",false) == true)
457             return _error->Error(_("Trivial Only specified but this is not a trivial operation."));
458          
459          if (_config->FindI("quiet",0) < 2 &&
460              _config->FindB("APT::Get::Assume-Yes",false) == false)
461          {
462             c2out << _("Do you want to continue? [Y/n] ") << flush;
463          
464             if (YnPrompt() == false)
465             {
466                c2out << _("Abort.") << endl;
467                exit(1);
468             }     
469          }       
470       }      
471    }
472    
473    // Just print out the uris an exit if the --print-uris flag was used
474    if (_config->FindB("APT::Get::Print-URIs") == true)
475    {
476       pkgAcquire::UriIterator I = Fetcher.UriBegin();
477       for (; I != Fetcher.UriEnd(); I++)
478          cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' << 
479                I->Owner->FileSize << ' ' << I->Owner->Checksum() << endl;
480       return true;
481    }
482
483    /* Unlock the dpkg lock if we are not going to be doing an install
484       after. */
485    if (_config->FindB("APT::Get::Download-Only",false) == true)
486       _system->UnLock();
487
488    // CNC:2003-02-24
489    bool Ret = true;
490
491    AutoReOpenCache CacheGuard(GCache);
492    
493    // Run it
494    while (1)
495    {
496       bool Transient = false;
497       if (_config->FindB("APT::Get::Download",true) == false)
498       {
499          for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I < Fetcher.ItemsEnd();)
500          {
501             if ((*I)->Local == true)
502             {
503                I++;
504                continue;
505             }
506
507             // Close the item and check if it was found in cache
508             (*I)->Finished();
509             if ((*I)->Complete == false)
510                Transient = true;
511             
512             // Clear it out of the fetch list
513             delete *I;
514             I = Fetcher.ItemsBegin();
515          }       
516       }
517       
518       if (Fetcher.Run() == pkgAcquire::Failed)
519          return false;
520
521       // CNC:2003-02-24
522       _error->PopState();
523       
524       // Print out errors
525       bool Failed = false;
526       for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
527       {
528          if ((*I)->Status == pkgAcquire::Item::StatDone &&
529              (*I)->Complete == true)
530             continue;
531          
532          if ((*I)->Status == pkgAcquire::Item::StatIdle)
533          {
534             Transient = true;
535             // Failed = true;
536             continue;
537          }
538
539          fprintf(stderr,_("Failed to fetch %s  %s\n"),(*I)->DescURI().c_str(),
540                  (*I)->ErrorText.c_str());
541          Failed = true;
542       }
543
544       /* If we are in no download mode and missing files and there were
545          'failures' then the user must specify -m. Furthermore, there 
546          is no such thing as a transient error in no-download mode! */
547       if (Transient == true &&
548           _config->FindB("APT::Get::Download",true) == false)
549       {
550          Transient = false;
551          Failed = true;
552       }
553       
554       if (_config->FindB("APT::Get::Download-Only",false) == true)
555       {
556          if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
557             return _error->Error(_("Some files failed to download"));
558          c1out << _("Download complete and in download only mode") << endl;
559          return true;
560       }
561       
562       if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
563       {
564          return _error->Error(_("Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?"));
565       }
566       
567       if (Transient == true && Failed == true)
568          return _error->Error(_("--fix-missing and media swapping is not currently supported"));
569       
570       // Try to deal with missing package files
571       if (Failed == true && PM->FixMissing() == false)
572       {
573          cerr << _("Unable to correct missing packages.") << endl;
574          return _error->Error(_("Aborting Install."));
575       }
576
577       // CNC:2002-10-18
578       if (Transient == false || _config->FindB("Acquire::CDROM::Copy-All", false) == false) {
579          if (Transient == true) {
580             // We must do that in a system independent way. */
581             _config->Set("RPM::Install-Options::", "--nodeps");
582          }
583          _system->UnLock();
584          pkgPackageManager::OrderResult Res = PM->DoInstall();
585          if (Res == pkgPackageManager::Failed || _error->PendingError() == true)
586          {
587             if (Transient == false)
588                return false;
589             Ret = false;
590          }
591
592          // CNC:2002-07-06
593          if (Res == pkgPackageManager::Completed)
594          {
595             CommandLine *CmdL = NULL; // Watch out! If used will blow up!
596             if (_config->FindB("APT::Post-Install::Clean",false) == true) 
597                Ret &= DoClean(*CmdL);
598             else if (_config->FindB("APT::Post-Install::AutoClean",false) == true) 
599                Ret &= DoAutoClean(*CmdL);
600             return Ret;
601          }
602          
603          _system->Lock();
604       }
605
606       // CNC:2003-02-24
607       _error->PushState();
608       
609       // Reload the fetcher object and loop again for media swapping
610       Fetcher.Shutdown();
611       if (PM->GetArchives(&Fetcher,&List,&Recs) == false)
612          return false;
613    }   
614 }
615                                                                         /*}}}*/
616 #define MODE_INSTALL 0
617 #define MODE_REMOVE  1
618 #define MODE_KEEP    2
619 // TryToInstall - Try to install a single package                       /*{{{*/
620 // ---------------------------------------------------------------------
621 /* This used to be inlined in DoInstall, but with the advent of regex package
622    name matching it was split out.. */
623 bool TryToInstall(pkgCache::PkgIterator Pkg,pkgDepCache &Cache,
624                   pkgProblemResolver &Fix,int Mode,bool BrokenFix,
625                   unsigned int &ExpectedInst,bool AllowFail = true)
626 {
627    // CNC:2004-03-03 - Improved virtual package handling.
628    if (Cache[Pkg].CandidateVer == 0 && Pkg->ProvidesList != 0)
629    {
630       vector<pkgCache::Package *> GoodSolutions;
631       for (pkgCache::PrvIterator Prv = Pkg.ProvidesList();
632            Prv.end() == false; Prv++)
633       {
634          pkgCache::PkgIterator PrvPkg = Prv.OwnerPkg();
635          // Check if it's a different version of a package already
636          // considered as a good solution.
637          bool AlreadySeen = false;
638          for (vector<pkgCache::Package *>::size_type i = 0; i != GoodSolutions.size(); i++)
639          {
640             pkgCache::PkgIterator GoodPkg(Cache, GoodSolutions[i]);
641             if (PrvPkg == GoodPkg)
642             {
643                AlreadySeen = true;
644                break;
645             }
646          }
647          if (AlreadySeen)
648             continue;
649          // Is the current version the provides owner?
650          if (PrvPkg.CurrentVer() == Prv.OwnerVer())
651          {
652             // Already installed packages are good solutions, since
653             // the user might try to install something he already has
654             // without being aware.
655             GoodSolutions.push_back(PrvPkg);
656             continue;
657          }
658          pkgCache::VerIterator PrvPkgCandVer =
659                                  Cache[PrvPkg].CandidateVerIter(Cache);
660          if (PrvPkgCandVer.end() == true)
661          {
662             // Packages without a candidate version are not good solutions.
663             continue;
664          }
665          // Is the provides pointing to the candidate version?
666          if (PrvPkgCandVer == Prv.OwnerVer())
667          {
668             // Yes, it is. This is a good solution.
669             GoodSolutions.push_back(PrvPkg);
670             continue;
671          }
672       }
673       vector<string> GoodSolutionNames;
674       for (vector<string>::size_type i = 0; i != GoodSolutions.size(); i++)
675       {
676          pkgCache::PkgIterator GoodPkg(Cache, GoodSolutions[i]);
677          GoodSolutionNames.push_back(GoodPkg.Name());
678       }
679 #ifdef APT_WITH_LUA
680       if (GoodSolutions.size() > 1)
681       {
682          vector<string> VS;
683          _lua->SetDepCache(&Cache);
684          _lua->SetDontFix();
685          _lua->SetGlobal("virtualname", Pkg.Name());
686          _lua->SetGlobal("packages", GoodSolutions);
687          _lua->SetGlobal("packagenames", GoodSolutionNames);
688          _lua->SetGlobal("selected");
689          _lua->RunScripts("Scripts::AptGet::Install::SelectPackage");
690          pkgCache::Package *selected = _lua->GetGlobalPkg("selected");
691          if (selected)
692          {
693             GoodSolutions.clear();
694             GoodSolutions.push_back(selected);
695          }
696          else
697          {
698             vector<string> Tmp = _lua->GetGlobalStrList("packagenames");
699             if (Tmp.size() == GoodSolutions.size())
700                GoodSolutionNames = Tmp;
701          }
702          _lua->ResetGlobals();
703          _lua->ResetCaches();
704       }
705 #endif
706       if (GoodSolutions.size() == 1)
707       {
708          pkgCache::PkgIterator GoodPkg(Cache, GoodSolutions[0]);
709          ioprintf(c1out,_("Selecting %s for '%s'\n"),
710                   GoodPkg.Name(), Pkg.Name());
711          Pkg = GoodPkg;
712       }
713       else if (GoodSolutions.size() == 0)
714       {
715          _error->Error(_("Package %s is a virtual package with no "
716                          "good providers.\n"), Pkg.Name());
717          return false;
718       }
719       else
720       {
721          ioprintf(c1out,_("Package %s is a virtual package provided by:\n"),
722                   Pkg.Name());
723          for (vector<pkgCache::Package *>::size_type i = 0; i != GoodSolutions.size(); i++)
724          {
725             pkgCache::PkgIterator GoodPkg(Cache, GoodSolutions[i]);
726             if (GoodPkg.CurrentVer().end() == false)
727                c1out << "  " << GoodSolutionNames[i]
728                      << " "  << Cache[GoodPkg].CandVersion
729                      << _(" [Installed]") << endl;
730             else
731                c1out << "  " << GoodSolutionNames[i]
732                      << " "  << Cache[GoodPkg].CandVersion << endl;
733          }
734          c1out << _("You should explicitly select one to install.") << endl;
735          _error->Error(_("Package %s is a virtual package with multiple "
736                          "good providers.\n"), Pkg.Name());
737          return false;
738       }
739    }
740    
741    // Handle the no-upgrade case
742    if (_config->FindB("APT::Get::upgrade",true) == false &&
743        Pkg->CurrentVer != 0)
744    {
745       if (AllowFail == true)
746          ioprintf(c1out,_("Skipping %s, it is already installed and upgrade is not set.\n"),
747                   Pkg.Name());
748       return true;
749    }
750    
751    // Check if there is something at all to install
752    pkgDepCache::StateCache &State = Cache[Pkg];
753    if (Mode == MODE_REMOVE && Pkg->CurrentVer == 0)
754    {
755       Fix.Clear(Pkg);
756       Fix.Protect(Pkg);
757       Fix.Remove(Pkg);
758       
759       /* We want to continue searching for regex hits, so we return false here
760          otherwise this is not really an error. */
761       if (AllowFail == false)
762          return false;
763       
764       ioprintf(c1out,_("Package %s is not installed, so not removed\n"),Pkg.Name());
765       return true;
766    }
767    
768    if (State.CandidateVer == 0 && Mode == MODE_INSTALL)
769    {
770       if (AllowFail == false)
771          return false;
772       
773 // CNC:2004-03-03 - Improved virtual package handling.
774 #if 0
775       if (Pkg->ProvidesList != 0)
776       {
777          ioprintf(c1out,_("Package %s is a virtual package provided by:\n"),
778                   Pkg.Name());
779          
780          pkgCache::PrvIterator I = Pkg.ProvidesList();
781          for (; I.end() == false; I++)
782          {
783             pkgCache::PkgIterator Pkg = I.OwnerPkg();
784             
785             if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer())
786             {
787                if (Cache[Pkg].Install() == true && Cache[Pkg].NewInstall() == false)
788                   c1out << "  " << Pkg.Name() << " " << I.OwnerVer().VerStr() <<
789                   _(" [Installed]") << endl;
790                else
791                   c1out << "  " << Pkg.Name() << " " << I.OwnerVer().VerStr() << endl;
792             }      
793          }
794          c1out << _("You should explicitly select one to install.") << endl;
795       }
796       else
797 #endif
798       {
799          ioprintf(c1out,
800          _("Package %s has no available version, but exists in the database.\n"
801            "This typically means that the package was mentioned in a dependency and\n"
802            "never uploaded, has been obsoleted or is not available with the contents\n"
803            "of sources.list\n"),Pkg.Name());
804          
805          string List;
806          string VersionsList;
807          SPtrArray<bool> Seen = new bool[Cache.Head().PackageCount];
808          memset(Seen,0,Cache.Head().PackageCount*sizeof(*Seen));
809          pkgCache::DepIterator Dep = Pkg.RevDependsList();
810          for (; Dep.end() == false; Dep++)
811          {
812             // CNC:2002-07-30
813             if (Dep->Type != pkgCache::Dep::Replaces &&
814                 Dep->Type != pkgCache::Dep::Obsoletes)
815                continue;
816             if (Seen[Dep.ParentPkg()->ID] == true)
817                continue;
818             Seen[Dep.ParentPkg()->ID] = true;
819             List += string(Dep.ParentPkg().Name()) + " ";
820             //VersionsList += string(Dep.ParentPkg().CurVersion) + "\n"; ???
821          }          
822          ShowList(c1out,_("However the following packages replace it:"),List,VersionsList);
823       }
824       
825       _error->Error(_("Package %s has no installation candidate"),Pkg.Name());
826       return false;
827    }
828
829    Fix.Clear(Pkg);
830    Fix.Protect(Pkg);   
831
832    if (Mode == MODE_KEEP) {
833       Cache.MarkKeep(Pkg);
834       return true;
835    }
836    
837    if (Mode == MODE_REMOVE)
838    {
839       Fix.Remove(Pkg);
840       Cache.MarkDelete(Pkg,_config->FindB("APT::Get::Purge",false));
841       return true;
842    }
843    
844    // Install it
845    Cache.MarkInstall(Pkg,false);
846    if (State.Install() == false)
847    {
848       if (_config->FindB("APT::Get::ReInstall",false) == true)
849       {
850          if (Pkg->CurrentVer == 0 || Pkg.CurrentVer().Downloadable() == false)
851             ioprintf(c1out,_("Reinstallation of %s is not possible, it cannot be downloaded.\n"),
852                      Pkg.Name());
853          else
854             Cache.SetReInstall(Pkg,true);
855       }      
856       else
857       {
858          if (AllowFail == true)
859             ioprintf(c1out,_("%s is already the newest version.\n"),
860                      Pkg.Name());
861       }      
862    }   
863    else
864       ExpectedInst++;
865    
866    // Install it with autoinstalling enabled.
867    if (State.InstBroken() == true && BrokenFix == false)
868       Cache.MarkInstall(Pkg,true);
869    return true;
870 }
871                                                                         /*}}}*/
872 // TryToChangeVer - Try to change a candidate version                   /*{{{*/
873 // ---------------------------------------------------------------------
874 // CNC:2003-11-11
875 bool TryToChangeVer(pkgCache::PkgIterator &Pkg,pkgDepCache &Cache,
876                     int VerOp,const char *VerTag,bool IsRel)
877 {
878    // CNC:2003-11-05
879    pkgVersionMatch Match(VerTag,(IsRel == true?pkgVersionMatch::Release : 
880                                  pkgVersionMatch::Version),VerOp);
881    
882    pkgCache::VerIterator Ver = Match.Find(Pkg);
883                          
884    if (Ver.end() == true)
885    {
886       // CNC:2003-11-05
887       if (IsRel == true)
888          return _error->Error(_("Release %s'%s' for '%s' was not found"),
889                               op2str(VerOp),VerTag,Pkg.Name());
890       return _error->Error(_("Version %s'%s' for '%s' was not found"),
891                            op2str(VerOp),VerTag,Pkg.Name());
892    }
893    
894    if (strcmp(VerTag,Ver.VerStr()) != 0)
895    {
896       // CNC:2003-11-11
897       if (IsRel == true)
898          ioprintf(c1out,_("Selected version %s (%s) for %s\n"),
899                   Ver.VerStr(),Ver.RelStr().c_str(),Pkg.Name());
900       else
901          ioprintf(c1out,_("Selected version %s for %s\n"),
902                   Ver.VerStr(),Pkg.Name());
903    }
904    
905    Cache.SetCandidateVersion(Ver);
906    // CNC:2003-11-11
907    Pkg = Ver.ParentPkg();
908    return true;
909 }
910                                                                         /*}}}*/
911
912 // DoUpdate - Update the package lists                                  /*{{{*/
913 // ---------------------------------------------------------------------
914 /* */
915
916 // CNC:2004-04-19
917 class UpdateLogCleaner : public pkgArchiveCleaner
918 {
919    protected:
920    virtual void Erase(const char *File,string Pkg,string Ver,struct stat &St) 
921    {
922       c1out << "Del " << Pkg << " " << Ver << " [" << SizeToStr(St.st_size) << "B]" << endl;
923       unlink(File);      
924    }
925 };
926
927 bool DoUpdate(CommandLine &CmdL)
928 {
929    if (CheckHelp(CmdL) == true)
930       return true;
931
932    bool Partial = false;
933    pkgSourceList List;
934
935    if (CmdL.FileSize() != 1)
936    {
937       List.ReadVendors();
938       for (const char **I = CmdL.FileList + 1; *I != 0; I++)
939       {
940          string Repo = _config->FindDir("Dir::Etc::sourceparts") + *I;
941          if (FileExists(Repo) == false)
942             Repo += ".list";
943          if (FileExists(Repo) == true)
944          {
945             if (List.ReadAppend(Repo) == true)
946                Partial = true;
947             else
948                return _error->Error(_("Sources list %s could not be read"),Repo.c_str());
949          }
950          else
951             return _error->Error(_("Sources list %s doesn't exist"),Repo.c_str());
952       }
953    }
954    else if (List.ReadMainList() == false)
955       return false;
956
957    // Lock the list directory
958    FileFd Lock;
959    if (_config->FindB("Debug::NoLocking",false) == false)
960    {
961       Lock.Fd(GetLock(_config->FindDir("Dir::State::Lists") + "lock"));
962       if (_error->PendingError() == true)
963          return _error->Error(_("Unable to lock the list directory"));
964    }
965
966 // CNC:2003-03-19
967 #ifdef APT_WITH_LUA
968    _lua->SetDepCache(*GCache);
969    _lua->RunScripts("Scripts::AptGet::Update::Pre");
970    _lua->ResetCaches();
971 #endif
972    
973    // Create the download object
974    AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
975    pkgAcquire Fetcher(&Stat);
976
977    // CNC:2002-07-03
978    bool Failed = false;
979    // Populate it with release file URIs
980    if (List.GetReleases(&Fetcher) == false)
981       return false;
982    if (_config->FindB("APT::Get::Print-URIs") == false)
983    {
984       Fetcher.Run();
985       for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
986       {
987          if ((*I)->Status == pkgAcquire::Item::StatDone)
988             continue;
989          (*I)->Finished();
990          Failed = true;
991       }
992       if (Failed == true)
993          _error->Warning(_("Release files for some repositories could not be retrieved or authenticated. Such repositories are being ignored."));
994    }
995    
996    // Populate it with the source selection
997    if (List.GetIndexes(&Fetcher) == false)
998          return false;
999    
1000    // Just print out the uris an exit if the --print-uris flag was used
1001    if (_config->FindB("APT::Get::Print-URIs") == true)
1002    {
1003       pkgAcquire::UriIterator I = Fetcher.UriBegin();
1004       for (; I != Fetcher.UriEnd(); I++)
1005          cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' << 
1006                I->Owner->FileSize << ' ' << I->Owner->Checksum() << endl;
1007       return true;
1008    }
1009    
1010    // Run it
1011    if (Fetcher.Run() == pkgAcquire::Failed)
1012       return false;
1013
1014    for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
1015    {
1016       if ((*I)->Status == pkgAcquire::Item::StatDone)
1017          continue;
1018
1019       (*I)->Finished();
1020       
1021       fprintf(stderr,_("Failed to fetch %s  %s\n"),(*I)->DescURI().c_str(),
1022               (*I)->ErrorText.c_str());
1023       Failed = true;
1024    }
1025    
1026    // Clean out any old list files
1027    if (Partial == false && _config->FindB("APT::Get::List-Cleanup",true) == true)
1028    {
1029       if (Fetcher.Clean(_config->FindDir("Dir::State::lists")) == false ||
1030           Fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/") == false)
1031          return false;
1032    }
1033
1034    {
1035       AutoReOpenCache CacheGuard(GCache);
1036    }
1037
1038 // CNC:2003-03-19
1039 #ifdef APT_WITH_LUA
1040    _lua->SetDepCache(*GCache);
1041    _lua->RunScripts("Scripts::AptGet::Update::Post");
1042    _lua->ResetCaches();
1043 #endif
1044
1045    // CNC:2004-04-19
1046    if (Failed == false && _config->FindB("APT::Get::Archive-Cleanup",true) == true)
1047    {
1048       UpdateLogCleaner Cleaner;
1049       Cleaner.Go(_config->FindDir("Dir::Cache::archives"), *GCache);
1050       Cleaner.Go(_config->FindDir("Dir::Cache::archives") + "partial/",
1051                  *GCache);
1052    }
1053    
1054    if (Failed == true)
1055       return _error->Error(_("Some index files failed to download, they have been ignored, or old ones used instead."));
1056    
1057    return true;
1058 }
1059                                                                         /*}}}*/
1060 // DoUpgrade - Upgrade all packages                                     /*{{{*/
1061 // ---------------------------------------------------------------------
1062 /* Upgrade all packages without installing new packages or erasing old
1063    packages */
1064 bool DoUpgrade(CommandLine &CmdL)
1065 {
1066    if (CheckHelp(CmdL, 0) == true)
1067       return true;
1068    
1069    CacheFile &Cache = *GCache;
1070    if (GCache->CanCommit() == false) {
1071       _error->Error(_("You have no permissions for that"));
1072       return false;
1073    }
1074    
1075    AutoRestore StateGuard(Cache);
1076    
1077    if (GCache->CheckDeps() == false)
1078       return false;
1079
1080    // Do the upgrade
1081    if (pkgAllUpgrade(Cache) == false)
1082    {
1083       ShowBroken(c1out,Cache,false);
1084       return _error->Error(_("Internal Error, AllUpgrade broke stuff"));
1085    }
1086
1087 // CNC:2003-03-19
1088 #ifdef APT_WITH_LUA
1089    _lua->SetDepCache(Cache);
1090    _lua->RunScripts("Scripts::AptGet::Upgrade");
1091    _lua->ResetCaches();
1092 #endif
1093
1094    ConfirmChanges(Cache, StateGuard);
1095    
1096    return true;
1097 }
1098                                                                         /*}}}*/
1099 // DoInstall - Install packages from the command line                   /*{{{*/
1100 // ---------------------------------------------------------------------
1101 /* Install named packages */
1102 bool DoInstall(CommandLine &CmdL)
1103 {
1104    if (CheckHelp(CmdL) == true)
1105       return true;
1106
1107    CacheFile &Cache = *GCache;
1108    if (GCache->CanCommit() == false) {
1109       _error->Error(_("You have no permissions for that"));
1110       return false;
1111    }
1112    if (Cache.CheckDeps(CmdL.FileSize() != 1) == false)
1113       return false;
1114
1115    // Enter the special broken fixing mode if the user specified arguments
1116    bool BrokenFix = false;
1117    if (Cache->BrokenCount() != 0)
1118       BrokenFix = true;
1119    
1120    unsigned int ExpectedInst = 0;
1121    unsigned int Packages = 0;
1122    pkgProblemResolver Fix(Cache);
1123    
1124    int DefMode = MODE_INSTALL;
1125    if (strcasecmp(CmdL.FileList[0],"remove") == 0)
1126       DefMode = MODE_REMOVE;
1127    else if (strcasecmp(CmdL.FileList[0],"keep") == 0)
1128       DefMode = MODE_KEEP;
1129
1130    AutoRestore StateGuard(Cache);
1131
1132    for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1133    {
1134       // Duplicate the string
1135       size_t Length = strlen(*I);
1136       char S[300];
1137       if (Length >= sizeof(S))
1138          continue;
1139       strcpy(S,*I);
1140       
1141       // CNC:2003-03-15
1142       char OrigS[300];
1143       strcpy(OrigS,S);
1144       
1145       // See if we are removing and special indicators..
1146       int Mode = DefMode;
1147       char *VerTag = 0;
1148       bool VerIsRel = false;
1149       // CNC:2003-11-05
1150       int VerOp = 0;
1151       while (Cache->FindPkg(S).end() == true)
1152       {
1153          // Handle an optional end tag indicating what to do
1154          if (Length >= 1 && S[Length - 1] == '-')
1155          {
1156             Mode = MODE_REMOVE;
1157             S[--Length] = 0;
1158             continue;
1159          }
1160          
1161          if (Length >= 1 && S[Length - 1] == '+')
1162          {
1163             Mode = MODE_INSTALL;
1164             S[--Length] = 0;
1165             continue;
1166          }
1167          
1168          // CNC:2003-11-05
1169          char *sep = strpbrk(S,"=><");
1170          if (sep)
1171          {
1172             char *p;
1173             int eq = 0, gt = 0, lt = 0;
1174
1175             VerIsRel = false;
1176             for (p = sep; *p && strchr("=><",*p); ++p)
1177                switch (*p)
1178                {
1179                   case '=': eq = 1; break;
1180                   case '>': gt = 1; break;
1181                   case '<': lt = 1; break;
1182                }
1183             if (eq)
1184             {
1185                if (lt && gt)
1186                   return _error->Error(_("Couldn't parse name '%s'"),S);
1187                else if (lt)
1188                   VerOp = pkgCache::Dep::LessEq;
1189                else if (gt)
1190                   VerOp = pkgCache::Dep::GreaterEq;
1191                else
1192                   VerOp = pkgCache::Dep::Equals;
1193             }
1194             else
1195             {
1196                if (lt && gt)
1197                   VerOp = pkgCache::Dep::NotEquals;
1198                else if (lt)
1199                   VerOp = pkgCache::Dep::Less;
1200                else if (gt)
1201                   VerOp = pkgCache::Dep::Greater;
1202                else
1203                   return _error->Error(_("Couldn't parse name '%s'"),S);
1204             }
1205             *sep = '\0';
1206             /* S may be overwritten later, for example, if it contains
1207              * a file name that will be resolved to a package.
1208              * So we point VerTag to the same offset in OrigS. */
1209             VerTag = (p - S) + OrigS;
1210          }
1211          
1212          // CNC:2003-11-21 - Try to handle unknown file items.
1213          if (S[0] == '/')
1214          {
1215             pkgRecords Recs(Cache);
1216             if (_error->PendingError() == true)
1217                return false;
1218             pkgCache::PkgIterator Pkg = (*Cache).PkgBegin();
1219             for (; Pkg.end() == false; Pkg++)
1220             {
1221                // Should we try on all versions?
1222                pkgCache::VerIterator Ver = (*Cache)[Pkg].CandidateVerIter(*Cache);
1223                if (Ver.end() == false)
1224                {
1225                   pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList());
1226                   if (Parse.HasFile(S)) {
1227                      strcpy(S, Pkg.Name());
1228                      // Confirm the translation.
1229                      ExpectedInst += 1000;
1230                      break;
1231                   }
1232                }
1233             }
1234          }
1235
1236          char *Slash = strchr(S,'/');
1237          if (Slash != 0)
1238          {
1239             VerIsRel = true;
1240             *Slash = 0;
1241             VerTag = Slash + 1;
1242          }
1243          
1244          break;
1245       }
1246       
1247       // Locate the package
1248       pkgCache::PkgIterator Pkg = Cache->FindPkg(S);
1249       Packages++;
1250       if (Pkg.end() == true)
1251       {
1252          // Check if the name is a regex
1253          const char *I;
1254          for (I = S; *I != 0; I++)
1255             if (*I == '?' || *I == '*' || *I == '|' ||
1256                 *I == '[' || *I == '^' || *I == '$')
1257                break;
1258
1259          // CNC:2003-05-15
1260          if (*I == 0) {
1261 #ifdef APT_WITH_LUA
1262             vector<string> VS;
1263             _lua->SetDepCache(Cache);
1264             _lua->SetDontFix();
1265             _lua->SetGlobal("argument", OrigS);
1266             _lua->SetGlobal("translated", VS);
1267             _lua->RunScripts("Scripts::AptGet::Install::TranslateArg");
1268             const char *name = _lua->GetGlobalStr("translated");
1269             if (name != NULL) {
1270                VS.push_back(name);
1271             } else {
1272                VS = _lua->GetGlobalStrList("translated");
1273             }
1274             _lua->ResetGlobals();
1275             _lua->ResetCaches();
1276
1277             // Translations must always be confirmed
1278             ExpectedInst += 1000;
1279
1280             // Run over the matches
1281             bool Hit = false;
1282             for (vector<string>::const_iterator I = VS.begin();
1283                  I != VS.end(); I++) {
1284
1285                Pkg = Cache->FindPkg(*I);
1286                if (Pkg.end() == true)
1287                   continue;
1288
1289                ioprintf(c1out,_("Selecting %s for '%s'\n"),
1290                         Pkg.Name(),OrigS);
1291             
1292                Hit |= TryToInstall(Pkg,Cache,Fix,Mode,BrokenFix,
1293                                    ExpectedInst,true);
1294             }
1295          
1296             if (Hit == true)
1297                continue;
1298 #endif
1299             return _error->Error(_("Couldn't find package %s"),S);
1300          }
1301
1302          // Regexs must always be confirmed
1303          ExpectedInst += 1000;
1304          
1305          // Compile the regex pattern
1306          regex_t Pattern;
1307          int Res;
1308          if ((Res = regcomp(&Pattern,S,REG_EXTENDED | REG_ICASE |
1309                      REG_NOSUB)) != 0)
1310          {
1311             char Error[300];        
1312             regerror(Res,&Pattern,Error,sizeof(Error));
1313             return _error->Error(_("Regex compilation error - %s"),Error);
1314          }
1315          
1316          // Run over the matches
1317          bool Hit = false;
1318          for (Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
1319          {
1320             if (regexec(&Pattern,Pkg.Name(),0,0,0) != 0)
1321                continue;
1322             
1323             // CNC:2003-11-23
1324             ioprintf(c1out,_("Selecting %s for '%s'\n"),
1325                      Pkg.Name(),S);
1326             StateGuard->Ignore(Pkg);
1327             
1328             if (VerTag != 0)
1329                // CNC:2003-11-05
1330                if (TryToChangeVer(Pkg,Cache,VerOp,VerTag,VerIsRel) == false)
1331                   return false;
1332             
1333             Hit |= TryToInstall(Pkg,Cache,Fix,Mode,BrokenFix,
1334                                 ExpectedInst,false);
1335          }
1336          regfree(&Pattern);
1337          
1338          if (Hit == false)
1339             return _error->Error(_("Couldn't find package %s"),S);
1340       }
1341       else
1342       {
1343          if (VerTag != 0)
1344             // CNC:2003-11-05
1345             if (TryToChangeVer(Pkg,Cache,VerOp,VerTag,VerIsRel) == false)
1346                return false;
1347          if (TryToInstall(Pkg,Cache,Fix,Mode,BrokenFix,ExpectedInst) == false)
1348             return false;
1349          StateGuard->Ignore(Pkg);
1350       }
1351    }
1352
1353 // CNC:2003-03-19
1354 #ifdef APT_WITH_LUA
1355    _lua->SetDepCache(Cache);
1356    _lua->SetDontFix();
1357    _lua->RunScripts("Scripts::AptGet::Install::PreResolve");
1358    _lua->ResetCaches();
1359 #endif
1360
1361    // CNC:2002-08-01
1362    if (_config->FindB("APT::Remove-Depends",false) == true)
1363       Fix.RemoveDepends();
1364
1365    /* If we are in the Broken fixing mode we do not attempt to fix the
1366       problems. This is if the user invoked install without -f and gave
1367       packages */
1368    if (BrokenFix == true && Cache->BrokenCount() != 0)
1369    {
1370       ConfirmChanges(Cache, StateGuard);
1371       c1out << _("There are still broken packages. ")
1372             << _("Run `check' to see them.") << endl;
1373       c1out << _("You can try to fix them automatically with `install --fix-broken'.") << endl;
1374       return true;
1375    }
1376
1377    // Call the scored problem resolver
1378    if (DefMode != MODE_KEEP) {
1379       Fix.InstallProtect();
1380       if (Fix.Resolve(true) == false)
1381          _error->Discard();
1382    } else {
1383       if (Fix.Resolve(false) == false)
1384          _error->Discard();
1385    }
1386
1387 // CNC:2003-03-19
1388 #ifdef APT_WITH_LUA
1389    if (Cache->BrokenCount() == 0) {
1390       _lua->SetDepCache(Cache);
1391       _lua->SetProblemResolver(&Fix);
1392       _lua->RunScripts("Scripts::AptGet::Install::PostResolve");
1393       _lua->ResetCaches();
1394    }
1395 #endif
1396
1397
1398    // Now we check the state of the packages,
1399    if (Cache->BrokenCount() != 0)
1400    {
1401       c1out << 
1402        _("Some packages could not be installed. This may mean that you have\n" 
1403          "requested an impossible situation or that some of the repositories\n"
1404          "in use are in an inconsistent state at the moment.") << endl;
1405       if (Packages == 1)
1406       {
1407          c1out << endl;
1408          c1out << 
1409           _("Since you only requested a single operation it is extremely likely that\n"
1410             "the package is simply not installable and a bug report against\n" 
1411             "that package should be filed.") << endl;
1412       }
1413
1414       c1out << _("The following information may help to resolve the situation:") << endl;
1415       c1out << endl;
1416       ShowBroken(c1out,Cache,false);
1417
1418       return _error->Error(_("Broken packages"));
1419    }
1420
1421    ConfirmChanges(Cache, StateGuard);
1422
1423    return true;
1424 }
1425                                                                         /*}}}*/
1426 // DoDistUpgrade - Automatic smart upgrader                             /*{{{*/
1427 // ---------------------------------------------------------------------
1428 /* Intelligent upgrader that will install and remove packages at will */
1429 bool DoDistUpgrade(CommandLine &CmdL)
1430 {
1431    if (CheckHelp(CmdL,0) == true)
1432       return true;
1433
1434    CacheFile &Cache = *GCache;
1435    if (GCache->CanCommit() == false) {
1436       _error->Error(_("You have no permissions for that"));
1437       return false;
1438    }
1439
1440    AutoRestore StateGuard(Cache);
1441
1442    if (GCache->CheckDeps() == false)
1443       return false;
1444
1445    c0out << _("Calculating Upgrade... ") << flush;
1446    if (pkgDistUpgrade(*Cache) == false)
1447    {
1448       c0out << _("Failed") << endl;
1449       ShowBroken(c1out,Cache,false);
1450       return false;
1451    }
1452
1453 // CNC:2003-03-19
1454 #ifdef APT_WITH_LUA
1455    _lua->SetDepCache(Cache);
1456    _lua->RunScripts("Scripts::AptGet::DistUpgrade");
1457    _lua->ResetCaches();
1458 #endif
1459    
1460    c0out << _("Done") << endl;
1461    
1462    ConfirmChanges(Cache, StateGuard);
1463
1464    return true;
1465 }
1466                                                                         /*}}}*/
1467 // DoClean - Remove download archives                                   /*{{{*/
1468 // ---------------------------------------------------------------------
1469 /* */
1470 bool DoClean(CommandLine &CmdL)
1471 {
1472    if (CheckHelp(CmdL,0) == true)
1473       return true;
1474
1475    return cmdDoClean(CmdL);
1476 }
1477                                                                         /*}}}*/
1478 bool DoAutoClean(CommandLine &CmdL)
1479 {
1480    if (CheckHelp(CmdL,0) == true)
1481       return true;
1482
1483    // Lock the archive directory
1484    FileFd Lock;
1485    if (_config->FindB("Debug::NoLocking",false) == false)
1486    {
1487       Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
1488       if (_error->PendingError() == true)
1489          return _error->Error(_("Unable to lock the download directory"));
1490    }
1491    
1492    CacheFile &Cache = *GCache;
1493 #if 0
1494    if (Cache.Open() == false)
1495       return false;
1496 #endif
1497    
1498    LogCleaner Cleaner;
1499    
1500    return Cleaner.Go(_config->FindDir("Dir::Cache::archives"),*Cache) &&
1501       Cleaner.Go(_config->FindDir("Dir::Cache::archives") + "partial/",*Cache);
1502 }
1503                                                                         /*}}}*/
1504 // DoCheck - Perform the check operation                                /*{{{*/
1505 // ---------------------------------------------------------------------
1506 /* Opening automatically checks the system, this command is mostly used
1507    for debugging */
1508 bool DoCheck(CommandLine &CmdL)
1509 {
1510    if (CheckHelp(CmdL,0) == true)
1511       return true;
1512
1513    CacheFile &Cache = *GCache;
1514    AutoRestore StateGuard(Cache);
1515
1516    if (GCache->CheckDeps() == false)
1517       return false;
1518    
1519    return true;
1520 }
1521                                                                         /*}}}*/
1522 // DoBuildDep - Install/removes packages to satisfy build dependencies  /*{{{*/
1523 // ---------------------------------------------------------------------
1524 /* This function will look at the build depends list of the given source 
1525    package and install the necessary packages to make it true, or fail. */
1526 bool DoBuildDep(CommandLine &CmdL)
1527 {
1528    if (CheckHelp(CmdL) == true)
1529       return true;
1530
1531    CacheFile &Cache = *GCache;
1532    if (GCache->CanCommit() == false) {
1533       _error->Error(_("You have no permissions for that"));
1534       return false;
1535    }
1536    
1537    AutoRestore StateGuard(Cache);
1538    
1539    if (GCache->CheckDeps() == false)
1540       return false;
1541
1542    if (CmdL.FileSize() <= 1)
1543       return _error->Error(_("Must specify at least one package to check builddeps for"));
1544    
1545    // Read the source list
1546    pkgSourceList List;
1547    if (List.ReadMainList() == false)
1548       return _error->Error(_("The list of sources could not be read."));
1549    
1550    // Create the text record parsers
1551    pkgRecords Recs(Cache);
1552    pkgSrcRecords SrcRecs(List);
1553    if (_error->PendingError() == true)
1554       return false;
1555
1556    // Create the download object
1557    AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));   
1558    pkgAcquire Fetcher(&Stat);
1559
1560    unsigned J = 0;
1561    for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++)
1562    {
1563       string Src;
1564       pkgSrcRecords::Parser *Last = FindSrc(*I,Recs,SrcRecs,Src,*Cache);
1565       if (Last == 0)
1566          return _error->Error(_("Unable to find a source package for %s"),Src.c_str());
1567             
1568       // Process the build-dependencies
1569       vector<pkgSrcRecords::Parser::BuildDepRec> BuildDeps;
1570       if (Last->BuildDepends(BuildDeps, _config->FindB("APT::Get::Arch-Only",false)) == false)
1571         return _error->Error(_("Unable to get build-dependency information for %s"),Src.c_str());
1572    
1573       // Also ensure that build-essential packages are present
1574       Configuration::Item const *Opts = _config->Tree("APT::Build-Essential");
1575       if (Opts) 
1576          Opts = Opts->Child;
1577       for (; Opts; Opts = Opts->Next)
1578       {
1579          if (Opts->Value.empty() == true)
1580             continue;
1581
1582          pkgSrcRecords::Parser::BuildDepRec rec;
1583          rec.Package = Opts->Value;
1584          rec.Type = pkgSrcRecords::Parser::BuildDependIndep;
1585          rec.Op = 0;
1586          BuildDeps.push_back(rec);
1587       }
1588
1589       if (BuildDeps.size() == 0)
1590       {
1591          ioprintf(c1out,_("%s has no build depends.\n"),Src.c_str());
1592          continue;
1593       }
1594       
1595       // Install the requested packages
1596       unsigned int ExpectedInst = 0;
1597       vector <pkgSrcRecords::Parser::BuildDepRec>::iterator D;
1598       pkgProblemResolver Fix(Cache);
1599       bool skipAlternatives = false; // skip remaining alternatives in an or group
1600       for (D = BuildDeps.begin(); D != BuildDeps.end(); D++)
1601       {
1602          bool hasAlternatives = (((*D).Op & pkgCache::Dep::Or) == pkgCache::Dep::Or);
1603
1604          if (skipAlternatives == true)
1605          {
1606             if (!hasAlternatives)
1607                skipAlternatives = false; // end of or group
1608             continue;
1609          }
1610
1611          if ((*D).Type == pkgSrcRecords::Parser::BuildConflict ||
1612              (*D).Type == pkgSrcRecords::Parser::BuildConflictIndep)
1613          {
1614             pkgCache::PkgIterator Pkg = Cache->FindPkg((*D).Package);
1615             // Build-conflicts on unknown packages are silently ignored
1616             if (Pkg.end() == true)
1617                continue;
1618
1619             pkgCache::VerIterator IV = (*Cache)[Pkg].InstVerIter(*Cache);
1620
1621             /* 
1622              * Remove if we have an installed version that satisfies the 
1623              * version criteria
1624              */
1625             if (IV.end() == false && 
1626                 Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
1627                TryToInstall(Pkg,Cache,Fix,MODE_REMOVE,false,ExpectedInst);
1628          }
1629          else // BuildDep || BuildDepIndep
1630          {
1631             if (_config->FindB("Debug::BuildDeps",false) == true)
1632                  cout << "Looking for " << (*D).Package << "...\n";
1633
1634             pkgCache::PkgIterator Pkg = Cache->FindPkg((*D).Package);
1635
1636             // CNC:2003-11-21 - Try to handle unknown file deps.
1637             if (Pkg.end() == true && (*D).Package[0] == '/')
1638             {
1639                const char *File = (*D).Package.c_str();
1640                Pkg = (*Cache).PkgBegin();
1641                for (; Pkg.end() == false; Pkg++)
1642                {
1643                   // Should we try on all versions?
1644                   pkgCache::VerIterator Ver = (*Cache)[Pkg].CandidateVerIter(*Cache);
1645                   if (Ver.end() == false)
1646                   {
1647                      pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList());
1648                      if (Parse.HasFile(File))
1649                         break;
1650                   }
1651                }
1652             }
1653
1654             if (Pkg.end() == true)
1655             {
1656                if (_config->FindB("Debug::BuildDeps",false) == true)
1657                     cout << " (not found)" << (*D).Package << endl;
1658
1659                if (hasAlternatives)
1660                   continue;
1661
1662                return _error->Error(_("%s dependency for %s cannot be satisfied "
1663                                       "because the package %s cannot be found"),
1664                                     Last->BuildDepType((*D).Type),Src.c_str(),
1665                                     (*D).Package.c_str());
1666             }
1667
1668             /*
1669              * if there are alternatives, we've already picked one, so skip
1670              * the rest
1671              *
1672              * TODO: this means that if there's a build-dep on A|B and B is
1673              * installed, we'll still try to install A; more importantly,
1674              * if A is currently broken, we cannot go back and try B. To fix 
1675              * this would require we do a Resolve cycle for each package we 
1676              * add to the install list. Ugh
1677              */
1678                        
1679             /* 
1680              * If this is a virtual package, we need to check the list of
1681              * packages that provide it and see if any of those are
1682              * installed
1683              */
1684             pkgCache::PrvIterator Prv = Pkg.ProvidesList();
1685             for (; Prv.end() != true; Prv++)
1686             {
1687                if (_config->FindB("Debug::BuildDeps",false) == true)
1688                     cout << "  Checking provider " << Prv.OwnerPkg().Name() << endl;
1689
1690                if ((*Cache)[Prv.OwnerPkg()].InstVerIter(*Cache).end() == false)
1691                   break;
1692             }
1693             
1694             // Get installed version and version we are going to install
1695             pkgCache::VerIterator IV = (*Cache)[Pkg].InstVerIter(*Cache);
1696
1697             if ((*D).Version[0] != '\0') {
1698                  // Versioned dependency
1699
1700                  pkgCache::VerIterator CV = (*Cache)[Pkg].CandidateVerIter(*Cache);
1701
1702                  for (; CV.end() != true; CV++)
1703                  {
1704                       if (Cache->VS().CheckDep(CV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
1705                            break;
1706                  }
1707                  if (CV.end() == true)
1708                  {
1709                    if (hasAlternatives)
1710                    {
1711                       continue;
1712                    }
1713                    else
1714                    {
1715                       return _error->Error(_("%s dependency for %s cannot be satisfied "
1716                                              "because no available versions of package %s "
1717                                              "can satisfy version requirements"),
1718                                            Last->BuildDepType((*D).Type),Src.c_str(),
1719                                            (*D).Package.c_str());
1720                    }
1721                  }
1722             }
1723             else
1724             {
1725                // Only consider virtual packages if there is no versioned dependency
1726                if (Prv.end() == false)
1727                {
1728                   if (_config->FindB("Debug::BuildDeps",false) == true)
1729                      cout << "  Is provided by installed package " << Prv.OwnerPkg().Name() << endl;
1730                   skipAlternatives = hasAlternatives;
1731                   continue;
1732                }
1733             }
1734             if (IV.end() == false)
1735             {
1736                if (_config->FindB("Debug::BuildDeps",false) == true)
1737                   cout << "  Is installed\n";
1738
1739                if (Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
1740                {
1741                   skipAlternatives = hasAlternatives;
1742                   continue;
1743                }
1744
1745                if (_config->FindB("Debug::BuildDeps",false) == true)
1746                   cout << "    ...but the installed version doesn't meet the version requirement\n";
1747
1748                if (((*D).Op & pkgCache::Dep::LessEq) == pkgCache::Dep::LessEq)
1749                {
1750                   return _error->Error(_("Failed to satisfy %s dependency for %s: Installed package %s is too new"),
1751                                        Last->BuildDepType((*D).Type),
1752                                        Src.c_str(),
1753                                        Pkg.Name());
1754                }
1755             }
1756
1757
1758             if (_config->FindB("Debug::BuildDeps",false) == true)
1759                cout << "  Trying to install " << (*D).Package << endl;
1760
1761             if (TryToInstall(Pkg,Cache,Fix,false,false,ExpectedInst) == true)
1762             {
1763                // We successfully installed something; skip remaining alternatives
1764                skipAlternatives = hasAlternatives;
1765                continue;
1766             }
1767             else if (hasAlternatives)
1768             {
1769                if (_config->FindB("Debug::BuildDeps",false) == true)
1770                   cout << "  Unsatisfiable, trying alternatives\n";
1771                continue;
1772             }
1773             else
1774             {
1775                return _error->Error(_("Failed to satisfy %s dependency for %s: %s"),
1776                                     Last->BuildDepType((*D).Type),
1777                                     Src.c_str(),
1778                                     (*D).Package.c_str());
1779             }
1780          }             
1781       }
1782       
1783       Fix.InstallProtect();
1784       if (Fix.Resolve(true) == false)
1785          _error->Discard();
1786       
1787       // Now we check the state of the packages,
1788       if (Cache->BrokenCount() != 0)
1789          return _error->Error(_("Some broken packages were found while trying to process build-dependencies for %s.\n"
1790                                 "You might want to run `apt-get --fix-broken install' to correct these."),*I);
1791    }
1792   
1793    ConfirmChanges(Cache, StateGuard);
1794
1795    return true;
1796 }
1797                                                                         /*}}}*/
1798 // * - Scripting stuff.                                                 /*{{{*/
1799 // ---------------------------------------------------------------------
1800 /* */
1801 bool DoScript(CommandLine &CmdL)
1802 {
1803    if (CheckHelp(CmdL) == true)
1804       return true;
1805
1806    CacheFile &Cache = *GCache;
1807    AutoRestore StateGuard(Cache);
1808
1809    for (const char **I = CmdL.FileList+1; *I != 0; I++)
1810       _config->Set("Scripts::AptShell::Script::", *I);
1811
1812 // CNC:2003-03-19
1813 #ifdef APT_WITH_LUA
1814    _lua->SetDepCache(Cache);
1815    _lua->RunScripts("Scripts::AptShell::Script");
1816    _lua->RunScripts("Scripts::AptGet::Script");
1817    _lua->RunScripts("Scripts::AptCache::Script");
1818    _lua->ResetCaches();
1819 #endif
1820
1821    _config->Clear("Scripts::AptShell::Script");
1822
1823    ConfirmChanges(Cache, StateGuard);
1824
1825    return true;
1826 }
1827
1828                                                                         /*}}}*/
1829
1830 // --- Unchanged stuff from apt-cache.
1831
1832
1833 // Depends - Print out a dependency tree                                /*{{{*/
1834 // ---------------------------------------------------------------------
1835 /* */
1836 bool Depends(CommandLine &CmdL)
1837 {
1838    if (CheckHelp(CmdL) == true)
1839       return true;
1840
1841    return cmdDepends(CmdL, *GCache);
1842 }
1843                                                                         /*}}}*/
1844 // RDepends - Print out a reverse dependency tree - mbc                 /*{{{*/
1845 // ---------------------------------------------------------------------
1846 /* */
1847 bool RDepends(CommandLine &CmdL)
1848 {
1849    if (CheckHelp(CmdL) == true)
1850       return true;
1851
1852    return cmdRDepends(CmdL, *GCache);
1853 }
1854
1855                                                                         /*}}}*/
1856 // CNC:2003-02-19
1857 // WhatDepends - Print out a reverse dependency tree                    /*{{{*/
1858 // ---------------------------------------------------------------------
1859 /* */
1860 bool WhatDepends(CommandLine &CmdL)
1861 {
1862    if (CheckHelp(CmdL) == true)
1863       return true;
1864
1865    return cmdWhatDepends(CmdL, *GCache);
1866 }
1867
1868 bool WhatProvides(CommandLine &CmdL)
1869 {
1870    if (CheckHelp(CmdL) == true)
1871       return true;
1872
1873    return cmdWhatProvides(CmdL, *GCache);
1874 }
1875                                                                         /*}}}*/
1876 // UnMet - Show unmet dependencies                                      /*{{{*/
1877 // ---------------------------------------------------------------------
1878 /* */
1879 bool UnMet(CommandLine &CmdL)
1880 {
1881    if (CheckHelp(CmdL,0) == true)
1882       return true;
1883
1884    return cmdUnMet(CmdL, *GCache);
1885 }
1886                                                                         /*}}}*/
1887 // DumpPackage - Show a dump of a package record                        /*{{{*/
1888 // ---------------------------------------------------------------------
1889 /* */
1890 bool DumpPackage(CommandLine &CmdL)
1891 {   
1892    if (CheckHelp(CmdL) == true)
1893       return true;
1894
1895    return cmdDumpPackage(CmdL, *GCache);
1896 }
1897                                                                         /*}}}*/
1898 // DisplayRecord - Displays the complete record for the package         /*{{{*/
1899 // ---------------------------------------------------------------------
1900 /* This displays the package record from the proper package index file. 
1901    It is not used by DumpAvail for performance reasons. */
1902 bool DisplayRecord(pkgCache::VerIterator V)
1903 {
1904    return cmdDisplayRecord(V, *GCache);
1905 }
1906                                                                         /*}}}*/
1907 bool Search(CommandLine &CmdL)
1908 {
1909    if (CheckHelp(CmdL) == true)
1910       return true;
1911
1912    return cmdSearch(CmdL, *GCache);
1913 }
1914
1915 bool SearchFile(CommandLine &CmdL)
1916 {
1917    if (CheckHelp(CmdL) == true)
1918       return true;
1919
1920    return cmdSearchFile(CmdL, *GCache);
1921 }
1922
1923 bool FileList(CommandLine &CmdL)
1924 {
1925    if (CheckHelp(CmdL) == true)
1926       return true;
1927
1928    return cmdFileList(CmdL, *GCache);
1929 }
1930
1931 bool ChangeLog(CommandLine &CmdL)
1932 {
1933    if (CheckHelp(CmdL) == true)
1934       return true;
1935
1936    return cmdChangeLog(CmdL, *GCache);
1937 }
1938
1939 // DoList - List packages.                                              /*{{{*/
1940 // ---------------------------------------------------------------------
1941 /* */
1942 bool DoList(CommandLine &CmdL)
1943 {
1944    if (CheckHelp(CmdL) == true)
1945       return true;
1946
1947    return cmdDoList(CmdL, *GCache);
1948 }
1949
1950                                                                         /*}}}*/
1951 // ShowPackage - Dump the package record to the screen                  /*{{{*/
1952 // ---------------------------------------------------------------------
1953 /* */
1954 bool ShowPackage(CommandLine &CmdL)
1955 {   
1956    if (CheckHelp(CmdL) == true)
1957       return true;
1958
1959    return cmdShowPackage(CmdL, *GCache);
1960 }
1961 // --- End of stuff from apt-cache.
1962
1963
1964 // ShowHelp - Show a help screen                                        /*{{{*/
1965 // ---------------------------------------------------------------------
1966 /* */
1967 bool ShowHelp(CommandLine &CmdL)
1968 {
1969    if (CheckHelp(CmdL) == true)
1970       return true;
1971
1972    if (CmdL.FileSize() > 1) {
1973       CommandHelp(CmdL.FileList[1]);
1974       return true;
1975    }
1976
1977    ioprintf(cout,_("%s %s for %s %s compiled on %s %s\n"),PACKAGE,VERSION,
1978             COMMON_OS,COMMON_CPU,__DATE__,__TIME__);
1979             
1980    if (_config->FindB("version") == true)
1981    {
1982       cout << _("Supported Modules:") << endl;
1983       
1984       for (unsigned I = 0; I != pkgVersioningSystem::GlobalListLen; I++)
1985       {
1986          pkgVersioningSystem *VS = pkgVersioningSystem::GlobalList[I];
1987          if (_system != 0 && _system->VS == VS)
1988             cout << '*';
1989          else
1990             cout << ' ';
1991          cout << "Ver: " << VS->Label << endl;
1992          
1993          /* Print out all the packaging systems that will work with 
1994             this VS */
1995          for (unsigned J = 0; J != pkgSystem::GlobalListLen; J++)
1996          {
1997             pkgSystem *Sys = pkgSystem::GlobalList[J];
1998             if (_system == Sys)
1999                cout << '*';
2000             else
2001                cout << ' ';
2002             if (Sys->VS->TestCompatibility(*VS) == true)
2003                cout << "Pkg:  " << Sys->Label << " (Priority " << Sys->Score(*_config) << ")" << endl;
2004          }
2005       }
2006       
2007       for (unsigned I = 0; I != pkgSourceList::Type::GlobalListLen; I++)
2008       {
2009          pkgSourceList::Type *Type = pkgSourceList::Type::GlobalList[I];
2010          cout << " S.L: '" << Type->Name << "' " << Type->Label << endl;
2011       }      
2012       
2013       for (unsigned I = 0; I != pkgIndexFile::Type::GlobalListLen; I++)
2014       {
2015          pkgIndexFile::Type *Type = pkgIndexFile::Type::GlobalList[I];
2016          cout << " Idx: " << Type->Label << endl;
2017       }      
2018       
2019       return true;
2020    }
2021    
2022    cout << 
2023     _("\n"
2024       "Main commands:\n"
2025       "   status - Show the current selections\n"
2026       "   install - Install new packages\n"
2027       "   remove - Remove packages\n"
2028       "   keep - Keep packages\n"
2029       "   upgrade - Perform a global upgrade\n"
2030       "   dist-upgrade - Perform a global distribution upgrade\n"
2031       "   build-dep - Install build-dependencies for source packages\n"
2032 //      "   dselect-upgrade - Follow dselect selections\n"
2033       "   update - Retrieve new lists of packages\n"
2034       "   commit - Apply the changes in the system\n"
2035       "   quit - Leave the APT shell\n"
2036       "\n"
2037       "Auxiliar commands:\n"
2038       "   show - Show a readable record for the package\n"
2039       "   showpkg - Show some general information for a single package\n"
2040       "   list/ls - List packages\n"
2041       "   search - Search the package list for a regex pattern\n"
2042       "   searchfile - Search the packages for a file\n"
2043       "   files - Show file list of the package(s)\n"
2044       "   changelog - Show changelog entries of the package(s)\n"
2045       "   script - Run scripts.\n"
2046       "   depends - Show raw dependency information for a package\n"
2047       "   whatdepends - Show packages depending on given capabilities\n"
2048       // "   rdepends - Show reverse dependency information for a package\n"
2049       "   whatprovides - Show packages that provide given capabilities\n"
2050       "   check - Verify that there are no broken dependencies\n"
2051       "   unmet - Show unmet dependencies\n"
2052       "   clean - Erase downloaded archive files\n"
2053       "   autoclean - Erase old downloaded archive files\n"
2054       "\n"
2055       "For more information type \"help <cmd>\" or \"<cmd> [-h|--help]\".\n"
2056       "\n"
2057       "                       This APT has Super Cow Powers.\n");
2058    return true;
2059 }
2060
2061 void CommandHelp(const char *Name)
2062 {
2063    unsigned long Hash = 0;
2064    for (const char *p=Name; *p; p++)
2065       Hash = 5*Hash + *p;
2066    switch (Hash%1000000) {
2067       case 73823: // install
2068          c2out << _(
2069             "Usage: install [options] pkg1[=ver] [pkg2 ...]\n"
2070             "\n"
2071             "Try to mark the given packages for installation (new packages,\n"
2072             "upgrades or downgrades) changing other packages if necessary.\n"
2073             "\n"
2074             "Options:\n"
2075             "  -h  This help text.\n"
2076             "  -y  Assume Yes to all queries and do not prompt\n"
2077             "  -f  Attempt to continue if the integrity check fails\n"
2078             "  -m  Attempt to continue if archives are unlocatable\n"
2079             "  -D  When removing packages, remove dependencies as possible\n"
2080             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
2081             "\n"
2082          );
2083          break;
2084
2085       case 436466: // remove
2086          c2out << _(
2087             "Usage: remove [options] pkg1 [pkg2 ...]\n"
2088             "\n"
2089             "Try to mark the given packages for deletion, changing other\n"
2090             "packages if necessary.\n"
2091             "\n"
2092             "Options:\n"
2093             "  -h  This help text.\n"
2094             "  -y  Assume Yes to all queries and do not prompt\n"
2095             "  -f  Attempt to continue if the integrity check fails\n"
2096             "  -m  Attempt to continue if archives are unlocatable\n"
2097             "  -D  When removing packages, remove dependencies as possible\n"
2098             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
2099             "\n"
2100          );
2101          break;
2102
2103       case 16517: // keep
2104          c2out << _(
2105             "Usage: keep [options] pkg1 [pkg2 ...]\n"
2106             "\n"
2107             "Try to keep the given packages, currently marked for deletion\n"
2108             "or installation, in the system, changing other packages if\n"
2109             "necessary.\n"
2110             "\n"
2111             "Options:\n"
2112             "  -h  This help text.\n"
2113             "  -y  Assume Yes to all queries and do not prompt\n"
2114             "  -f  Attempt to continue if the integrity check fails\n"
2115             "  -m  Attempt to continue if archives are unlocatable\n"
2116             "  -D  When removing packages, remove dependencies as possible\n"
2117             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
2118             "\n"
2119          );
2120          break;
2121
2122       case 259776: // upgrade
2123          c2out << _(
2124             "Usage: upgrade [options]\n"
2125             "\n"
2126             "Perform a global upgrade.\n"
2127             "\n"
2128             "Options:\n"
2129             "  -h  This help text.\n"
2130             "  -y  Assume Yes to all queries and do not prompt\n"
2131             "  -f  Attempt to continue if the integrity check fails\n"
2132             "  -m  Attempt to continue if archives are unlocatable\n"
2133             "  -D  When removing packages, remove dependencies as possible\n"
2134             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
2135             "\n"
2136          );
2137
2138       case 900401: // dist-upgrade
2139          c2out << _(
2140             "Usage: dist-upgrade [options]\n"
2141             "\n"
2142             "Perform a global distribution upgrade.\n"
2143             "\n"
2144             "Options:\n"
2145             "  -h  This help text.\n"
2146             "  -y  Assume Yes to all queries and do not prompt\n"
2147             "  -f  Attempt to continue if the integrity check fails\n"
2148             "  -m  Attempt to continue if archives are unlocatable\n"
2149             "  -D  When removing packages, remove dependencies as possible\n"
2150             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
2151             "\n"
2152          );
2153
2154       case 209563: // showpkg
2155          c2out << _(
2156             "Usage: showpkg [options] pkg1 [pkg2 ...]\n"
2157             "\n"
2158             "Show some general information for the given packages.\n"
2159             "\n"
2160             "Options:\n"
2161             "  -h  This help text.\n"
2162             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
2163             "\n"
2164          );
2165          break;
2166
2167       case 17649: // show
2168          c2out << _(
2169             "Usage: show [options] pkg1 [pkg2 ...]\n"
2170             "\n"
2171             "Show a readable record for the given packages.\n"
2172             "\n"
2173             "Options:\n"
2174             "  -h  This help text.\n"
2175             "  -a  Show information about all versions.\n"
2176             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
2177             "\n"
2178          );
2179          break;
2180
2181       case 964115: // depends
2182          c2out << _(
2183             "Usage: depends [options] pkg1 [pkg2 ...]\n"
2184             "\n"
2185             "Show dependency relations for the given packages.\n"
2186             "\n"
2187             "Options:\n"
2188             "  -h  This help text.\n"
2189             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
2190             "\n"
2191          );
2192          break;
2193
2194       case 151615: // whatdepends
2195          c2out << _(
2196             "Usage: whatdepends [options] pkg1 [pkg2 ...]\n"
2197             "\n"
2198             "Show dependency relations on the given packages.\n"
2199             "\n"
2200             "Options:\n"
2201             "  -h  This help text.\n"
2202             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
2203             "\n"
2204          );
2205          break;
2206
2207       case 90221: // unmet
2208          c2out << _(
2209             "Usage: unmet [options]\n"
2210             "\n"
2211             "Show unsolvable relations in the cache.\n"
2212             "\n"
2213             "Options:\n"
2214             "  -h  This help text.\n"
2215             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
2216             "\n"
2217          );
2218          break;
2219
2220       case 438074: // search
2221          c2out << _(
2222             "Usage: search [options] <regex>\n"
2223             "\n"
2224             "Search for the given regular expression in package names and\n"
2225             "descriptions.\n"
2226             "\n"
2227             "Options:\n"
2228             "  -h  This help text.\n"
2229             "  -n  Search only in package names.\n"
2230             "  -f  Show full records for found packages.\n"
2231             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
2232             "\n"
2233          );
2234          break;
2235
2236       case 16816: // list
2237       case 655: // ls
2238          c2out << _(
2239             "Usage: list/ls [options] [pattern ...]\n"
2240             "\n"
2241             "List packages matching the given patterns, or all packages if\n"
2242             "no pattern is given. Wildcards are accepted.\n"
2243             "\n"
2244             "Options:\n"
2245             "  -h  This help text.\n"
2246             "  -i  Show only installed packages.\n"
2247             "  -u  Show only installed packages that are upgradable.\n"
2248             "  -v  Show installed and candidate versions.\n"
2249             "  -s  Show summaries.\n"
2250             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
2251             "\n"
2252          );
2253          break;
2254
2255       case 395741: // commit
2256          c2out << _(
2257             "Usage: commit [options]\n"
2258             "\n"
2259             "Apply the changes in the system.\n"
2260             "\n"
2261             "Options:\n"
2262             "  -h  This help text.\n"
2263             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
2264             "\n"
2265          );
2266          break;
2267
2268       case 438801: // script
2269          c2out << _(
2270             "Usage: script [options] script1 [script2]\n"
2271             "\n"
2272             "Run the given scripts.\n"
2273             "\n"
2274             "Options:\n"
2275             "  -h  This help text.\n"
2276             "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
2277             "\n"
2278          );
2279          break;
2280       default:
2281          _error->Error(_("No help for that"));
2282    }
2283 }
2284                                                                         /*}}}*/
2285
2286 bool DoQuit(CommandLine &CmdL)
2287 {
2288    _config->Set("quit", "true");
2289    return true;
2290 }
2291
2292 bool DoCommit(CommandLine &CmdL)
2293 {
2294    if (CheckHelp(CmdL,0) == true)
2295       return true;
2296
2297    if (GCache->CanCommit() == false) {
2298       _error->Error(_("You have no permissions for that"));
2299       return false;
2300    }
2301    return InstallPackages(*GCache,false);
2302 }
2303
2304 bool DoStatus(CommandLine &CmdL)
2305 {
2306    if (CheckHelp(CmdL,0) == true)
2307       return true;
2308
2309    ShowChanges(*GCache);
2310    return true;
2311 }
2312
2313 // GetInitialize - Initialize things for apt-get                        /*{{{*/
2314 // ---------------------------------------------------------------------
2315 /* */
2316 void GetInitialize()
2317 {
2318    _config->Set("quiet",0);
2319    _config->Set("help",false);
2320    _config->Set("APT::Get::Download-Only",false);
2321    _config->Set("APT::Get::Simulate",false);
2322    _config->Set("APT::Get::Assume-Yes",false);
2323    _config->Set("APT::Get::Fix-Broken",false);
2324    _config->Set("APT::Get::Force-Yes",false);
2325    _config->Set("APT::Get::APT::Get::No-List-Cleanup",true);
2326 }
2327                                                                         /*}}}*/
2328 // ReadLine* - readline library stuff                                   /*{{{*/
2329 // ---------------------------------------------------------------------
2330 /* */
2331 char *ReadLineCompCommands(const char *Text, int State)
2332 {
2333    static const char *Commands[] =  {"update", "upgrade", "install", "remove",
2334          "keep", "dist-upgrade", "dselect-upgrade", "build-dep", "clean",
2335          "autoclean", "check", "help", "commit", "exit", "quit", "status",
2336          "showpkg", "unmet", "search", "depends", "whatdepends", "rdepends",
2337          "show", "script", "searchfile", "files", "changelog", "list", "ls", 0};
2338    static int Last;
2339    static size_t Len;
2340    if (State == 0) {
2341       Last = 0;
2342       Len = strlen(Text);
2343    }
2344    const char *Cmd;
2345    while ((Cmd = Commands[Last++])) {
2346       if (strncmp(Cmd, Text, Len) == 0)
2347          return strdup(Cmd);
2348    }
2349    return NULL;
2350 }
2351
2352 static int CompPackagesMode;
2353
2354 char *ReadLineCompPackages(const char *Text, int State)
2355 {
2356    CacheFile &Cache = *GCache;
2357    static pkgCache::PkgIterator Pkg;
2358    static size_t Len;
2359    if (State == 0) {
2360       Pkg = Cache->PkgBegin();
2361       Len = strlen(Text);
2362    } else {
2363       Pkg++;
2364    }
2365    const char *Name;
2366    for (; Pkg.end() == false; Pkg++) {
2367       Name = Pkg.Name();
2368       if (Pkg->VersionList == 0) {
2369          continue;
2370       } else if (CompPackagesMode == MODE_REMOVE) {
2371          if (Pkg->CurrentVer == 0)
2372             continue;
2373       } else if (CompPackagesMode == MODE_KEEP) {
2374          if (Cache[Pkg].Delete() == false && Cache[Pkg].Install() == false)
2375             continue;
2376       }
2377       if (strncmp(Name, Text, Len) == 0)
2378          return strdup(Name);
2379    }
2380    return NULL;
2381 }
2382
2383 static const char *CompVersionName;
2384
2385 char *ReadLineCompVersion(const char *Text, int State)
2386 {
2387    CacheFile &Cache = *GCache;
2388    static pkgCache::VerIterator Ver;
2389    static int Len;
2390    if (State == 0) {
2391       pkgCache::PkgIterator Pkg = Cache->FindPkg(CompVersionName);
2392       if (Pkg.end() == true)
2393          return NULL;
2394       Ver = Pkg.VersionList();
2395       Len = strlen(Text);
2396    } else {
2397       Ver++;
2398    }
2399    const char *Version;
2400    for (; Ver.end() == false; Ver++) {
2401       Version = Ver.VerStr();
2402       if (strncmp(Version, Text, Len) == 0)
2403          return strdup(Version);
2404    }
2405    return NULL;
2406 }
2407
2408
2409 unsigned long ReadLineHashCmd(const char *Cmd, const char *CmdEnd)
2410 {
2411    unsigned long Hash = 0;
2412    for (; Cmd != CmdEnd; Cmd++)
2413       Hash = 5*Hash + *Cmd;
2414    return Hash;
2415 }
2416    
2417 char **ReadLineCompletion(const char *Text, int Start, int End)
2418 {
2419    char **Matches = (char **)NULL;
2420    char *Cmd = rl_line_buffer;
2421    int Pos = 0;
2422    for (; *Cmd != 0 && isspace(*Cmd); Pos++, Cmd++);
2423    rl_attempted_completion_over = 1;
2424    if (Start == Pos)
2425       Matches = rl_completion_matches(Text, ReadLineCompCommands);
2426    else {
2427       char *CmdEnd = Cmd;
2428       while (!isspace(*CmdEnd)) CmdEnd++;
2429       CompPackagesMode = -1;
2430       switch (ReadLineHashCmd(Cmd,CmdEnd)) {
2431          case 2073823: // install
2432             if (*(rl_line_buffer+Start-1) == '=') {
2433                const char *NameEnd = rl_line_buffer+Start-1;
2434                const char *NameStart = NameEnd-1;
2435                while (!isspace(*NameStart)) NameStart--;
2436                if (++NameStart == NameEnd)
2437                   return NULL;
2438                string PkgName(NameStart, NameEnd-NameStart);
2439                CompVersionName = PkgName.c_str();
2440                Matches = rl_completion_matches(Text, ReadLineCompVersion);
2441             } else {
2442                Matches = rl_completion_matches(Text, ReadLineCompPackages);
2443             }
2444             break;
2445
2446          case 436466: // remove
2447             CompPackagesMode = MODE_REMOVE;
2448          case 16517: // keep
2449             if (CompPackagesMode == -1)
2450                CompPackagesMode = MODE_KEEP;
2451          case 2209563: // showpkg
2452          case 17649: // show
2453          case 16816: // list
2454          case 655: // ls
2455          case 1964115: // depends
2456          case 1414151615: // whatdepends
2457          case 10870365: // rdepends
2458             Matches = rl_completion_matches(Text, ReadLineCompPackages);
2459             break;
2460
2461          default:
2462             break;
2463       }
2464    }
2465    return Matches;
2466 }
2467
2468 string ReadLineHistoryFile()
2469 {
2470    string Path;
2471    const char *Dir = getenv("HOME");
2472    if (Dir != NULL) {
2473       Path = Dir;
2474       Path += "/.apt_history";
2475    }
2476    return Path;
2477 }
2478
2479 void ReadLineInit()
2480 {
2481    rl_readline_name = "APTShell";
2482    rl_attempted_completion_function = ReadLineCompletion;
2483    string History = ReadLineHistoryFile();
2484    if (History.empty() == false)
2485       read_history_range(History.c_str(), 0, -1);
2486 }
2487
2488 void ReadLineFinish()
2489 {
2490    string History = ReadLineHistoryFile();
2491    if (History.empty() == false)
2492       write_history(History.c_str());
2493 }
2494                                                                         /*}}}*/
2495
2496 CommandLine::Args *CommandArgs(const char *Name)
2497 {
2498    static CommandLine::Args ChangeCacheArgs[] = {
2499       {'h',"help","help",0},
2500       {'q',"quiet","quiet",CommandLine::IntLevel},
2501       {'q',"silent","quiet",CommandLine::IntLevel},
2502       {'y',"yes","APT::Get::Assume-Yes",0},
2503       {'y',"assume-yes","APT::Get::Assume-Yes",0},      
2504       {'s',"simulate","APT::Get::Simulate",0},
2505       {'s',"just-print","APT::Get::Simulate",0},
2506       {'s',"recon","APT::Get::Simulate",0},
2507       {'s',"dry-run","APT::Get::Simulate",0},
2508       {'s',"no-act","APT::Get::Simulate",0},
2509       {'f',"fix-broken","APT::Get::Fix-Broken",0},
2510       {'D',"remove-deps","APT::Remove-Depends",0}, // CNC:2002-08-01
2511       {'V',"verbose-versions","APT::Get::Show-Versions",0},
2512       {'t',"target-release","APT::Default-Release",CommandLine::HasArg},
2513       {'t',"default-release","APT::Default-Release",CommandLine::HasArg},
2514       {0,"reinstall","APT::Get::ReInstall",0},
2515       {0,"upgrade","APT::Get::upgrade",0},
2516       {0,"force-yes","APT::Get::Force-Yes",0},
2517       {0,"ignore-hold","APT::Ignore-Hold",0},      
2518       {0,"purge","APT::Get::Purge",0},
2519       {0,"remove","APT::Get::Remove",0},
2520       {0,"arch-only","APT::Get::Arch-Only",0},
2521       {'c',"config-file",0,CommandLine::ConfigFile},
2522       {'o',"option",0,CommandLine::ArbItem},
2523       {0,0,0,0}};
2524
2525    static CommandLine::Args CommitArgs[] = {
2526       {'h',"help","help",0},
2527       {'q',"quiet","quiet",CommandLine::IntLevel},
2528       {'q',"silent","quiet",CommandLine::IntLevel},
2529       {'y',"yes","APT::Get::Assume-Yes",0},
2530       {'y',"assume-yes","APT::Get::Assume-Yes",0},      
2531       {'d',"download-only","APT::Get::Download-Only",0},
2532       {'s',"simulate","APT::Get::Simulate",0},
2533       {'s',"just-print","APT::Get::Simulate",0},
2534       {'s',"recon","APT::Get::Simulate",0},
2535       {'s',"dry-run","APT::Get::Simulate",0},
2536       {'s',"no-act","APT::Get::Simulate",0},
2537       {'m',"ignore-missing","APT::Get::Fix-Missing",0},
2538       {0,"trivial-only","APT::Get::Trivial-Only",0},
2539       {0,"print-uris","APT::Get::Print-URIs",0},
2540       {0,"force-yes","APT::Get::Force-Yes",0},
2541       {0,"download","APT::Get::Download",0},
2542       {0,"fix-missing","APT::Get::Fix-Missing",0},
2543       {'c',"config-file",0,CommandLine::ConfigFile},
2544       {'o',"option",0,CommandLine::ArbItem},
2545       {0,0,0,0}};
2546
2547    static CommandLine::Args ShowArgs[] = {
2548       {'h',"help","help",0},
2549       {'a',"all-versions","APT::Cache::AllVersions",0},
2550       {'n',"names-only","APT::Cache::NamesOnly",0},
2551       {'f',"show-full","APT::Cache::ShowFull",0},
2552       {'c',"config-file",0,CommandLine::ConfigFile},
2553       {'o',"option",0,CommandLine::ArbItem},
2554       {0,0,0,0}};
2555
2556    static CommandLine::Args SearchArgs[] = {
2557       {'h',"help","help",0},
2558       {'n',"names-only","APT::Cache::NamesOnly",0},
2559       {'f',"show-full","APT::Cache::ShowFull",0},
2560       {'c',"config-file",0,CommandLine::ConfigFile},
2561       {'o',"option",0,CommandLine::ArbItem},
2562       {0,0,0,0}};
2563
2564    static CommandLine::Args ListArgs[] = {
2565       {'h',"help","help",0},
2566       {'u',"upgradable","APT::Cache::ShowUpgradable",0},
2567       {'i',"installed","APT::Cache::ShowInstalled",0},
2568       {'v',"version","APT::Cache::ShowVersion",0},
2569       {'s',"summary","APT::Cache::ShowSummary",0},
2570       {'n',"installed","APT::Cache::Installed",0},
2571       {'c',"config-file",0,CommandLine::ConfigFile},
2572       {'o',"option",0,CommandLine::ArbItem},
2573       {0,0,0,0}};
2574
2575    static CommandLine::Args NoArgs[] = {
2576       {'h',"help","help",0},
2577       {'v',"version","version",0},
2578       {'c',"config-file",0,CommandLine::ConfigFile},
2579       {'o',"option",0,CommandLine::ArbItem},
2580       {0,0,0,0}};
2581
2582
2583    unsigned long Hash = 0;
2584    for (const char *p=Name; *p; p++)
2585       Hash = 5*Hash + *p;
2586    switch (Hash%1000000) {
2587       case 73823: // install
2588       case 436466: // remove
2589       case 16517: // keep
2590       case 259776: // upgrade
2591       case 900401: // dist-upgrade
2592          return ChangeCacheArgs;
2593
2594       case 395741: // commit
2595          return CommitArgs;
2596
2597       case 209563: // showpkg
2598       case 17649: // show
2599          return ShowArgs;
2600
2601       case 438074: // search
2602          return SearchArgs;
2603
2604       case 16816: // list
2605       case 655: // ls
2606          return ListArgs;
2607
2608       default:
2609          return NoArgs;
2610    }
2611 }
2612                                                                         /*}}}*/
2613 int main(int argc,const char *argv[])
2614 {
2615    CommandLine::Dispatch Cmds[] = {{"update",&DoUpdate},
2616                                    {"upgrade",&DoUpgrade},
2617                                    {"install",&DoInstall},
2618                                    {"remove",&DoInstall},
2619                                    {"keep",&DoInstall},
2620                                    {"dist-upgrade",&DoDistUpgrade},
2621                                    {"build-dep",&DoBuildDep},
2622                                    {"clean",&DoClean},
2623                                    {"autoclean",&DoAutoClean},
2624                                    {"check",&DoCheck},
2625                                    {"help",&ShowHelp},
2626                                    {"commit",&DoCommit},
2627                                    {"quit",&DoQuit},
2628                                    {"exit",&DoQuit},
2629                                    {"status",&DoStatus},
2630                                    {"script",&DoScript},
2631                                    // apt-cache
2632                                    {"showpkg",&DumpPackage},
2633                                    {"unmet",&UnMet},
2634                                    {"search",&Search},
2635                                    {"search",&SearchFile},
2636                                    {"files",&FileList},
2637                                    {"changelog",&ChangeLog},
2638                                    {"list",&DoList},
2639                                    {"ls",&DoList},
2640                                    {"depends",&Depends},
2641                                    {"whatdepends",&WhatDepends},
2642                                    {"whatprovides",&WhatProvides},
2643                                    {"rdepends",&RDepends},
2644                                    {"show",&ShowPackage},
2645                                    {0,0}};
2646
2647    // Set up gettext support
2648    setlocale(LC_ALL,"");
2649    textdomain(PACKAGE);
2650
2651    // Parse the command line and initialize the package library
2652    CommandLine CmdL(CommandArgs(""),_config);
2653    if (pkgInitConfig(*_config) == false ||
2654        CmdL.Parse(argc,argv) == false ||
2655        pkgInitSystem(*_config,_system) == false)
2656    {
2657       if (_config->FindB("version") == true)
2658          ShowHelp(CmdL);
2659          
2660       _error->DumpErrors();
2661       return 100;
2662    }
2663
2664    // Deal with stdout not being a tty
2665    if (ttyname(STDOUT_FILENO) == 0 && _config->FindI("quiet",0) < 1)
2666       _config->Set("quiet","1");
2667
2668    // Setup the output streams
2669    c0out.rdbuf(cout.rdbuf());
2670    c1out.rdbuf(cout.rdbuf());
2671    c2out.rdbuf(cout.rdbuf());
2672    if (_config->FindI("quiet",0) > 0)
2673       c0out.rdbuf(devnull.rdbuf());
2674    if (_config->FindI("quiet",0) > 1)
2675       c1out.rdbuf(devnull.rdbuf());
2676
2677    // Setup the signals
2678    signal(SIGPIPE,SIG_IGN);
2679    signal(SIGINT,SIG_IGN);
2680    signal(SIGWINCH,SigWinch);
2681    SigWinch(0);
2682
2683    // Prepare the cache
2684    GCache = new CacheFile();
2685    GCache->Open();
2686
2687    // CNC:2004-02-18
2688    if (_error->empty() == false)
2689    {
2690       bool Errors = _error->PendingError();
2691       _error->DumpErrors();
2692       return Errors == true?100:0;
2693    }
2694
2695    if (GCache->CheckDeps(true) == false) {
2696       c1out << _("There are broken packages. ")
2697             << _("Run `check' to see them.") << endl;
2698       c1out << _("You can try to fix them automatically with `install --fix-broken'.") << endl;
2699    }
2700
2701    // Make a copy of the configuration. Each command will modify its
2702    // own copy of the whole configuration.
2703    Configuration GlobalConfig(*_config);
2704
2705    ReadLineInit();
2706    c1out << _("Welcome to the APT shell. Type \"help\" for more information.") << endl;
2707
2708 // CNC:2003-03-19
2709 #ifdef APT_WITH_LUA
2710    _lua->SetDepCache(*GCache);
2711    _lua->RunScripts("Scripts::AptShell::Init");
2712    _lua->ResetCaches();
2713    bool HasCmdScripts = (_lua->HasScripts("Scripts::AptGet::Command") ||
2714                          _lua->HasScripts("Scripts::AptCache::Command"));
2715 #endif
2716
2717    size_t largc;
2718    const char *largv[1024];
2719    char *line, *p, *q;
2720    largv[0] = "";
2721    while (_config->FindB("quit") == false)
2722    {
2723       if (_error->empty() == false)
2724       {
2725          _error->DumpErrors();
2726          continue;
2727       }
2728       
2729       line = readline(_config->Find("APT::Shell::Prompt", "apt> ").c_str());
2730       if (!line) {
2731         c1out << endl;
2732         // exit from shell by EOF
2733          _config->Set("quit", "true");
2734          continue;
2735       }
2736
2737       if (!*line) {
2738          free(line);
2739          continue;
2740       }
2741
2742       add_history(line);
2743
2744       largc = 1; // CommandLine.Parse() ignores the first option.
2745
2746       // Split the line into arguments, handling quotes.
2747       p = q = line;
2748       // *p = parsed contents, assigned from *q
2749       // *q = buffer checker, copying valid stuff to *p
2750       while (*q != 0)
2751       {
2752          if (largc > sizeof(largv)/sizeof(*largv))
2753          {
2754             _error->Error(_("Exceeded maximum number of command arguments"));
2755             break;
2756          }
2757          while (isspace(*q)) q++;
2758          if (*q == 0)
2759             break;
2760          largv[largc++] = p = q;
2761          while (*q != 0 && !isspace(*q)) {
2762             if (*q == '"' || *q == '\'') {
2763                char quote = *q++;
2764                while (*q != 0) {
2765                   if (*q == quote) {
2766                      q++;
2767                      break;
2768                   } else if (*q == '\\') {
2769                      switch (*(++q)) {
2770                         case '\0':
2771                            break;
2772                         case '\\':
2773                            *p++ = '\\';
2774                            break;
2775                         default:
2776                            *p++ = *q;
2777                            break;
2778                      }
2779                      q++;
2780                   } else {
2781                      *p++ = *q++;
2782                   }
2783                }
2784             } else {
2785                *p++ = *q++;
2786             }
2787          }
2788          if (*q != 0)
2789             q++;
2790          *p++ = 0;
2791       }
2792       if (largc == 1 || _error->empty() == false)
2793          continue;
2794       largv[largc] = 0;
2795       
2796       // Make our own copy of the configuration.
2797       delete _config;
2798       _config = new Configuration(GlobalConfig);
2799
2800       // Prepare the command line
2801       CommandLine CmdL(CommandArgs(largv[1]),_config);
2802       CmdL.Parse(largc,largv);
2803
2804 // CNC:2003-03-19
2805 #ifdef APT_WITH_LUA
2806       if (HasCmdScripts == true && _error->PendingError() == false) {
2807          _lua->SetDepCache(*GCache);
2808          _lua->SetGlobal("command_args", CmdL.FileList);
2809          _lua->SetGlobal("command_consume", 0.0);
2810          _lua->RunScripts("Scripts::AptGet::Command", true);
2811          _lua->RunScripts("Scripts::AptCache::Command", true);
2812          double Consume = _lua->GetGlobalNum("command_consume");
2813          _lua->ResetGlobals();
2814          _lua->ResetCaches();
2815          if (Consume == 1) {
2816             free(line);
2817             continue;
2818          }
2819       }
2820 #endif
2821
2822       if (_error->PendingError() == false)
2823          CmdL.DispatchArg(Cmds);
2824       
2825       free(line);
2826    }
2827
2828    ReadLineFinish();
2829
2830    delete GCache;
2831
2832    // Print any errors or warnings found during parsing
2833    if (_error->empty() == false)
2834    {
2835       bool Errors = _error->PendingError();
2836       _error->DumpErrors();
2837       return Errors == true?100:0;
2838    }
2839    
2840    return 0;   
2841 }
2842
2843 // vim:sts=3:sw=3