]> git.saurik.com Git - apt.git/blame_incremental - cmdline/apt-get.cc
Sync
[apt.git] / cmdline / apt-get.cc
... / ...
CommitLineData
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
3// $Id: apt-get.cc,v 1.2 1998/10/08 04:55:05 jgg 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/pkgcachegen.h>
34#include <apt-pkg/algorithms.h>
35
36#include <config.h>
37
38#include <fstream.h>
39 /*}}}*/
40
41ostream c0out;
42ostream c1out;
43ostream c2out;
44ofstream devnull("/dev/null");
45unsigned int ScreenWidth = 80;
46
47// ShowList - Show a list /*{{{*/
48// ---------------------------------------------------------------------
49/* This prints out a string of space seperated words with a title and
50 a two space indent line wraped to the current screen width. */
51void ShowList(ostream &out,string Title,string List)
52{
53 if (List.empty() == true)
54 return;
55
56 // Acount for the leading space
57 int ScreenWidth = ::ScreenWidth - 3;
58
59 out << Title << endl;
60 string::size_type Start = 0;
61 while (Start < List.size())
62 {
63 string::size_type End;
64 if (Start + ScreenWidth >= List.size())
65 End = List.size();
66 else
67 End = List.rfind(' ',Start+ScreenWidth);
68
69 if (End == string::npos || End < Start)
70 End = Start + ScreenWidth;
71 out << " " << string(List,Start,End - Start) << endl;
72 Start = End + 1;
73 }
74}
75 /*}}}*/
76// ShowBroken - Debugging aide /*{{{*/
77// ---------------------------------------------------------------------
78/* This prints out the names of all the packages that are broken along
79 with the name of each each broken dependency and a quite version
80 description. */
81void ShowBroken(ostream &out,pkgDepCache &Cache)
82{
83 out << "Sorry, but the following packages are broken - this means they have unmet" << endl;
84 out << "dependencies:" << endl;
85 pkgCache::PkgIterator I = Cache.PkgBegin();
86 for (;I.end() != true; I++)
87 {
88 if (Cache[I].InstBroken() == true)
89 {
90 // Print out each package and the failed dependencies
91 out <<" " << I.Name() << ":";
92 int Indent = strlen(I.Name()) + 3;
93 bool First = true;
94 for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); D.end() == false; D++)
95 {
96 if (Cache.IsImportantDep(D) == false || (Cache[D] &
97 pkgDepCache::DepInstall) != 0)
98 continue;
99
100 if (First == false)
101 for (int J = 0; J != Indent; J++)
102 out << ' ';
103 First = false;
104
105 if (D->Type == pkgCache::Dep::Conflicts)
106 out << " Conflicts:" << D.TargetPkg().Name();
107 else
108 out << " Depends:" << D.TargetPkg().Name();
109
110 // Show a quick summary of the version requirements
111 if (D.TargetVer() != 0)
112 out << " (" << D.CompType() << " " << D.TargetVer() <<
113 ")";
114
115 /* Show a summary of the target package if possible. In the case
116 of virtual packages we show nothing */
117 pkgCache::PkgIterator Targ = D.TargetPkg();
118 if (Targ->ProvidesList == 0)
119 {
120 out << " but ";
121 pkgCache::VerIterator Ver = Cache[Targ].InstVerIter(Cache);
122 if (Ver.end() == false)
123 out << Ver.VerStr() << "is installed";
124 else
125 out << "it is not installed";
126 }
127
128 out << endl;
129 }
130 }
131 }
132}
133 /*}}}*/
134// ShowNew - Show packages to newly install /*{{{*/
135// ---------------------------------------------------------------------
136/* */
137void ShowNew(ostream &out,pkgDepCache &Dep)
138{
139 /* Print out a list of packages that are going to be removed extra
140 to what the user asked */
141 pkgCache::PkgIterator I = Dep.PkgBegin();
142 string List;
143 for (;I.end() != true; I++)
144 if (Dep[I].NewInstall() == true)
145 List += string(I.Name()) + " ";
146 ShowList(out,"The following NEW packages will be installed:",List);
147}
148 /*}}}*/
149// ShowDel - Show packages to delete /*{{{*/
150// ---------------------------------------------------------------------
151/* */
152void ShowDel(ostream &out,pkgDepCache &Dep)
153{
154 /* Print out a list of packages that are going to be removed extra
155 to what the user asked */
156 pkgCache::PkgIterator I = Dep.PkgBegin();
157 string List;
158 for (;I.end() != true; I++)
159 if (Dep[I].Delete() == true)
160 List += string(I.Name()) + " ";
161 ShowList(out,"The following packages will be REMOVED:",List);
162}
163 /*}}}*/
164// ShowKept - Show kept packages /*{{{*/
165// ---------------------------------------------------------------------
166/* */
167void ShowKept(ostream &out,pkgDepCache &Dep)
168{
169 pkgCache::PkgIterator I = Dep.PkgBegin();
170 string List;
171 for (;I.end() != true; I++)
172 {
173 // Not interesting
174 if (Dep[I].Upgrade() == true || Dep[I].Upgradable() == false ||
175 I->CurrentVer == 0 || Dep[I].Delete() == true)
176 continue;
177
178 List += string(I.Name()) + " ";
179 }
180 ShowList(out,"The following packages have been kept back",List);
181}
182 /*}}}*/
183// ShowUpgraded - Show upgraded packages /*{{{*/
184// ---------------------------------------------------------------------
185/* */
186void ShowUpgraded(ostream &out,pkgDepCache &Dep)
187{
188 pkgCache::PkgIterator I = Dep.PkgBegin();
189 string List;
190 for (;I.end() != true; I++)
191 {
192 // Not interesting
193 if (Dep[I].Upgrade() == false || Dep[I].NewInstall() == true)
194 continue;
195
196 List += string(I.Name()) + " ";
197 }
198 ShowList(out,"The following packages will be upgraded",List);
199}
200 /*}}}*/
201// ShowHold - Show held but changed packages /*{{{*/
202// ---------------------------------------------------------------------
203/* */
204void ShowHold(ostream &out,pkgDepCache &Dep)
205{
206 pkgCache::PkgIterator I = Dep.PkgBegin();
207 string List;
208 for (;I.end() != true; I++)
209 {
210 if (Dep[I].InstallVer != (pkgCache::Version *)I.CurrentVer() &&
211 I->SelectedState == pkgCache::State::Hold)
212 List += string(I.Name()) + " ";
213 }
214
215 ShowList(out,"The following held packages will be changed:",List);
216}
217 /*}}}*/
218// ShowEssential - Show an essential package warning /*{{{*/
219// ---------------------------------------------------------------------
220/* This prints out a warning message that is not to be ignored. It shows
221 all essential packages and their dependents that are to be removed.
222 It is insanely risky to remove the dependents of an essential package! */
223void ShowEssential(ostream &out,pkgDepCache &Dep)
224{
225 pkgCache::PkgIterator I = Dep.PkgBegin();
226 string List;
227 bool *Added = new bool[Dep.HeaderP->PackageCount];
228 for (int I = 0; I != Dep.HeaderP->PackageCount; I++)
229 Added[I] = false;
230
231 for (;I.end() != true; I++)
232 {
233 if ((I->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential)
234 continue;
235
236 // The essential package is being removed
237 if (Dep[I].Delete() == true)
238 {
239 if (Added[I->ID] == false)
240 {
241 Added[I->ID] = true;
242 List += string(I.Name()) + " ";
243 }
244 }
245
246 if (I->CurrentVer == 0)
247 continue;
248
249 // Print out any essential package depenendents that are to be removed
250 for (pkgDepCache::DepIterator D = I.CurrentVer().DependsList(); D.end() == false; D++)
251 {
252 pkgCache::PkgIterator P = D.SmartTargetPkg();
253 if (Dep[P].Delete() == true)
254 {
255 if (Added[P->ID] == true)
256 continue;
257 Added[P->ID] = true;
258 List += string(P.Name()) + " ";
259 }
260 }
261 }
262
263 if (List.empty() == false)
264 out << "WARNING: The following essential packages will be removed" << endl;
265 ShowList(out,"This should NOT be done unless you know exactly what you are doing!",List);
266
267 delete [] Added;
268}
269 /*}}}*/
270// Stats - Show some statistics /*{{{*/
271// ---------------------------------------------------------------------
272/* */
273void Stats(ostream &out,pkgDepCache &Dep)
274{
275 unsigned long Upgrade = 0;
276 unsigned long Install = 0;
277 for (pkgCache::PkgIterator I = Dep.PkgBegin(); I.end() == false; I++)
278 {
279 if (Dep[I].NewInstall() == true)
280 Install++;
281 else
282 if (Dep[I].Upgrade() == true)
283 Upgrade++;
284 }
285
286 out << Upgrade << " packages upgraded, " <<
287 Install << " newly installed, " <<
288 Dep.DelCount() << " to remove and " <<
289 Dep.KeepCount() << " not upgraded." << endl;
290
291 if (Dep.BadCount() != 0)
292 out << Dep.BadCount() << " packages not fully installed or removed." << endl;
293}
294 /*}}}*/
295
296// class CacheFile - Cover class for some dependency cache functions /*{{{*/
297// ---------------------------------------------------------------------
298/* */
299class CacheFile
300{
301 public:
302
303 FileFd *File;
304 MMap *Map;
305 pkgDepCache *Cache;
306
307 inline operator pkgDepCache &() {return *Cache;};
308 inline pkgDepCache *operator ->() {return Cache;};
309 inline pkgDepCache &operator *() {return *Cache;};
310
311 bool Open();
312 CacheFile() : File(0), Map(0), Cache(0) {};
313 ~CacheFile()
314 {
315 delete Cache;
316 delete Map;
317 delete File;
318 }
319};
320 /*}}}*/
321// CacheFile::Open - Open the cache file /*{{{*/
322// ---------------------------------------------------------------------
323/* This routine generates the caches and then opens the dependency cache
324 and verifies that the system is OK. */
325bool CacheFile::Open()
326{
327 // Create a progress class
328 OpTextProgress Progress(*_config);
329
330 // Read the source list
331 pkgSourceList List;
332 if (List.ReadMainList() == false)
333 return _error->Error("The list of sources could not be read.");
334
335 // Build all of the caches
336 pkgMakeStatusCache(List,Progress);
337 if (_error->PendingError() == true)
338 return _error->Error("The package lists or status file could not be parsed or opened.");
339
340 Progress.Done();
341
342 // Open the cache file
343 File = new FileFd(_config->FindDir("Dir::Cache::pkgcache"),FileFd::ReadOnly);
344 if (_error->PendingError() == true)
345 return false;
346
347 Map = new MMap(*File,MMap::Public | MMap::ReadOnly);
348 if (_error->PendingError() == true)
349 return false;
350
351 Cache = new pkgDepCache(*Map,Progress);
352 if (_error->PendingError() == true)
353 return false;
354
355 Progress.Done();
356
357 // Check that the system is OK
358 if (Cache->DelCount() != 0 || Cache->InstCount() != 0)
359 return _error->Error("Internal Error, non-zero counts");
360
361 // Apply corrections for half-installed packages
362 if (pkgApplyStatus(*Cache) == false)
363 return false;
364
365 // Nothing is broken
366 if (Cache->BrokenCount() == 0)
367 return true;
368
369 // Attempt to fix broken things
370 if (_config->FindB("APT::Get::Fix-Broken",false) == true)
371 {
372 c1out << "Correcting dependencies..." << flush;
373 if (pkgFixBroken(*Cache) == false || Cache->BrokenCount() != 0)
374 {
375 c1out << " failed." << endl;
376 ShowBroken(c1out,*this);
377
378 return _error->Error("Unable to correct dependencies");
379 }
380 if (pkgMinimizeUpgrade(*Cache) == false)
381 return _error->Error("Unable to minimize the upgrade set");
382
383 c1out << " Done" << endl;
384 }
385 else
386 {
387 c1out << "You might want to run `apt-get -f install' to correct these." << endl;
388 ShowBroken(c1out,*this);
389
390 return _error->Error("Unmet dependencies. Try using -f.");
391 }
392
393 return true;
394}
395 /*}}}*/
396
397// InstallPackages - Actually download and install the packages /*{{{*/
398// ---------------------------------------------------------------------
399/* This displays the informative messages describing what is going to
400 happen and then calls the download routines */
401bool InstallPackages(pkgDepCache &Cache,bool ShwKept)
402{
403 ShowDel(c1out,Cache);
404 ShowNew(c1out,Cache);
405 if (ShwKept == true)
406 ShowKept(c1out,Cache);
407 ShowHold(c1out,Cache);
408 if (_config->FindB("APT::Get::Show-Upgraded",false) == true)
409 ShowUpgraded(c1out,Cache);
410 ShowEssential(c1out,Cache);
411 Stats(c1out,Cache);
412
413 // Sanity check
414 if (Cache.BrokenCount() != 0)
415 {
416 ShowBroken(c1out,Cache);
417 return _error->Error("Internal Error, InstallPackages was called with broken packages!");
418 }
419
420 if (Cache.DelCount() == 0 && Cache.InstCount() == 0 &&
421 Cache.BadCount() == 0)
422 return true;
423
424 return true;
425}
426 /*}}}*/
427
428// DoUpdate - Update the package lists /*{{{*/
429// ---------------------------------------------------------------------
430/* */
431bool DoUpdate(CommandLine &CmdL)
432{
433}
434 /*}}}*/
435// DoUpgrade - Upgrade all packages /*{{{*/
436// ---------------------------------------------------------------------
437/* Upgrade all packages without installing new packages or erasing old
438 packages */
439bool DoUpgrade(CommandLine &CmdL)
440{
441 CacheFile Cache;
442 if (Cache.Open() == false)
443 return false;
444
445 // Do the upgrade
446 pkgProblemResolver Resolve(Cache);
447 if (pkgAllUpgrade(Cache) == false)
448 {
449 ShowBroken(c1out,Cache);
450 return _error->Error("Internal Error, AllUpgrade broke stuff");
451 }
452
453 return InstallPackages(Cache,true);
454}
455 /*}}}*/
456// DoInstall - Install packages from the command line /*{{{*/
457// ---------------------------------------------------------------------
458/* Install named packages */
459bool DoInstall(CommandLine &CmdL)
460{
461 CacheFile Cache;
462 if (Cache.Open() == false)
463 return false;
464
465 int ExpectedInst = 0;
466 pkgProblemResolver Fix(Cache);
467
468 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
469 {
470 // Duplicate the string
471 unsigned int Length = strlen(*I);
472 char S[300];
473 if (Length >= sizeof(S))
474 continue;
475 strcpy(S,*I);
476
477 // See if we are removing the package
478 bool Remove = false;
479 if (S[Length - 1] == '-')
480 {
481 Remove = true;
482 S[--Length] = 0;
483 }
484
485 // Locate the package
486 pkgCache::PkgIterator Pkg = Cache->FindPkg(S);
487 if (Pkg.end() == true)
488 return _error->Error("Couldn't find package %s",S);
489
490 // Check if there is something new to install
491 pkgDepCache::StateCache &State = (*Cache)[Pkg];
492 if (State.CandidateVer == 0)
493 return _error->Error("Package %s has no installation candidate",S);
494
495 Fix.Protect(Pkg);
496 if (Remove == true)
497 {
498 Cache->MarkDelete(Pkg);
499 continue;
500 }
501
502 // Install it
503 Cache->MarkInstall(Pkg,false);
504 if (State.Install() == false)
505 c1out << "Sorry, " << S << " is already the newest version" << endl;
506 else
507 ExpectedInst++;
508
509 // Install it with autoinstalling enabled.
510 if (State.InstBroken() == true)
511 Cache->MarkInstall(Pkg,true);
512 }
513
514 // Call the scored problem resolver
515 if (Fix.Resolve(true) == false)
516 _error->Discard();
517
518 // Now we check the state of the packages,
519 if (Cache->BrokenCount() != 0)
520 {
521 ShowBroken(c1out,Cache);
522 return _error->Error("Sorry, broken packages");
523 }
524
525 /* Print out a list of packages that are going to be installed extra
526 to what the user asked */
527 if (Cache->InstCount() != ExpectedInst)
528 {
529 string List;
530 pkgCache::PkgIterator I = Cache->PkgBegin();
531 for (;I.end() != true; I++)
532 {
533 if ((*Cache)[I].Install() == false)
534 continue;
535
536 const char **J;
537 for (J = CmdL.FileList + 1; *J != 0; J++)
538 if (strcmp(*J,I.Name()) == 0)
539 break;
540
541 if (*J == 0)
542 List += string(I.Name()) + " ";
543 }
544
545 ShowList(c1out,"The following extra packages will be installed:",List);
546 }
547
548 return InstallPackages(Cache,false);
549}
550 /*}}}*/
551// DoDistUpgrade - Automatic smart upgrader /*{{{*/
552// ---------------------------------------------------------------------
553/* Intelligent upgrader that will install and remove packages at will */
554bool DoDistUpgrade(CommandLine &CmdL)
555{
556 CacheFile Cache;
557 if (Cache.Open() == false)
558 return false;
559
560 c0out << "Calculating Upgrade... " << flush;
561 if (pkgDistUpgrade(*Cache) == false)
562 {
563 c0out << "Failed" << endl;
564 ShowBroken(c1out,Cache);
565 return false;
566 }
567
568 c0out << "Done" << endl;
569
570 return InstallPackages(Cache,true);
571}
572 /*}}}*/
573// DoDSelectUpgrade - Do an upgrade by following dselects selections /*{{{*/
574// ---------------------------------------------------------------------
575/* Follows dselect's selections */
576bool DoDSelectUpgrade(CommandLine &CmdL)
577{
578 CacheFile Cache;
579 if (Cache.Open() == false)
580 return false;
581
582 // Install everything with the install flag set
583 pkgCache::PkgIterator I = Cache->PkgBegin();
584 for (;I.end() != true; I++)
585 {
586 /* Install the package only if it is a new install, the autoupgrader
587 will deal with the rest */
588 if (I->SelectedState == pkgCache::State::Install)
589 Cache->MarkInstall(I,false);
590 }
591
592 /* Now install their deps too, if we do this above then order of
593 the status file is significant for | groups */
594 for (I = Cache->PkgBegin();I.end() != true; I++)
595 {
596 /* Install the package only if it is a new install, the autoupgrader
597 will deal with the rest */
598 if (I->SelectedState == pkgCache::State::Install)
599 Cache->MarkInstall(I);
600 }
601
602 // Apply erasures now, they override everything else.
603 for (I = Cache->PkgBegin();I.end() != true; I++)
604 {
605 // Remove packages
606 if (I->SelectedState == pkgCache::State::DeInstall ||
607 I->SelectedState == pkgCache::State::Purge)
608 Cache->MarkDelete(I);
609 }
610
611 /* Use updates smart upgrade to do the rest, it will automatically
612 ignore held items */
613 if (pkgAllUpgrade(Cache) == false)
614 {
615 ShowBroken(c1out,Cache);
616 return _error->Error("Internal Error, AllUpgrade broke stuff");
617 }
618
619 return InstallPackages(Cache,false);
620}
621 /*}}}*/
622// DoClean - Remove download archives /*{{{*/
623// ---------------------------------------------------------------------
624/* */
625bool DoClean(CommandLine &CmdL)
626{
627 return true;
628}
629 /*}}}*/
630// DoCheck - Perform the check operation /*{{{*/
631// ---------------------------------------------------------------------
632/* Opening automatically checks the system, this command is mostly used
633 for debugging */
634bool DoCheck(CommandLine &CmdL)
635{
636 CacheFile Cache;
637 Cache.Open();
638
639 return true;
640}
641 /*}}}*/
642
643// ShowHelp - Show a help screen /*{{{*/
644// ---------------------------------------------------------------------
645/* */
646int ShowHelp()
647{
648 cout << PACKAGE << ' ' << VERSION << " for " << ARCHITECTURE <<
649 " compiled on " << __DATE__ << " " << __TIME__ << endl;
650
651 cout << "Usage: apt-get [options] command" << endl;
652 cout << " apt-get [options] install pkg1 [pkg2 ...]" << endl;
653 cout << endl;
654 cout << "apt-get is a simple command line interface for downloading and" << endl;
655 cout << "installing packages. The most frequently used commands are update" << endl;
656 cout << "and install." << endl;
657 cout << endl;
658 cout << "Commands:" << endl;
659 cout << " update - Retrieve new lists of packages" << endl;
660 cout << " upgrade - Perform an upgrade" << endl;
661 cout << " install - Install new packages (pkg is libc6 not libc6.deb)" << endl;
662 cout << " dist-upgrade - Distribution upgrade, see apt-get(8)" << endl;
663 cout << " dselect-upgrade - Follow dselect selections" << endl;
664 cout << " clean - Erase downloaded archive files" << endl;
665 cout << " check - Verify that there are no broken dependencies" << endl;
666 cout << endl;
667 cout << "Options:" << endl;
668 cout << " -h This help text." << endl;
669 cout << " -q Loggable output - no progress indicator" << endl;
670 cout << " -qq No output except for errors" << endl;
671 cout << " -d Download only - do NOT install or unpack archives" << endl;
672 cout << " -s No-act. Perform ordering simulation" << endl;
673 cout << " -y Assume Yes to all queries and do not prompt" << endl;
674 cout << " -f Attempt to continue if the integrity check fails" << endl;
675 cout << " -m Attempt to continue if archives are unlocatable" << endl;
676 cout << " -u Show a list of upgraded packages as well" << endl;
677 cout << " -c=? Read this configuration file" << endl;
678 cout << " -o=? Set an arbitary configuration option, ie -o dir::cache=/tmp" << endl;
679 cout << "See the apt-get(8), sources.list(8) and apt.conf(8) manual" << endl;
680 cout << "pages for more information." << endl;
681 return 100;
682}
683 /*}}}*/
684// GetInitialize - Initialize things for apt-get /*{{{*/
685// ---------------------------------------------------------------------
686/* */
687void GetInitialize()
688{
689 _config->Set("quiet",0);
690 _config->Set("help",false);
691 _config->Set("APT::Get::Download-Only",false);
692 _config->Set("APT::Get::Simulate",false);
693 _config->Set("APT::Get::Assume-Yes",false);
694 _config->Set("APT::Get::Fix-Broken",false);
695}
696 /*}}}*/
697
698int main(int argc,const char *argv[])
699{
700 CommandLine::Args Args[] = {
701 {'h',"help","help",0},
702 {'q',"quiet","quiet",CommandLine::IntLevel},
703 {'q',"silent","quiet",CommandLine::IntLevel},
704 {'d',"download-only","APT::Get::Download-Only",0},
705 {'s',"simulate","APT::Get::Simulate",0},
706 {'s',"just-print","APT::Get::Simulate",0},
707 {'s',"recon","APT::Get::Simulate",0},
708 {'s',"no-act","APT::Get::Simulate",0},
709 {'y',"yes","APT::Get::Assume-Yes",0},
710 {'y',"assume-yes","APT::Get::Assume-Yes",0},
711 {'f',"fix-broken","APT::Get::Fix-Broken",0},
712 {'u',"show-upgraded","APT::Get::Show-Upgraded",0},
713 {'m',"ignore-missing","APT::Get::Fix-Broken",0},
714 {'c',"config-file",0,CommandLine::ConfigFile},
715 {'o',"option",0,CommandLine::ArbItem},
716 {0,0,0,0}};
717
718 // Parse the command line and initialize the package library
719 CommandLine CmdL(Args,_config);
720 if (pkgInitialize(*_config) == false ||
721 CmdL.Parse(argc,argv) == false)
722 {
723 _error->DumpErrors();
724 return 100;
725 }
726
727 // See if the help should be shown
728 if (_config->FindB("help") == true ||
729 CmdL.FileSize() == 0)
730 return ShowHelp();
731
732 // Setup the output streams
733 c0out.rdbuf(cout.rdbuf());
734 c1out.rdbuf(cout.rdbuf());
735 c2out.rdbuf(cout.rdbuf());
736 if (_config->FindI("quiet",0) > 0)
737 c0out.rdbuf(devnull.rdbuf());
738 if (_config->FindI("quiet",0) > 1)
739 c1out.rdbuf(devnull.rdbuf());
740
741 // Match the operation
742 struct
743 {
744 const char *Match;
745 bool (*Handler)(CommandLine &);
746 } Map[] = {{"update",&DoUpdate},
747 {"upgrade",&DoUpgrade},
748 {"install",&DoInstall},
749 {"dist-upgrade",&DoDistUpgrade},
750 {"dselect-upgrade",&DoDSelectUpgrade},
751 {"clean",&DoClean},
752 {"check",&DoCheck},
753 {0,0}};
754 int I;
755 for (I = 0; Map[I].Match != 0; I++)
756 {
757 if (strcmp(CmdL.FileList[0],Map[I].Match) == 0)
758 {
759 Map[I].Handler(CmdL);
760 break;
761 }
762 }
763
764 // No matching name
765 if (Map[I].Match == 0)
766 _error->Error("Invalid operation %s", CmdL.FileList[0]);
767
768 // Print any errors or warnings found during parsing
769 if (_error->empty() == false)
770 {
771 bool Errors = _error->PendingError();
772 _error->DumpErrors();
773 if (Errors == true)
774 cout << "Returning 100." << endl;
775 return Errors == true?100:0;
776 }
777
778 return 0;
779}