- initial import of revision 374 from cnc
[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       unsigned 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 (unsigned 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 (Cache[Pkg].CandidateVer == 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 (int 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 (int 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 (int 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 };
1619
1620 bool DoUpdate(CommandLine &CmdL)
1621 {
1622 // CNC:2003-03-27
1623 #if 0
1624    if (CmdL.FileSize() != 1)
1625       return _error->Error(_("The update command takes no arguments"));
1626
1627    // Get the source list
1628    pkgSourceList List;
1629    if (List.ReadMainList() == false)
1630       return false;
1631 #else
1632    bool Partial = false;
1633    pkgSourceList List;
1634
1635    if (CmdL.FileSize() != 1)
1636    {
1637       List.ReadVendors();
1638       for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1639       {
1640          string Repo = _config->FindDir("Dir::Etc::sourceparts") + *I;
1641          if (FileExists(Repo) == false)
1642             Repo += ".list";
1643          if (FileExists(Repo) == true)
1644          {
1645             if (List.ReadAppend(Repo) == true)
1646                Partial = true;
1647             else
1648                return _error->Error(_("Sources list %s could not be read"),Repo.c_str());
1649          }
1650          else
1651             return _error->Error(_("Sources list %s doesn't exist"),Repo.c_str());
1652       }
1653    }
1654    else if (List.ReadMainList() == false)
1655       return false;
1656 #endif
1657
1658    // Lock the list directory
1659    FileFd Lock;
1660    if (_config->FindB("Debug::NoLocking",false) == false)
1661    {
1662       Lock.Fd(GetLock(_config->FindDir("Dir::State::Lists") + "lock"));
1663       if (_error->PendingError() == true)
1664          return _error->Error(_("Unable to lock the list directory"));
1665    }
1666    
1667 // CNC:2003-03-19
1668 #ifdef WITH_LUA
1669    if (_lua->HasScripts("Scripts::AptGet::Update::Pre")) {
1670       _lua->RunScripts("Scripts::AptGet::Update::Pre");
1671       LuaCacheControl *LuaCache = _lua->GetCacheControl();
1672       LuaCache->Close();
1673    }
1674 #endif
1675    
1676    // Create the download object
1677    AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
1678    pkgAcquire Fetcher(&Stat);
1679
1680    // CNC:2002-07-03
1681    bool Failed = false;
1682    // Populate it with release file URIs
1683    if (List.GetReleases(&Fetcher) == false)
1684       return false;
1685    if (_config->FindB("APT::Get::Print-URIs") == false)
1686    {
1687       Fetcher.Run();
1688       for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
1689       {
1690          if ((*I)->Status == pkgAcquire::Item::StatDone)
1691             continue;
1692          (*I)->Finished();
1693          Failed = true;
1694       }
1695       if (Failed == true)
1696          _error->Warning(_("Release files for some repositories could not be retrieved or authenticated. Such repositories are being ignored."));
1697    }
1698    
1699    // Populate it with the source selection
1700    if (List.GetIndexes(&Fetcher) == false)
1701          return false;
1702    
1703    // Just print out the uris an exit if the --print-uris flag was used
1704    if (_config->FindB("APT::Get::Print-URIs") == true)
1705    {
1706       pkgAcquire::UriIterator I = Fetcher.UriBegin();
1707       for (; I != Fetcher.UriEnd(); I++)
1708          cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' << 
1709                I->Owner->FileSize << ' ' << I->Owner->MD5Sum() << endl;
1710       return true;
1711    }
1712    
1713    // Run it
1714    if (Fetcher.Run() == pkgAcquire::Failed)
1715       return false;
1716
1717    for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
1718    {
1719       if ((*I)->Status == pkgAcquire::Item::StatDone)
1720          continue;
1721
1722       (*I)->Finished();
1723       
1724       fprintf(stderr,_("Failed to fetch %s  %s\n"),(*I)->DescURI().c_str(),
1725               (*I)->ErrorText.c_str());
1726       Failed = true;
1727    }
1728    
1729    // Clean out any old list files if not in partial update
1730    if (Partial == false && _config->FindB("APT::Get::List-Cleanup",true) == true)
1731    {
1732       if (Fetcher.Clean(_config->FindDir("Dir::State::lists")) == false ||
1733           Fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/") == false)
1734          return false;
1735    }
1736    
1737 // CNC:2003-03-19
1738 #if 0
1739    // Prepare the cache.   
1740    CacheFile Cache;
1741    if (Cache.BuildCaches() == false)
1742       return false;
1743 #else
1744    // Prepare the cache.   
1745    CacheFile Cache;
1746    if (Cache.Open() == false)
1747       return false;
1748
1749 #ifdef WITH_LUA
1750    _lua->RunScripts("Scripts::AptGet::Update::Post");
1751 #endif
1752 #endif
1753
1754    // CNC:2004-04-19
1755    if (Failed == false && _config->FindB("APT::Get::Archive-Cleanup",true) == true)
1756    {
1757       UpdateLogCleaner Cleaner;
1758       Cleaner.Go(_config->FindDir("Dir::Cache::archives"), *Cache);
1759       Cleaner.Go(_config->FindDir("Dir::Cache::archives") + "partial/",
1760                  *Cache);
1761    }
1762    
1763    if (Failed == true)
1764       return _error->Error(_("Some index files failed to download, they have been ignored, or old ones used instead."));
1765    
1766    return true;
1767 }
1768                                                                         /*}}}*/
1769 // DoUpgrade - Upgrade all packages                                     /*{{{*/
1770 // ---------------------------------------------------------------------
1771 /* Upgrade all packages without installing new packages or erasing old
1772    packages */
1773 bool DoUpgrade(CommandLine &CmdL)
1774 {
1775    CacheFile Cache;
1776    if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false)
1777       return false;
1778
1779    // Do the upgrade
1780    if (pkgAllUpgrade(Cache) == false)
1781    {
1782       ShowBroken(c1out,Cache,false);
1783       return _error->Error(_("Internal Error, AllUpgrade broke stuff"));
1784    }
1785
1786 // CNC:2003-03-19
1787 #ifdef WITH_LUA
1788    _lua->SetDepCache(Cache);
1789    _lua->RunScripts("Scripts::AptGet::Upgrade");
1790    _lua->ResetCaches();
1791 #endif
1792
1793    // CNC:2003-03-06
1794    if (CheckOnly(Cache) == true)
1795       return true;
1796    
1797    return InstallPackages(Cache,true);
1798 }
1799                                                                         /*}}}*/
1800 // DoInstall - Install packages from the command line                   /*{{{*/
1801 // ---------------------------------------------------------------------
1802 /* Install named packages */
1803 bool DoInstall(CommandLine &CmdL)
1804 {
1805    CacheFile Cache;
1806    if (Cache.OpenForInstall() == false || 
1807        Cache.CheckDeps(CmdL.FileSize() != 1) == false)
1808       return false;
1809    
1810    // Enter the special broken fixing mode if the user specified arguments
1811    bool BrokenFix = false;
1812    if (Cache->BrokenCount() != 0)
1813       BrokenFix = true;
1814    
1815    unsigned int ExpectedInst = 0;
1816    unsigned int Packages = 0;
1817    pkgProblemResolver Fix(Cache);
1818    
1819    bool DefRemove = false;
1820    if (strcasecmp(CmdL.FileList[0],"remove") == 0)
1821       DefRemove = true;
1822    // CNC:2004-03-22
1823    else if (strcasecmp(CmdL.FileList[0],"reinstall") == 0)
1824       _config->Set("APT::Get::ReInstall", true);
1825
1826    for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1827    {
1828       // Duplicate the string
1829       unsigned int Length = strlen(*I);
1830       char S[300];
1831       if (Length >= sizeof(S))
1832          continue;
1833       strcpy(S,*I);
1834
1835       // CNC:2003-03-15
1836       char OrigS[300];
1837       strcpy(OrigS,S);
1838       
1839       // See if we are removing and special indicators..
1840       bool Remove = DefRemove;
1841       char *VerTag = 0;
1842       bool VerIsRel = false;
1843       // CNC:2003-11-05
1844       int VerOp = 0;
1845       while (Cache->FindPkg(S).end() == true)
1846       {
1847          // Handle an optional end tag indicating what to do
1848          if (Length >= 1 && S[Length - 1] == '-')
1849          {
1850             Remove = true;
1851             S[--Length] = 0;
1852             continue;
1853          }
1854          
1855          if (Length >= 1 && S[Length - 1] == '+')
1856          {
1857             Remove = false;
1858             S[--Length] = 0;
1859             continue;
1860          }
1861          
1862          // CNC:2003-11-05
1863          char *sep = strpbrk(S,"=><");
1864          if (sep)
1865          {
1866             char *p;
1867             int eq = 0, gt = 0, lt = 0;
1868
1869             VerIsRel = false;
1870             for (p = sep; *p && strchr("=><",*p); ++p)
1871                switch (*p)
1872                {
1873                   case '=': eq = 1; break;
1874                   case '>': gt = 1; break;
1875                   case '<': lt = 1; break;
1876                }
1877             if (eq)
1878             {
1879                if (lt && gt)
1880                   return _error->Error(_("Couldn't parse name '%s'"),S);
1881                else if (lt)
1882                   VerOp = pkgCache::Dep::LessEq;
1883                else if (gt)
1884                   VerOp = pkgCache::Dep::GreaterEq;
1885                else
1886                   VerOp = pkgCache::Dep::Equals;
1887             }
1888             else
1889             {
1890                if (lt && gt)
1891                   VerOp = pkgCache::Dep::NotEquals;
1892                else if (lt)
1893                   VerOp = pkgCache::Dep::Less;
1894                else if (gt)
1895                   VerOp = pkgCache::Dep::Greater;
1896                else
1897                   return _error->Error(_("Couldn't parse name '%s'"),S);
1898             }
1899             *sep = '\0';
1900             VerTag = p;
1901          }
1902          
1903          // CNC:2003-11-21 - Try to handle unknown file items.
1904          if (S[0] == '/')
1905          {
1906             pkgRecords Recs(Cache);
1907             if (_error->PendingError() == true)
1908                return false;
1909             pkgCache::PkgIterator Pkg = (*Cache).PkgBegin();
1910             for (; Pkg.end() == false; Pkg++)
1911             {
1912                // Should we try on all versions?
1913                pkgCache::VerIterator Ver = (*Cache)[Pkg].CandidateVerIter(*Cache);
1914                if (Ver.end() == false)
1915                {
1916                   pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList());
1917                   if (Parse.HasFile(S)) {
1918                      strcpy(S, Pkg.Name());
1919                      ioprintf(c1out,_("Selecting %s for '%s'\n"),
1920                               Pkg.Name(),OrigS);
1921                      // Confirm the translation.
1922                      ExpectedInst += 1000;
1923                      break;
1924                   }
1925                }
1926             }
1927          }
1928
1929          char *Slash = strchr(S,'/');
1930          if (Slash != 0)
1931          {
1932             VerIsRel = true;
1933             *Slash = 0;
1934             VerTag = Slash + 1;
1935          }
1936          
1937          break;
1938       }
1939       
1940       // Locate the package
1941       pkgCache::PkgIterator Pkg = Cache->FindPkg(S);
1942       Packages++;
1943       if (Pkg.end() == true)
1944       {
1945          // Check if the name is a regex
1946          const char *I;
1947          for (I = S; *I != 0; I++)
1948             if (*I == '?' || *I == '*' || *I == '|' ||
1949                 *I == '[' || *I == '^' || *I == '$')
1950                break;
1951
1952          // CNC:2003-05-15
1953          if (*I == 0) {
1954 #ifdef WITH_LUA
1955             vector<string> VS;
1956             _lua->SetDepCache(Cache);
1957             _lua->SetDontFix();
1958             _lua->SetGlobal("argument", OrigS);
1959             _lua->SetGlobal("translated", VS);
1960             _lua->RunScripts("Scripts::AptGet::Install::TranslateArg");
1961             const char *name = _lua->GetGlobalStr("translated");
1962             if (name != NULL) {
1963                VS.push_back(name);
1964             } else {
1965                VS = _lua->GetGlobalStrList("translated");
1966             }
1967             _lua->ResetGlobals();
1968             _lua->ResetCaches();
1969
1970             // Translations must always be confirmed
1971             ExpectedInst += 1000;
1972
1973             // Run over the matches
1974             bool Hit = false;
1975             for (vector<string>::const_iterator I = VS.begin();
1976                  I != VS.end(); I++) {
1977
1978                Pkg = Cache->FindPkg(*I);
1979                if (Pkg.end() == true)
1980                   continue;
1981
1982                ioprintf(c1out,_("Selecting %s for '%s'\n"),
1983                         Pkg.Name(),OrigS);
1984             
1985                Hit |= TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix,
1986                                    ExpectedInst,true);
1987             }
1988          
1989             if (Hit == true)
1990                continue;
1991 #endif
1992             return _error->Error(_("Couldn't find package %s"),S);
1993          }
1994
1995          // Regexs must always be confirmed
1996          ExpectedInst += 1000;
1997          
1998          // Compile the regex pattern
1999          regex_t Pattern;
2000          int Res;
2001          if ((Res = regcomp(&Pattern,S,REG_EXTENDED | REG_ICASE |
2002                      REG_NOSUB)) != 0)
2003          {
2004             char Error[300];        
2005             regerror(Res,&Pattern,Error,sizeof(Error));
2006             return _error->Error(_("Regex compilation error - %s"),Error);
2007          }
2008          
2009          // Run over the matches
2010          bool Hit = false;
2011          for (Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
2012          {
2013             if (regexec(&Pattern,Pkg.Name(),0,0,0) != 0)
2014                continue;
2015             
2016             // CNC:2003-11-23
2017             ioprintf(c1out,_("Selecting %s for '%s'\n"),
2018                      Pkg.Name(),S);
2019             
2020             if (VerTag != 0)
2021                // CNC:2003-11-05
2022                if (TryToChangeVer(Pkg,Cache,VerOp,VerTag,VerIsRel) == false)
2023                   return false;
2024             
2025             Hit |= TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix,
2026                                 ExpectedInst,false);
2027          }
2028          regfree(&Pattern);
2029          
2030          if (Hit == false)
2031             return _error->Error(_("Couldn't find package %s"),S);
2032       }
2033       else
2034       {
2035          if (VerTag != 0)
2036             // CNC:2003-11-05
2037             if (TryToChangeVer(Pkg,Cache,VerOp,VerTag,VerIsRel) == false)
2038                return false;
2039          if (TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix,ExpectedInst) == false)
2040             return false;
2041       }      
2042    }
2043
2044 // CNC:2003-03-19
2045 #ifdef WITH_LUA
2046    _lua->SetDepCache(Cache);
2047    _lua->SetDontFix();
2048    _lua->RunScripts("Scripts::AptGet::Install::PreResolve");
2049    _lua->ResetCaches();
2050 #endif
2051
2052    // CNC:2002-08-01
2053    if (_config->FindB("APT::Remove-Depends",false) == true)
2054       Fix.RemoveDepends();
2055
2056    /* If we are in the Broken fixing mode we do not attempt to fix the
2057       problems. This is if the user invoked install without -f and gave
2058       packages */
2059    if (BrokenFix == true && Cache->BrokenCount() != 0)
2060    {
2061       c1out << _("You might want to run `apt-get --fix-broken install' to correct these:") << endl;
2062       ShowBroken(c1out,Cache,false);
2063
2064       return _error->Error(_("Unmet dependencies. Try 'apt-get --fix-broken install' with no packages (or specify a solution)."));
2065    }
2066    
2067    // Call the scored problem resolver
2068    Fix.InstallProtect();
2069    if (Fix.Resolve(true) == false)
2070       _error->Discard();
2071
2072 // CNC:2003-03-19
2073 #ifdef WITH_LUA
2074    if (Cache->BrokenCount() == 0) {
2075       _lua->SetDepCache(Cache);
2076       _lua->SetProblemResolver(&Fix);
2077       _lua->RunScripts("Scripts::AptGet::Install::PostResolve");
2078       _lua->ResetCaches();
2079    }
2080 #endif
2081
2082    // Now we check the state of the packages,
2083    if (Cache->BrokenCount() != 0)
2084    {
2085       c1out << 
2086        _("Some packages could not be installed. This may mean that you have\n" 
2087          "requested an impossible situation or if you are using the unstable\n" 
2088          "distribution that some required packages have not yet been created\n"
2089          "or been moved out of Incoming.") << endl;
2090       if (Packages == 1)
2091       {
2092          c1out << endl;
2093          c1out << 
2094           _("Since you only requested a single operation it is extremely likely that\n"
2095             "the package is simply not installable and a bug report against\n" 
2096             "that package should be filed.") << endl;
2097       }
2098
2099       c1out << _("The following information may help to resolve the situation:") << endl;
2100       c1out << endl;
2101       ShowBroken(c1out,Cache,false);
2102       return _error->Error(_("Broken packages"));
2103    }   
2104    
2105    /* Print out a list of packages that are going to be installed extra
2106       to what the user asked */
2107    if (Cache->InstCount() != ExpectedInst)
2108    {
2109       string List;
2110       string VersionsList;
2111       for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
2112       {
2113          pkgCache::PkgIterator I(Cache,Cache.List[J]);
2114          if ((*Cache)[I].Install() == false)
2115             continue;
2116
2117          // CNC:2004-06-15
2118          const char **K;
2119          for (K = CmdL.FileList + 1; *K != 0; K++)
2120             if (strcmp(*K,I.Name()) == 0)
2121                 break;
2122          
2123          if (*K == 0) {
2124             List += string(I.Name()) + " ";
2125         VersionsList += string(Cache[I].CandVersion) + "\n";
2126      }
2127       }
2128       
2129       ShowList(c1out,_("The following extra packages will be installed:"),List,VersionsList);
2130    }
2131
2132    /* Print out a list of suggested and recommended packages */
2133    {
2134       string SuggestsList, RecommendsList, List;
2135       string SuggestsVersions, RecommendsVersions;
2136       for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
2137       {
2138          pkgCache::PkgIterator I(Cache,Cache.List[J]);
2139
2140          /* Just look at the ones we want to install */
2141          if ((*Cache)[I].Install() == false)
2142            continue;
2143
2144          for (pkgCache::VerIterator V = I.VersionList(); V.end() == false; V++)
2145            {
2146              for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; D++)
2147                {
2148                  pkgCache::DepIterator Start;
2149                  pkgCache::DepIterator End;
2150                  D.GlobOr(Start,End);
2151
2152                  /* 
2153                   * If this is a virtual package, we need to check the list of
2154                   * packages that provide it and see if any of those are
2155                   * installed
2156                   */
2157                  pkgCache::PrvIterator Prv = Start.TargetPkg().ProvidesList();
2158                  bool providedBySomething = false;
2159                  for (; Prv.end() != true; Prv++)
2160                     if ((*Cache)[Prv.OwnerPkg()].InstVerIter(*Cache).end() == false) {
2161                        providedBySomething = true;
2162                        break;
2163                     }
2164
2165                  if (providedBySomething) continue;
2166             
2167                  do
2168                    {
2169                      if (Start->Type == pkgCache::Dep::Suggests) {
2170
2171                        /* A suggests relations, let's see if we have it 
2172                           installed already */
2173
2174                        string target = string(Start.TargetPkg().Name()) + " ";
2175                        if ((*Start.TargetPkg()).SelectedState == pkgCache::State::Install || Cache[Start.TargetPkg()].Install())
2176                          break;
2177                        /* Does another package suggest it as well?  If so,
2178                           don't print it twice */
2179                        if (int(SuggestsList.find(target)) > -1)
2180                          break; 
2181                        SuggestsList += target;
2182                        SuggestsVersions += string(Cache[Start.TargetPkg()].CandVersion) + "\n";
2183                      }
2184                      
2185                      if (Start->Type == pkgCache::Dep::Recommends) {
2186
2187                        /* A recommends relation, let's see if we have it
2188                           installed already */
2189
2190                        string target = string(Start.TargetPkg().Name()) + " ";
2191                        if ((*Start.TargetPkg()).SelectedState == pkgCache::State::Install || Cache[Start.TargetPkg()].Install())
2192                          break;
2193                        
2194                        /* Does another package recommend it as well?  If so,
2195                           don't print it twice */
2196
2197                        if (int(RecommendsList.find(target)) > -1)
2198                          break;
2199                        RecommendsList += target;
2200                        SuggestsVersions += string(Cache[Start.TargetPkg()].CandVersion) + "\n";
2201                      }
2202               if (Start == End)
2203                 break;
2204               Start++;
2205             } while (1);
2206                }
2207            }
2208       }
2209       ShowList(c1out,_("Suggested packages:"),SuggestsList,SuggestsVersions);
2210       ShowList(c1out,_("Recommended packages:"),RecommendsList,RecommendsVersions);
2211
2212    }
2213
2214    // CNC:2003-03-06
2215    if (CheckOnly(Cache) == true)
2216       return true;
2217
2218    // See if we need to prompt
2219    if (Cache->InstCount() == ExpectedInst && Cache->DelCount() == 0)
2220       return InstallPackages(Cache,false,false);
2221    
2222    return InstallPackages(Cache,false);   
2223 }
2224                                                                         /*}}}*/
2225 // DoDistUpgrade - Automatic smart upgrader                             /*{{{*/
2226 // ---------------------------------------------------------------------
2227 /* Intelligent upgrader that will install and remove packages at will */
2228 bool DoDistUpgrade(CommandLine &CmdL)
2229 {
2230    CacheFile Cache;
2231    if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false)
2232       return false;
2233
2234    c0out << _("Calculating Upgrade... ") << flush;
2235    if (pkgDistUpgrade(*Cache) == false)
2236    {
2237       c0out << _("Failed") << endl;
2238       ShowBroken(c1out,Cache,false);
2239       return false;
2240    }
2241
2242 // CNC:2003-03-19
2243 #ifdef WITH_LUA
2244    _lua->SetDepCache(Cache);
2245    _lua->RunScripts("Scripts::AptGet::DistUpgrade");
2246    _lua->ResetCaches();
2247 #endif
2248    
2249    // CNC:2003-03-06
2250    if (CheckOnly(Cache) == true)
2251       return true;
2252    
2253    c0out << _("Done") << endl;
2254    
2255    return InstallPackages(Cache,true);
2256 }
2257                                                                         /*}}}*/
2258 // DoDSelectUpgrade - Do an upgrade by following dselects selections    /*{{{*/
2259 // ---------------------------------------------------------------------
2260 /* Follows dselect's selections */
2261 bool DoDSelectUpgrade(CommandLine &CmdL)
2262 {
2263    CacheFile Cache;
2264    if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false)
2265       return false;
2266    
2267    // Install everything with the install flag set
2268    pkgCache::PkgIterator I = Cache->PkgBegin();
2269    for (;I.end() != true; I++)
2270    {
2271       /* Install the package only if it is a new install, the autoupgrader
2272          will deal with the rest */
2273       if (I->SelectedState == pkgCache::State::Install)
2274          Cache->MarkInstall(I,false);
2275    }
2276
2277    /* Now install their deps too, if we do this above then order of
2278       the status file is significant for | groups */
2279    for (I = Cache->PkgBegin();I.end() != true; I++)
2280    {
2281       /* Install the package only if it is a new install, the autoupgrader
2282          will deal with the rest */
2283       if (I->SelectedState == pkgCache::State::Install)
2284          Cache->MarkInstall(I,true);
2285    }
2286    
2287    // Apply erasures now, they override everything else.
2288    for (I = Cache->PkgBegin();I.end() != true; I++)
2289    {
2290       // Remove packages 
2291       if (I->SelectedState == pkgCache::State::DeInstall ||
2292           I->SelectedState == pkgCache::State::Purge)
2293          Cache->MarkDelete(I,I->SelectedState == pkgCache::State::Purge);
2294    }
2295
2296    /* Resolve any problems that dselect created, allupgrade cannot handle
2297       such things. We do so quite agressively too.. */
2298    if (Cache->BrokenCount() != 0)
2299    {      
2300       pkgProblemResolver Fix(Cache);
2301
2302       // Hold back held packages.
2303       if (_config->FindB("APT::Ignore-Hold",false) == false)
2304       {
2305          for (pkgCache::PkgIterator I = Cache->PkgBegin(); I.end() == false; I++)
2306          {
2307             if (I->SelectedState == pkgCache::State::Hold)
2308             {
2309                Fix.Protect(I);
2310                Cache->MarkKeep(I);
2311             }
2312          }
2313       }
2314    
2315       if (Fix.Resolve() == false)
2316       {
2317          ShowBroken(c1out,Cache,false);
2318          return _error->Error("Internal Error, problem resolver broke stuff");
2319       }
2320    }
2321
2322    // Now upgrade everything
2323    if (pkgAllUpgrade(Cache) == false)
2324    {
2325       ShowBroken(c1out,Cache,false);
2326       return _error->Error("Internal Error, problem resolver broke stuff");
2327    }
2328
2329    // CNC:2003-03-06
2330    if (CheckOnly(Cache) == true)
2331       return true;
2332    
2333    return InstallPackages(Cache,false);
2334 }
2335                                                                         /*}}}*/
2336 // DoClean - Remove download archives                                   /*{{{*/
2337 // ---------------------------------------------------------------------
2338 /* */
2339 bool DoClean(CommandLine &CmdL)
2340 {
2341    if (_config->FindB("APT::Get::Simulate") == true)
2342    {
2343       cout << "Del " << _config->FindDir("Dir::Cache::archives") << "* " <<
2344          _config->FindDir("Dir::Cache::archives") << "partial/*" << endl;
2345       return true;
2346    }
2347    
2348    // Lock the archive directory
2349    FileFd Lock;
2350    if (_config->FindB("Debug::NoLocking",false) == false)
2351    {
2352       Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
2353       if (_error->PendingError() == true)
2354          return _error->Error(_("Unable to lock the download directory"));
2355    }
2356    
2357    pkgAcquire Fetcher;
2358    Fetcher.Clean(_config->FindDir("Dir::Cache::archives"));
2359    Fetcher.Clean(_config->FindDir("Dir::Cache::archives") + "partial/");
2360    return true;
2361 }
2362                                                                         /*}}}*/
2363 // DoAutoClean - Smartly remove downloaded archives                     /*{{{*/
2364 // ---------------------------------------------------------------------
2365 /* This is similar to clean but it only purges things that cannot be 
2366    downloaded, that is old versions of cached packages. */
2367 class LogCleaner : public pkgArchiveCleaner
2368 {
2369    protected:
2370    virtual void Erase(const char *File,string Pkg,string Ver,struct stat &St) 
2371    {
2372       c1out << "Del " << Pkg << " " << Ver << " [" << SizeToStr(St.st_size) << "B]" << endl;
2373       
2374       if (_config->FindB("APT::Get::Simulate") == false)
2375          unlink(File);      
2376    };
2377 };
2378
2379 bool DoAutoClean(CommandLine &CmdL)
2380 {
2381    // Lock the archive directory
2382    FileFd Lock;
2383    if (_config->FindB("Debug::NoLocking",false) == false)
2384    {
2385       Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
2386       if (_error->PendingError() == true)
2387          return _error->Error(_("Unable to lock the download directory"));
2388    }
2389    
2390    CacheFile Cache;
2391    if (Cache.Open() == false)
2392       return false;
2393    
2394    LogCleaner Cleaner;
2395    
2396    return Cleaner.Go(_config->FindDir("Dir::Cache::archives"),*Cache) &&
2397       Cleaner.Go(_config->FindDir("Dir::Cache::archives") + "partial/",*Cache);
2398 }
2399                                                                         /*}}}*/
2400 // DoCheck - Perform the check operation                                /*{{{*/
2401 // ---------------------------------------------------------------------
2402 /* Opening automatically checks the system, this command is mostly used
2403    for debugging */
2404 bool DoCheck(CommandLine &CmdL)
2405 {
2406    CacheFile Cache;
2407    Cache.Open();
2408    Cache.CheckDeps();
2409    
2410    return true;
2411 }
2412                                                                         /*}}}*/
2413 // DoSource - Fetch a source archive                                    /*{{{*/
2414 // ---------------------------------------------------------------------
2415 /* Fetch souce packages */
2416 struct DscFile
2417 {
2418    string Package;
2419    string Version;
2420    string Dsc;
2421 };
2422
2423 bool DoSource(CommandLine &CmdL)
2424 {
2425    CacheFile Cache;
2426    if (Cache.Open(false) == false)
2427       return false;
2428
2429    if (CmdL.FileSize() <= 1)
2430       return _error->Error(_("Must specify at least one package to fetch source for"));
2431    
2432    // Read the source list
2433    pkgSourceList List;
2434    if (List.ReadMainList() == false)
2435       return _error->Error(_("The list of sources could not be read."));
2436    
2437    // Create the text record parsers
2438    pkgRecords Recs(Cache);
2439    pkgSrcRecords SrcRecs(List);
2440    if (_error->PendingError() == true)
2441       return false;
2442
2443    // Create the download object
2444    AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));   
2445    pkgAcquire Fetcher(&Stat);
2446
2447    DscFile *Dsc = new DscFile[CmdL.FileSize()];
2448    
2449    // Load the requestd sources into the fetcher
2450    unsigned J = 0;
2451    for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++)
2452    {
2453       // CNC:2004-09-23 - Try to handle unknown file items.
2454       unsigned int Length = strlen(*I);
2455       char S[300];
2456       if (Length >= sizeof(S))
2457         continue;
2458       strcpy(S,*I);
2459
2460       if (S[0] == '/')
2461       {
2462          pkgRecords Recs(Cache);
2463          if (_error->PendingError() == true)
2464             return false;
2465          pkgCache::PkgIterator Pkg = (*Cache).PkgBegin();
2466          for (; Pkg.end() == false; Pkg++)
2467          {
2468             // Should we try on all versions?
2469             pkgCache::VerIterator Ver = (*Cache)[Pkg].CandidateVerIter(*Cache);
2470             if (Ver.end() == false)
2471             {
2472                pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList());
2473                if (Parse.HasFile(S)) {
2474                   ioprintf(c1out,_("Selecting %s for '%s'\n"),
2475                            Pkg.Name(),S);
2476                   strcpy(S, Pkg.Name());
2477                   break;
2478                }
2479             }
2480          }
2481       }
2482
2483       string Src;
2484       pkgSrcRecords::Parser *Last = FindSrc(S,Recs,SrcRecs,Src,*Cache);
2485       
2486       if (Last == 0)
2487          return _error->Error(_("Unable to find a source package for %s"),Src.c_str());
2488       
2489       // Back track
2490       vector<pkgSrcRecords::File> Lst;
2491       if (Last->Files(Lst) == false)
2492          return false;
2493
2494       // Load them into the fetcher
2495       for (vector<pkgSrcRecords::File>::const_iterator I = Lst.begin();
2496            I != Lst.end(); I++)
2497       {
2498          // Try to guess what sort of file it is we are getting.
2499          // CNC:2002-07-06
2500          if (I->Type == "dsc" || I->Type == "srpm")
2501          {
2502             Dsc[J].Package = Last->Package();
2503             Dsc[J].Version = Last->Version();
2504             Dsc[J].Dsc = flNotDir(I->Path);
2505          }
2506          
2507          // Diff only mode only fetches .diff files
2508          if (_config->FindB("APT::Get::Diff-Only",false) == true &&
2509              I->Type != "diff")
2510             continue;
2511          
2512          // Tar only mode only fetches .tar files
2513          if (_config->FindB("APT::Get::Tar-Only",false) == true &&
2514              I->Type != "tar")
2515             continue;
2516          
2517          new pkgAcqFile(&Fetcher,Last->Index().ArchiveURI(I->Path),
2518                         I->MD5Hash,I->Size,
2519                         Last->Index().SourceInfo(*Last,*I),Src);
2520       }
2521    }
2522    
2523    // Display statistics
2524    double FetchBytes = Fetcher.FetchNeeded();
2525    double FetchPBytes = Fetcher.PartialPresent();
2526    double DebBytes = Fetcher.TotalNeeded();
2527
2528    // Check for enough free space
2529    struct statvfs Buf;
2530    string OutputDir = ".";
2531    if (statvfs(OutputDir.c_str(),&Buf) != 0)
2532       return _error->Errno("statvfs","Couldn't determine free space in %s",
2533                            OutputDir.c_str());
2534    // CNC:2002-07-12
2535    if (unsigned(Buf.f_bavail) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
2536       return _error->Error(_("You don't have enough free space in %s"),
2537                            OutputDir.c_str());
2538    
2539    // Number of bytes
2540    if (DebBytes != FetchBytes)
2541       ioprintf(c1out,_("Need to get %sB/%sB of source archives.\n"),
2542                SizeToStr(FetchBytes).c_str(),SizeToStr(DebBytes).c_str());
2543    else
2544       ioprintf(c1out,_("Need to get %sB of source archives.\n"),
2545                SizeToStr(DebBytes).c_str());
2546    
2547    if (_config->FindB("APT::Get::Simulate",false) == true)
2548    {
2549       for (unsigned I = 0; I != J; I++)
2550          ioprintf(cout,_("Fetch Source %s\n"),Dsc[I].Package.c_str());
2551       return true;
2552    }
2553    
2554    // Just print out the uris an exit if the --print-uris flag was used
2555    if (_config->FindB("APT::Get::Print-URIs") == true)
2556    {
2557       pkgAcquire::UriIterator I = Fetcher.UriBegin();
2558       for (; I != Fetcher.UriEnd(); I++)
2559          cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' << 
2560                I->Owner->FileSize << ' ' << I->Owner->MD5Sum() << endl;
2561       return true;
2562    }
2563    
2564    // Run it
2565    if (Fetcher.Run() == pkgAcquire::Failed)
2566       return false;
2567
2568    // Print error messages
2569    bool Failed = false;
2570    for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
2571    {
2572       if ((*I)->Status == pkgAcquire::Item::StatDone &&
2573           (*I)->Complete == true)
2574          continue;
2575       
2576       fprintf(stderr,_("Failed to fetch %s  %s\n"),(*I)->DescURI().c_str(),
2577               (*I)->ErrorText.c_str());
2578       Failed = true;
2579    }
2580    if (Failed == true)
2581       return _error->Error(_("Failed to fetch some archives."));
2582    
2583    if (_config->FindB("APT::Get::Download-only",false) == true)
2584    {
2585       c1out << _("Download complete and in download only mode") << endl;
2586       return true;
2587    }
2588
2589    // Unpack the sources
2590    pid_t Process = ExecFork();
2591    
2592    if (Process == 0)
2593    {
2594       for (unsigned I = 0; I != J; I++)
2595       {
2596          string Dir = Dsc[I].Package + '-' + Cache->VS().UpstreamVersion(Dsc[I].Version.c_str());
2597          
2598          // Diff only mode only fetches .diff files
2599          if (_config->FindB("APT::Get::Diff-Only",false) == true ||
2600              _config->FindB("APT::Get::Tar-Only",false) == true ||
2601              Dsc[I].Dsc.empty() == true)
2602             continue;
2603
2604 // CNC:2002-07-06
2605 #if 1
2606          if (_config->FindB("APT::Get::Compile",false) == true)
2607          {
2608             char S[500];
2609             snprintf(S,sizeof(S),"%s %s %s",
2610                      _config->Find("RPM::Source::Build-Command","rpm --rebuild").c_str(),
2611                      _config->Find("RPM::Source::Build-Options","").c_str(),
2612                      Dsc[I].Dsc.c_str());
2613             if (system(S) != 0)
2614             {
2615                fprintf(stderr,_("Build command '%s' failed.\n"),S);
2616                _exit(1);
2617             }       
2618          }
2619          else
2620          {
2621             char S[500];
2622             snprintf(S,sizeof(S),"%s %s",
2623                      _config->Find("RPM::Source::Install-Command","rpm -ivh").c_str(),
2624                      Dsc[I].Dsc.c_str());
2625             if (system(S) != 0)
2626             {
2627                fprintf(stderr,_("Unpack command '%s' failed.\n"),S);
2628                _exit(1);
2629             }       
2630          } 
2631 #else
2632          // See if the package is already unpacked
2633          struct stat Stat;
2634          if (stat(Dir.c_str(),&Stat) == 0 &&
2635              S_ISDIR(Stat.st_mode) != 0)
2636          {
2637             ioprintf(c0out ,_("Skipping unpack of already unpacked source in %s\n"),
2638                               Dir.c_str());
2639          }
2640          else
2641          {
2642             // Call dpkg-source
2643             char S[500];
2644             snprintf(S,sizeof(S),"%s -x %s",
2645                      _config->Find("Dir::Bin::dpkg-source","dpkg-source").c_str(),
2646                      Dsc[I].Dsc.c_str());
2647             if (system(S) != 0)
2648             {
2649                fprintf(stderr,_("Unpack command '%s' failed.\n"),S);
2650                _exit(1);
2651             }       
2652          }
2653          
2654          // Try to compile it with dpkg-buildpackage
2655          if (_config->FindB("APT::Get::Compile",false) == true)
2656          {
2657             // Call dpkg-buildpackage
2658             char S[500];
2659             snprintf(S,sizeof(S),"cd %s && %s %s",
2660                      Dir.c_str(),
2661                      _config->Find("Dir::Bin::dpkg-buildpackage","dpkg-buildpackage").c_str(),
2662                      _config->Find("DPkg::Build-Options","-b -uc").c_str());
2663             
2664             if (system(S) != 0)
2665             {
2666                fprintf(stderr,_("Build command '%s' failed.\n"),S);
2667                _exit(1);
2668             }       
2669          }      
2670 #endif
2671       }
2672       
2673       _exit(0);
2674    }
2675    
2676    // Wait for the subprocess
2677    int Status = 0;
2678    while (waitpid(Process,&Status,0) != Process)
2679    {
2680       if (errno == EINTR)
2681          continue;
2682       return _error->Errno("waitpid","Couldn't wait for subprocess");
2683    }
2684
2685    if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0)
2686       return _error->Error(_("Child process failed"));
2687    
2688    return true;
2689 }
2690                                                                         /*}}}*/
2691 // DoBuildDep - Install/removes packages to satisfy build dependencies  /*{{{*/
2692 // ---------------------------------------------------------------------
2693 /* This function will look at the build depends list of the given source 
2694    package and install the necessary packages to make it true, or fail. */
2695 bool DoBuildDep(CommandLine &CmdL)
2696 {
2697    CacheFile Cache;
2698    // CNC:2004-04-06
2699    if (Cache.OpenForInstall() == false || 
2700        Cache.CheckDeps() == false)
2701       return false;
2702
2703    if (CmdL.FileSize() <= 1)
2704       return _error->Error(_("Must specify at least one package to check builddeps for"));
2705    
2706    // Read the source list
2707    pkgSourceList List;
2708    if (List.ReadMainList() == false)
2709       return _error->Error(_("The list of sources could not be read."));
2710    
2711    // Create the text record parsers
2712    pkgRecords Recs(Cache);
2713    pkgSrcRecords SrcRecs(List);
2714    if (_error->PendingError() == true)
2715       return false;
2716
2717    // Create the download object
2718    AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));   
2719    pkgAcquire Fetcher(&Stat);
2720
2721    unsigned J = 0;
2722    for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++)
2723    {
2724       string Src;
2725       pkgSrcRecords::Parser *Last = FindSrc(*I,Recs,SrcRecs,Src,*Cache);
2726       if (Last == 0)
2727          return _error->Error(_("Unable to find a source package for %s"),Src.c_str());
2728             
2729       // Process the build-dependencies
2730       vector<pkgSrcRecords::Parser::BuildDepRec> BuildDeps;
2731       if (Last->BuildDepends(BuildDeps, _config->FindB("APT::Get::Arch-Only",false)) == false)
2732         return _error->Error(_("Unable to get build-dependency information for %s"),Src.c_str());
2733    
2734       // Also ensure that build-essential packages are present
2735       Configuration::Item const *Opts = _config->Tree("APT::Build-Essential");
2736       if (Opts) 
2737          Opts = Opts->Child;
2738       for (; Opts; Opts = Opts->Next)
2739       {
2740          if (Opts->Value.empty() == true)
2741             continue;
2742
2743          pkgSrcRecords::Parser::BuildDepRec rec;
2744          rec.Package = Opts->Value;
2745          rec.Type = pkgSrcRecords::Parser::BuildDependIndep;
2746          rec.Op = 0;
2747          BuildDeps.push_back(rec);
2748       }
2749
2750       if (BuildDeps.size() == 0)
2751       {
2752          ioprintf(c1out,_("%s has no build depends.\n"),Src.c_str());
2753          continue;
2754       }
2755       
2756       // Install the requested packages
2757       unsigned int ExpectedInst = 0;
2758       vector <pkgSrcRecords::Parser::BuildDepRec>::iterator D;
2759       pkgProblemResolver Fix(Cache);
2760       bool skipAlternatives = false; // skip remaining alternatives in an or group
2761       for (D = BuildDeps.begin(); D != BuildDeps.end(); D++)
2762       {
2763          bool hasAlternatives = (((*D).Op & pkgCache::Dep::Or) == pkgCache::Dep::Or);
2764
2765          if (skipAlternatives == true)
2766          {
2767             if (!hasAlternatives)
2768                skipAlternatives = false; // end of or group
2769             continue;
2770          }
2771
2772          if ((*D).Type == pkgSrcRecords::Parser::BuildConflict ||
2773              (*D).Type == pkgSrcRecords::Parser::BuildConflictIndep)
2774          {
2775             pkgCache::PkgIterator Pkg = Cache->FindPkg((*D).Package);
2776             // Build-conflicts on unknown packages are silently ignored
2777             if (Pkg.end() == true)
2778                continue;
2779
2780             pkgCache::VerIterator IV = (*Cache)[Pkg].InstVerIter(*Cache);
2781
2782             /* 
2783              * Remove if we have an installed version that satisfies the 
2784              * version criteria
2785              */
2786             if (IV.end() == false && 
2787                 Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
2788                TryToInstall(Pkg,Cache,Fix,true,false,ExpectedInst);
2789          }
2790          else // BuildDep || BuildDepIndep
2791          {
2792             if (_config->FindB("Debug::BuildDeps",false) == true)
2793                  cout << "Looking for " << (*D).Package << "...\n";
2794
2795             pkgCache::PkgIterator Pkg = Cache->FindPkg((*D).Package);
2796
2797             // CNC:2003-11-21 - Try to handle unknown file deps.
2798             if (Pkg.end() == true && (*D).Package[0] == '/')
2799             {
2800                const char *File = (*D).Package.c_str();
2801                Pkg = (*Cache).PkgBegin();
2802                for (; Pkg.end() == false; Pkg++)
2803                {
2804                   // Should we try on all versions?
2805                   pkgCache::VerIterator Ver = (*Cache)[Pkg].CandidateVerIter(*Cache);
2806                   if (Ver.end() == false)
2807                   {
2808                      pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList());
2809                      if (Parse.HasFile(File))
2810                         break;
2811                   }
2812                }
2813             }
2814
2815             if (Pkg.end() == true)
2816             {
2817                if (_config->FindB("Debug::BuildDeps",false) == true)
2818                     cout << " (not found)" << (*D).Package << endl;
2819
2820                if (hasAlternatives)
2821                   continue;
2822
2823                return _error->Error(_("%s dependency for %s cannot be satisfied "
2824                                       "because the package %s cannot be found"),
2825                                     Last->BuildDepType((*D).Type),Src.c_str(),
2826                                     (*D).Package.c_str());
2827             }
2828
2829             /*
2830              * if there are alternatives, we've already picked one, so skip
2831              * the rest
2832              *
2833              * TODO: this means that if there's a build-dep on A|B and B is
2834              * installed, we'll still try to install A; more importantly,
2835              * if A is currently broken, we cannot go back and try B. To fix 
2836              * this would require we do a Resolve cycle for each package we 
2837              * add to the install list. Ugh
2838              */
2839                        
2840             /* 
2841              * If this is a virtual package, we need to check the list of
2842              * packages that provide it and see if any of those are
2843              * installed
2844              */
2845             pkgCache::PrvIterator Prv = Pkg.ProvidesList();
2846             for (; Prv.end() != true; Prv++)
2847             {
2848                if (_config->FindB("Debug::BuildDeps",false) == true)
2849                     cout << "  Checking provider " << Prv.OwnerPkg().Name() << endl;
2850
2851                if ((*Cache)[Prv.OwnerPkg()].InstVerIter(*Cache).end() == false)
2852                   break;
2853             }
2854             
2855             // Get installed version and version we are going to install
2856             pkgCache::VerIterator IV = (*Cache)[Pkg].InstVerIter(*Cache);
2857
2858             if ((*D).Version[0] != '\0') {
2859                  // Versioned dependency
2860
2861                  pkgCache::VerIterator CV = (*Cache)[Pkg].CandidateVerIter(*Cache);
2862
2863                  for (; CV.end() != true; CV++)
2864                  {
2865                       if (Cache->VS().CheckDep(CV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
2866                            break;
2867                  }
2868                  if (CV.end() == true)
2869                    if (hasAlternatives)
2870                    {
2871                       continue;
2872                    }
2873                    else
2874                    {
2875                       return _error->Error(_("%s dependency for %s cannot be satisfied "
2876                                              "because no available versions of package %s "
2877                                              "can satisfy version requirements"),
2878                                            Last->BuildDepType((*D).Type),Src.c_str(),
2879                                            (*D).Package.c_str());
2880                    }
2881             }
2882             else
2883             {
2884                // Only consider virtual packages if there is no versioned dependency
2885                if (Prv.end() == false)
2886                {
2887                   if (_config->FindB("Debug::BuildDeps",false) == true)
2888                      cout << "  Is provided by installed package " << Prv.OwnerPkg().Name() << endl;
2889                   skipAlternatives = hasAlternatives;
2890                   continue;
2891                }
2892             }
2893
2894             if (IV.end() == false)
2895             {
2896                if (_config->FindB("Debug::BuildDeps",false) == true)
2897                   cout << "  Is installed\n";
2898
2899                if (Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
2900                {
2901                   skipAlternatives = hasAlternatives;
2902                   continue;
2903                }
2904
2905                if (_config->FindB("Debug::BuildDeps",false) == true)
2906                   cout << "    ...but the installed version doesn't meet the version requirement\n";
2907
2908                if (((*D).Op & pkgCache::Dep::LessEq) == pkgCache::Dep::LessEq)
2909                {
2910                   return _error->Error(_("Failed to satisfy %s dependency for %s: Installed package %s is too new"),
2911                                        Last->BuildDepType((*D).Type),
2912                                        Src.c_str(),
2913                                        Pkg.Name());
2914                }
2915             }
2916
2917
2918             if (_config->FindB("Debug::BuildDeps",false) == true)
2919                cout << "  Trying to install " << (*D).Package << endl;
2920
2921             if (TryToInstall(Pkg,Cache,Fix,false,false,ExpectedInst) == true)
2922             {
2923                // We successfully installed something; skip remaining alternatives
2924                skipAlternatives = hasAlternatives;
2925                continue;
2926             }
2927             else if (hasAlternatives)
2928             {
2929                if (_config->FindB("Debug::BuildDeps",false) == true)
2930                   cout << "  Unsatisfiable, trying alternatives\n";
2931                continue;
2932             }
2933             else
2934             {
2935                return _error->Error(_("Failed to satisfy %s dependency for %s: %s"),
2936                                     Last->BuildDepType((*D).Type),
2937                                     Src.c_str(),
2938                                     (*D).Package.c_str());
2939             }
2940          }             
2941       }
2942       
2943       Fix.InstallProtect();
2944       if (Fix.Resolve(true) == false)
2945          _error->Discard();
2946       
2947       // Now we check the state of the packages,
2948       if (Cache->BrokenCount() != 0)
2949       {
2950          // CNC:2004-07-05
2951          ShowBroken(c1out, Cache, false);
2952          return _error->Error(_("Some broken packages were found while trying to process build-dependencies for %s.\n"
2953                                 "You might want to run `apt-get --fix-broken install' to correct these."),*I);
2954       }
2955    }
2956   
2957    if (InstallPackages(Cache, false, true) == false)
2958       return _error->Error(_("Failed to process build dependencies"));
2959
2960    // CNC:2003-03-06
2961    if (CheckOnly(Cache) == true)
2962       return true;
2963    
2964    return true;
2965 }
2966                                                                         /*}}}*/
2967
2968 // DoMoo - Never Ask, Never Tell                                        /*{{{*/
2969 // ---------------------------------------------------------------------
2970 /* */
2971 bool DoMoo(CommandLine &CmdL)
2972 {
2973    cout << 
2974       "         (__) \n"
2975       "         (oo) \n"
2976       "   /------\\/ \n"
2977       "  / |    ||   \n" 
2978       " *  /\\---/\\ \n"
2979       "    ~~   ~~   \n"
2980       "....\"Have you mooed today?\"...\n";
2981                             
2982    return true;
2983 }
2984                                                                         /*}}}*/
2985
2986 // CNC:2003-03-18
2987 // DoScript - Scripting stuff.                                          /*{{{*/
2988 // ---------------------------------------------------------------------
2989 /* */
2990 #ifdef WITH_LUA
2991 bool DoScript(CommandLine &CmdL)
2992 {
2993    for (const char **I = CmdL.FileList+1; *I != 0; I++)
2994       _config->Set("Scripts::AptGet::Script::", *I);
2995
2996    _lua->SetGlobal("commit_ask", 1);
2997    _lua->RunScripts("Scripts::AptGet::Script");
2998    double Ask = _lua->GetGlobalNum("commit_ask");
2999    _lua->ResetGlobals();
3000
3001    AptGetLuaCache *LuaCache = (AptGetLuaCache*) _lua->GetCacheControl();
3002    if (LuaCache && LuaCache->Cache) {
3003       CacheFile &Cache = *LuaCache->Cache;
3004       if (CheckOnly(Cache))
3005          return true;
3006       if ((*Cache).InstCount() > 0 || (*Cache).DelCount() > 0)
3007          return InstallPackages(Cache, false, Ask);
3008    }
3009
3010    return true;
3011 }
3012 #endif
3013                                                                         /*}}}*/
3014
3015 // ShowHelp - Show a help screen                                        /*{{{*/
3016 // ---------------------------------------------------------------------
3017 /* */
3018 bool ShowHelp(CommandLine &CmdL)
3019 {
3020    ioprintf(cout,_("%s %s for %s %s compiled on %s %s\n"),PACKAGE,VERSION,
3021             COMMON_OS,COMMON_CPU,__DATE__,__TIME__);
3022             
3023    if (_config->FindB("version") == true)
3024    {
3025       cout << _("Supported Modules:") << endl;
3026       
3027       for (unsigned I = 0; I != pkgVersioningSystem::GlobalListLen; I++)
3028       {
3029          pkgVersioningSystem *VS = pkgVersioningSystem::GlobalList[I];
3030          if (_system != 0 && _system->VS == VS)
3031             cout << '*';
3032          else
3033             cout << ' ';
3034          cout << "Ver: " << VS->Label << endl;
3035          
3036          /* Print out all the packaging systems that will work with 
3037             this VS */
3038          for (unsigned J = 0; J != pkgSystem::GlobalListLen; J++)
3039          {
3040             pkgSystem *Sys = pkgSystem::GlobalList[J];
3041             if (_system == Sys)
3042                cout << '*';
3043             else
3044                cout << ' ';
3045             if (Sys->VS->TestCompatibility(*VS) == true)
3046                cout << "Pkg:  " << Sys->Label << " (Priority " << Sys->Score(*_config) << ")" << endl;
3047          }
3048       }
3049       
3050       for (unsigned I = 0; I != pkgSourceList::Type::GlobalListLen; I++)
3051       {
3052          pkgSourceList::Type *Type = pkgSourceList::Type::GlobalList[I];
3053          cout << " S.L: '" << Type->Name << "' " << Type->Label << endl;
3054       }      
3055       
3056       for (unsigned I = 0; I != pkgIndexFile::Type::GlobalListLen; I++)
3057       {
3058          pkgIndexFile::Type *Type = pkgIndexFile::Type::GlobalList[I];
3059          cout << " Idx: " << Type->Label << endl;
3060       }      
3061       
3062       return true;
3063    }
3064    
3065    cout << 
3066     _("Usage: apt-get [options] command\n"
3067       "       apt-get [options] install|remove pkg1 [pkg2 ...]\n"
3068       "       apt-get [options] source pkg1 [pkg2 ...]\n"
3069       "\n"
3070       "apt-get is a simple command line interface for downloading and\n"
3071       "installing packages. The most frequently used commands are update\n"
3072       "and install.\n"   
3073       "\n"
3074       "Commands:\n"
3075       "   update - Retrieve new lists of packages\n"
3076       "   upgrade - Perform an upgrade\n"
3077 // CNC:2003-02-20 - Use .rpm extension in documentation.
3078       "   install - Install new packages (pkg is libc6 not libc6.rpm)\n"
3079       "   remove - Remove packages\n"
3080       "   source - Download source archives\n"
3081       "   build-dep - Configure build-dependencies for source packages\n"
3082       "   dist-upgrade - Distribution upgrade, see apt-get(8)\n"
3083 // CNC:2002-08-01
3084 //      "   dselect-upgrade - Follow dselect selections\n"
3085       "   clean - Erase downloaded archive files\n"
3086       "   autoclean - Erase old downloaded archive files\n"
3087       "   check - Verify that there are no broken dependencies\n"
3088 // CNC:2003-03-16
3089       );
3090 #ifdef WITH_LUA
3091       _lua->RunScripts("Scripts::AptGet::Help::Command");
3092 #endif
3093       cout << _(
3094       "\n"
3095       "Options:\n"
3096       "  -h  This help text.\n"
3097       "  -q  Loggable output - no progress indicator\n"
3098       "  -qq No output except for errors\n"
3099       "  -d  Download only - do NOT install or unpack archives\n"
3100       "  -s  No-act. Perform ordering simulation\n"
3101       "  -y  Assume Yes to all queries and do not prompt\n"
3102       "  -f  Attempt to continue if the integrity check fails\n"
3103       "  -m  Attempt to continue if archives are unlocatable\n"
3104       "  -u  Show a list of upgraded packages as well\n"
3105       "  -b  Build the source package after fetching it\n"
3106 // CNC:2002-08-02
3107       "  -D  When removing packages, remove dependencies as possible\n"
3108       "  -V  Show verbose version numbers\n"
3109       "  -c=? Read this configuration file\n"
3110       "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
3111       "See the apt-get(8), sources.list(5) and apt.conf(5) manual\n"
3112       "pages for more information and options.\n"
3113       "                       This APT has Super Cow Powers.\n");
3114    return true;
3115 }
3116                                                                         /*}}}*/
3117 // GetInitialize - Initialize things for apt-get                        /*{{{*/
3118 // ---------------------------------------------------------------------
3119 /* */
3120 void GetInitialize()
3121 {
3122    _config->Set("quiet",0);
3123    _config->Set("help",false);
3124    _config->Set("APT::Get::Download-Only",false);
3125    _config->Set("APT::Get::Simulate",false);
3126    _config->Set("APT::Get::Assume-Yes",false);
3127    _config->Set("APT::Get::Fix-Broken",false);
3128    _config->Set("APT::Get::Force-Yes",false);
3129    _config->Set("APT::Get::APT::Get::No-List-Cleanup",true);
3130 }
3131                                                                         /*}}}*/
3132 // SigWinch - Window size change signal handler                         /*{{{*/
3133 // ---------------------------------------------------------------------
3134 /* */
3135 void SigWinch(int)
3136 {
3137    // Riped from GNU ls
3138 #ifdef TIOCGWINSZ
3139    struct winsize ws;
3140   
3141    if (ioctl(1, TIOCGWINSZ, &ws) != -1 && ws.ws_col >= 5)
3142       ScreenWidth = ws.ws_col - 1;
3143 #endif
3144 }
3145                                                                         /*}}}*/
3146
3147 int main(int argc,const char *argv[])
3148 {
3149    CommandLine::Args Args[] = {
3150       {'h',"help","help",0},
3151       {'v',"version","version",0},
3152       {'V',"verbose-versions","APT::Get::Show-Versions",0},
3153       {'q',"quiet","quiet",CommandLine::IntLevel},
3154       {'q',"silent","quiet",CommandLine::IntLevel},
3155       {'d',"download-only","APT::Get::Download-Only",0},
3156       {'b',"compile","APT::Get::Compile",0},
3157       {'b',"build","APT::Get::Compile",0},
3158       {'s',"simulate","APT::Get::Simulate",0},
3159       {'s',"just-print","APT::Get::Simulate",0},
3160       {'s',"recon","APT::Get::Simulate",0},
3161       {'s',"dry-run","APT::Get::Simulate",0},
3162       {'s',"no-act","APT::Get::Simulate",0},
3163       {'y',"yes","APT::Get::Assume-Yes",0},
3164       {'y',"assume-yes","APT::Get::Assume-Yes",0},      
3165       {'f',"fix-broken","APT::Get::Fix-Broken",0},
3166       {'u',"show-upgraded","APT::Get::Show-Upgraded",0},
3167       {'m',"ignore-missing","APT::Get::Fix-Missing",0},
3168       {'D',"remove-deps","APT::Remove-Depends",0}, // CNC:2002-08-01
3169       {'t',"target-release","APT::Default-Release",CommandLine::HasArg},
3170       {'t',"default-release","APT::Default-Release",CommandLine::HasArg},
3171       {0,"download","APT::Get::Download",0},
3172       {0,"fix-missing","APT::Get::Fix-Missing",0},
3173       {0,"ignore-hold","APT::Ignore-Hold",0},      
3174       {0,"upgrade","APT::Get::upgrade",0},
3175       {0,"force-yes","APT::Get::force-yes",0},
3176       {0,"print-uris","APT::Get::Print-URIs",0},
3177       {0,"diff-only","APT::Get::Diff-Only",0},
3178       {0,"tar-only","APT::Get::tar-Only",0},
3179       {0,"purge","APT::Get::Purge",0},
3180       {0,"list-cleanup","APT::Get::List-Cleanup",0},
3181       {0,"reinstall","APT::Get::ReInstall",0},
3182       {0,"trivial-only","APT::Get::Trivial-Only",0},
3183       {0,"remove","APT::Get::Remove",0},
3184       {0,"only-source","APT::Get::Only-Source",0},
3185       {0,"arch-only","APT::Get::Arch-Only",0},
3186       {0,"check-only","APT::Get::Check-Only",0}, // CNC:2003-03-06
3187       {'c',"config-file",0,CommandLine::ConfigFile},
3188       {'o',"option",0,CommandLine::ArbItem},
3189       {0,0,0,0}};
3190    CommandLine::Dispatch Cmds[] = {{"update",&DoUpdate},
3191                                    {"upgrade",&DoUpgrade},
3192                                    {"install",&DoInstall},
3193                                    // CNC:2004-03-22
3194                                    {"reinstall",&DoInstall},
3195                                    {"remove",&DoInstall},
3196                                    {"dist-upgrade",&DoDistUpgrade},
3197                                    {"dselect-upgrade",&DoDSelectUpgrade},
3198                                    {"build-dep",&DoBuildDep},
3199                                    {"clean",&DoClean},
3200                                    {"autoclean",&DoAutoClean},
3201                                    {"check",&DoCheck},
3202                                    {"source",&DoSource},
3203                                    {"moo",&DoMoo},
3204                                    {"help",&ShowHelp},
3205 // CNC:2003-03-19
3206 #ifdef WITH_LUA
3207                                    {"script",&DoScript},
3208 #endif
3209                                    {0,0}};
3210
3211    // Set up gettext support
3212    setlocale(LC_ALL,"");
3213    textdomain(PACKAGE);
3214
3215    // Parse the command line and initialize the package library
3216    CommandLine CmdL(Args,_config);
3217    if (pkgInitConfig(*_config) == false ||
3218        CmdL.Parse(argc,argv) == false ||
3219        pkgInitSystem(*_config,_system) == false)
3220    {
3221       if (_config->FindB("version") == true)
3222          ShowHelp(CmdL);
3223          
3224       _error->DumpErrors();
3225       return 100;
3226    }
3227
3228    // See if the help should be shown
3229    if (_config->FindB("help") == true ||
3230        _config->FindB("version") == true ||
3231        CmdL.FileSize() == 0)
3232    {
3233       ShowHelp(CmdL);
3234       return 0;
3235    }
3236    
3237    // CNC:2003-11-21
3238    if (CmdL.FileSize() > 1)
3239    {
3240       // CNC:2003-11-23
3241       vector<string> URLLst;
3242       for (const char **I = CmdL.FileList + 1; *I != 0; I++)
3243       {
3244          if (strstr(*I, "://") != NULL)
3245          {
3246             URLLst.push_back(*I);
3247             *I = strrchr(*I, '/')+1;
3248          }
3249       }
3250
3251       if (URLLst.empty() == false && DownloadPackages(URLLst) == false)
3252       {
3253             _error->DumpErrors();
3254             return 100;
3255       }
3256
3257       for (const char **I = CmdL.FileList + 1; *I != 0; I++)
3258          _config->Set("APT::Arguments::", *I);
3259    }
3260
3261    // Deal with stdout not being a tty
3262    if (ttyname(STDOUT_FILENO) == 0 && _config->FindI("quiet",0) < 1)
3263       _config->Set("quiet","1");
3264
3265    // Setup the output streams
3266    c0out.rdbuf(cout.rdbuf());
3267    c1out.rdbuf(cout.rdbuf());
3268    c2out.rdbuf(cout.rdbuf());
3269    if (_config->FindI("quiet",0) > 0)
3270       c0out.rdbuf(devnull.rdbuf());
3271    if (_config->FindI("quiet",0) > 1)
3272       c1out.rdbuf(devnull.rdbuf());
3273
3274    // Setup the signals
3275    signal(SIGPIPE,SIG_IGN);
3276    signal(SIGWINCH,SigWinch);
3277    SigWinch(0);
3278
3279 // CNC:2003-11-23
3280 #ifdef WITH_LUA
3281    AptGetLuaCache LuaCache;
3282    _lua->SetCacheControl(&LuaCache);
3283    
3284    double Consume = 0;
3285    if (argc > 1 && _lua->HasScripts("Scripts::AptGet::Command") == true)
3286    {
3287       _lua->SetGlobal("commit_ask", 1);
3288       _lua->SetGlobal("command_args", CmdL.FileList);
3289       _lua->SetGlobal("command_consume", 0.0);
3290       _lua->RunScripts("Scripts::AptGet::Command");
3291       Consume = _lua->GetGlobalNum("command_consume");
3292       double Ask = _lua->GetGlobalNum("commit_ask");
3293       _lua->ResetGlobals();
3294       _lua->ResetCaches();
3295
3296       if (Consume == 1 && LuaCache.Cache)
3297       {
3298          CacheFile &Cache = *LuaCache.Cache;
3299          if (CheckOnly(Cache) == false &&
3300              (*Cache).InstCount() > 0 || (*Cache).DelCount() > 0)
3301             InstallPackages(Cache, false, Ask);
3302       }
3303    }
3304
3305    if (Consume == 0)
3306 #endif
3307    // Match the operation
3308    CmdL.DispatchArg(Cmds);
3309
3310    // Print any errors or warnings found during parsing
3311    if (_error->empty() == false)
3312    {
3313       bool Errors = _error->PendingError();
3314       _error->DumpErrors();
3315       return Errors == true?100:0;
3316    }
3317    
3318    return 0;   
3319 }
3320
3321 // vim:sts=3:sw=3