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