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