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