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