]> git.saurik.com Git - apt.git/blob - cmdline/apt-get.cc
279a0c4ed2298a231b41fe951efc349d42581c98
[apt.git] / cmdline / apt-get.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: apt-get.cc,v 1.16 1998/11/22 23:37:07 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 #include <apt-pkg/acquire-item.h>
36 #include <apt-pkg/dpkgpm.h>
37 #include <strutl.h>
38
39 #include <config.h>
40
41 #include "acqprogress.h"
42
43 #include <fstream.h>
44 #include <termios.h>
45 #include <sys/ioctl.h>
46 #include <signal.h>
47 #include <stdio.h>
48 /*}}}*/
49
50 ostream c0out;
51 ostream c1out;
52 ostream c2out;
53 ofstream devnull("/dev/null");
54 unsigned int ScreenWidth = 80;
55
56 // YnPrompt - Yes No Prompt. /*{{{*/
57 // ---------------------------------------------------------------------
58 /* Returns true on a Yes.*/
59 bool YnPrompt()
60 {
61 if (_config->FindB("APT::Get::Assume-Yes",false) == true)
62 {
63 c2out << 'Y' << endl;
64 return true;
65 }
66
67 char C = 0;
68 char Jnk = 0;
69 read(STDIN_FILENO,&C,1);
70 while (C != '\n' && Jnk != '\n') read(STDIN_FILENO,&Jnk,1);
71
72 if (!(C == 'Y' || C == 'y' || C == '\n' || C == '\r'))
73 return false;
74 return true;
75 }
76 /*}}}*/
77 // ShowList - Show a list /*{{{*/
78 // ---------------------------------------------------------------------
79 /* This prints out a string of space seperated words with a title and
80 a two space indent line wraped to the current screen width. */
81 void ShowList(ostream &out,string Title,string List)
82 {
83 if (List.empty() == true)
84 return;
85
86 // Acount for the leading space
87 int ScreenWidth = ::ScreenWidth - 3;
88
89 out << Title << endl;
90 string::size_type Start = 0;
91 while (Start < List.size())
92 {
93 string::size_type End;
94 if (Start + ScreenWidth >= List.size())
95 End = List.size();
96 else
97 End = List.rfind(' ',Start+ScreenWidth);
98
99 if (End == string::npos || End < Start)
100 End = Start + ScreenWidth;
101 out << " " << string(List,Start,End - Start) << endl;
102 Start = End + 1;
103 }
104 }
105 /*}}}*/
106 // ShowBroken - Debugging aide /*{{{*/
107 // ---------------------------------------------------------------------
108 /* This prints out the names of all the packages that are broken along
109 with the name of each each broken dependency and a quite version
110 description. */
111 void ShowBroken(ostream &out,pkgDepCache &Cache)
112 {
113 out << "Sorry, but the following packages have unmet dependencies:" << endl;
114 pkgCache::PkgIterator I = Cache.PkgBegin();
115 for (;I.end() != true; I++)
116 {
117 if (Cache[I].InstBroken() == false)
118 continue;
119
120 // Print out each package and the failed dependencies
121 out <<" " << I.Name() << ":";
122 int Indent = strlen(I.Name()) + 3;
123 bool First = true;
124 if (Cache[I].InstVerIter(Cache).end() == true)
125 {
126 cout << endl;
127 continue;
128 }
129
130 for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); D.end() == false;)
131 {
132 // Compute a single dependency element (glob or)
133 pkgCache::DepIterator Start;
134 pkgCache::DepIterator End;
135 D.GlobOr(Start,End);
136
137 if (Cache.IsImportantDep(End) == false ||
138 (Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
139 continue;
140
141 if (First == false)
142 for (int J = 0; J != Indent; J++)
143 out << ' ';
144 First = false;
145
146 cout << ' ' << End.DepType() << ": " << End.TargetPkg().Name();
147
148 // Show a quick summary of the version requirements
149 if (End.TargetVer() != 0)
150 out << " (" << End.CompType() << " " << End.TargetVer() <<
151 ")";
152
153 /* Show a summary of the target package if possible. In the case
154 of virtual packages we show nothing */
155
156 pkgCache::PkgIterator Targ = End.TargetPkg();
157 if (Targ->ProvidesList == 0)
158 {
159 out << " but ";
160 pkgCache::VerIterator Ver = Cache[Targ].InstVerIter(Cache);
161 if (Ver.end() == false)
162 out << Ver.VerStr() << " is installed";
163 else
164 {
165 if (Cache[Targ].CandidateVerIter(Cache).end() == true)
166 {
167 if (Targ->ProvidesList == 0)
168 out << "it is not installable";
169 else
170 out << "it is a virtual package";
171 }
172 else
173 out << "it is not installed";
174 }
175 }
176
177 out << endl;
178 }
179 }
180 }
181 /*}}}*/
182 // ShowNew - Show packages to newly install /*{{{*/
183 // ---------------------------------------------------------------------
184 /* */
185 void ShowNew(ostream &out,pkgDepCache &Dep)
186 {
187 /* Print out a list of packages that are going to be removed extra
188 to what the user asked */
189 pkgCache::PkgIterator I = Dep.PkgBegin();
190 string List;
191 for (;I.end() != true; I++)
192 if (Dep[I].NewInstall() == true)
193 List += string(I.Name()) + " ";
194 ShowList(out,"The following NEW packages will be installed:",List);
195 }
196 /*}}}*/
197 // ShowDel - Show packages to delete /*{{{*/
198 // ---------------------------------------------------------------------
199 /* */
200 void ShowDel(ostream &out,pkgDepCache &Dep)
201 {
202 /* Print out a list of packages that are going to be removed extra
203 to what the user asked */
204 pkgCache::PkgIterator I = Dep.PkgBegin();
205 string List;
206 for (;I.end() != true; I++)
207 if (Dep[I].Delete() == true)
208 List += string(I.Name()) + " ";
209 ShowList(out,"The following packages will be REMOVED:",List);
210 }
211 /*}}}*/
212 // ShowKept - Show kept packages /*{{{*/
213 // ---------------------------------------------------------------------
214 /* */
215 void ShowKept(ostream &out,pkgDepCache &Dep)
216 {
217 pkgCache::PkgIterator I = Dep.PkgBegin();
218 string List;
219 for (;I.end() != true; I++)
220 {
221 // Not interesting
222 if (Dep[I].Upgrade() == true || Dep[I].Upgradable() == false ||
223 I->CurrentVer == 0 || Dep[I].Delete() == true)
224 continue;
225
226 List += string(I.Name()) + " ";
227 }
228 ShowList(out,"The following packages have been kept back",List);
229 }
230 /*}}}*/
231 // ShowUpgraded - Show upgraded packages /*{{{*/
232 // ---------------------------------------------------------------------
233 /* */
234 void ShowUpgraded(ostream &out,pkgDepCache &Dep)
235 {
236 pkgCache::PkgIterator I = Dep.PkgBegin();
237 string List;
238 for (;I.end() != true; I++)
239 {
240 // Not interesting
241 if (Dep[I].Upgrade() == false || Dep[I].NewInstall() == true)
242 continue;
243
244 List += string(I.Name()) + " ";
245 }
246 ShowList(out,"The following packages will be upgraded",List);
247 }
248 /*}}}*/
249 // ShowHold - Show held but changed packages /*{{{*/
250 // ---------------------------------------------------------------------
251 /* */
252 void ShowHold(ostream &out,pkgDepCache &Dep)
253 {
254 pkgCache::PkgIterator I = Dep.PkgBegin();
255 string List;
256 for (;I.end() != true; I++)
257 {
258 if (Dep[I].InstallVer != (pkgCache::Version *)I.CurrentVer() &&
259 I->SelectedState == pkgCache::State::Hold)
260 List += string(I.Name()) + " ";
261 }
262
263 ShowList(out,"The following held packages will be changed:",List);
264 }
265 /*}}}*/
266 // ShowEssential - Show an essential package warning /*{{{*/
267 // ---------------------------------------------------------------------
268 /* This prints out a warning message that is not to be ignored. It shows
269 all essential packages and their dependents that are to be removed.
270 It is insanely risky to remove the dependents of an essential package! */
271 void ShowEssential(ostream &out,pkgDepCache &Dep)
272 {
273 pkgCache::PkgIterator I = Dep.PkgBegin();
274 string List;
275 bool *Added = new bool[Dep.HeaderP->PackageCount];
276 for (unsigned int I = 0; I != Dep.HeaderP->PackageCount; I++)
277 Added[I] = false;
278
279 for (;I.end() != true; I++)
280 {
281 if ((I->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential)
282 continue;
283
284 // The essential package is being removed
285 if (Dep[I].Delete() == true)
286 {
287 if (Added[I->ID] == false)
288 {
289 Added[I->ID] = true;
290 List += string(I.Name()) + " ";
291 }
292 }
293
294 if (I->CurrentVer == 0)
295 continue;
296
297 // Print out any essential package depenendents that are to be removed
298 for (pkgDepCache::DepIterator D = I.CurrentVer().DependsList(); D.end() == false; D++)
299 {
300 // Skip everything but depends
301 if (D->Type != pkgCache::Dep::PreDepends &&
302 D->Type != pkgCache::Dep::Depends)
303 continue;
304
305 pkgCache::PkgIterator P = D.SmartTargetPkg();
306 if (Dep[P].Delete() == true)
307 {
308 if (Added[P->ID] == true)
309 continue;
310 Added[P->ID] = true;
311
312 char S[300];
313 sprintf(S,"%s (due to %s) ",P.Name(),I.Name());
314 List += S;
315 }
316 }
317 }
318
319 if (List.empty() == false)
320 out << "WARNING: The following essential packages will be removed" << endl;
321 ShowList(out,"This should NOT be done unless you know exactly what you are doing!",List);
322
323 delete [] Added;
324 }
325 /*}}}*/
326 // Stats - Show some statistics /*{{{*/
327 // ---------------------------------------------------------------------
328 /* */
329 void Stats(ostream &out,pkgDepCache &Dep)
330 {
331 unsigned long Upgrade = 0;
332 unsigned long Install = 0;
333 for (pkgCache::PkgIterator I = Dep.PkgBegin(); I.end() == false; I++)
334 {
335 if (Dep[I].NewInstall() == true)
336 Install++;
337 else
338 if (Dep[I].Upgrade() == true)
339 Upgrade++;
340 }
341
342 out << Upgrade << " packages upgraded, " <<
343 Install << " newly installed, " <<
344 Dep.DelCount() << " to remove and " <<
345 Dep.KeepCount() << " not upgraded." << endl;
346
347 if (Dep.BadCount() != 0)
348 out << Dep.BadCount() << " packages not fully installed or removed." << endl;
349 }
350 /*}}}*/
351
352 // class CacheFile - Cover class for some dependency cache functions /*{{{*/
353 // ---------------------------------------------------------------------
354 /* */
355 class CacheFile
356 {
357 public:
358
359 FileFd *File;
360 MMap *Map;
361 pkgDepCache *Cache;
362
363 inline operator pkgDepCache &() {return *Cache;};
364 inline pkgDepCache *operator ->() {return Cache;};
365 inline pkgDepCache &operator *() {return *Cache;};
366
367 bool Open();
368 CacheFile() : File(0), Map(0), Cache(0) {};
369 ~CacheFile()
370 {
371 delete Cache;
372 delete Map;
373 delete File;
374 }
375 };
376 /*}}}*/
377 // CacheFile::Open - Open the cache file /*{{{*/
378 // ---------------------------------------------------------------------
379 /* This routine generates the caches and then opens the dependency cache
380 and verifies that the system is OK. */
381 bool CacheFile::Open()
382 {
383 // Create a progress class
384 OpTextProgress Progress(*_config);
385
386 // Read the source list
387 pkgSourceList List;
388 if (List.ReadMainList() == false)
389 return _error->Error("The list of sources could not be read.");
390
391 // Build all of the caches
392 pkgMakeStatusCache(List,Progress);
393 if (_error->PendingError() == true)
394 return _error->Error("The package lists or status file could not be parsed or opened.");
395
396 Progress.Done();
397
398 // Open the cache file
399 File = new FileFd(_config->FindFile("Dir::Cache::pkgcache"),FileFd::ReadOnly);
400 if (_error->PendingError() == true)
401 return false;
402
403 Map = new MMap(*File,MMap::Public | MMap::ReadOnly);
404 if (_error->PendingError() == true)
405 return false;
406
407 Cache = new pkgDepCache(*Map,Progress);
408 if (_error->PendingError() == true)
409 return false;
410
411 Progress.Done();
412
413 // Check that the system is OK
414 if (Cache->DelCount() != 0 || Cache->InstCount() != 0)
415 return _error->Error("Internal Error, non-zero counts");
416
417 // Apply corrections for half-installed packages
418 if (pkgApplyStatus(*Cache) == false)
419 return false;
420
421 // Nothing is broken
422 if (Cache->BrokenCount() == 0)
423 return true;
424
425 // Attempt to fix broken things
426 if (_config->FindB("APT::Get::Fix-Broken",false) == true)
427 {
428 c1out << "Correcting dependencies..." << flush;
429 if (pkgFixBroken(*Cache) == false || Cache->BrokenCount() != 0)
430 {
431 c1out << " failed." << endl;
432 ShowBroken(c1out,*this);
433
434 return _error->Error("Unable to correct dependencies");
435 }
436 if (pkgMinimizeUpgrade(*Cache) == false)
437 return _error->Error("Unable to minimize the upgrade set");
438
439 c1out << " Done" << endl;
440 }
441 else
442 {
443 c1out << "You might want to run `apt-get -f install' to correct these." << endl;
444 ShowBroken(c1out,*this);
445
446 return _error->Error("Unmet dependencies. Try using -f.");
447 }
448
449 return true;
450 }
451 /*}}}*/
452
453 // InstallPackages - Actually download and install the packages /*{{{*/
454 // ---------------------------------------------------------------------
455 /* This displays the informative messages describing what is going to
456 happen and then calls the download routines */
457 bool InstallPackages(pkgDepCache &Cache,bool ShwKept,bool Ask = true)
458 {
459 // Show all the various warning indicators
460 ShowDel(c1out,Cache);
461 ShowNew(c1out,Cache);
462 if (ShwKept == true)
463 ShowKept(c1out,Cache);
464 ShowHold(c1out,Cache);
465 if (_config->FindB("APT::Get::Show-Upgraded",false) == true)
466 ShowUpgraded(c1out,Cache);
467 ShowEssential(c1out,Cache);
468 Stats(c1out,Cache);
469
470 // Sanity check
471 if (Cache.BrokenCount() != 0)
472 {
473 ShowBroken(c1out,Cache);
474 return _error->Error("Internal Error, InstallPackages was called with broken packages!");
475 }
476
477 if (Cache.DelCount() == 0 && Cache.InstCount() == 0 &&
478 Cache.BadCount() == 0)
479 return true;
480
481 // Run the simulator ..
482 if (_config->FindB("APT::Get::Simulate") == true)
483 {
484 pkgSimulate PM(Cache);
485 return PM.DoInstall();
486 }
487
488 // Create the text record parser
489 pkgRecords Recs(Cache);
490
491 // Create the download object
492 AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
493 pkgAcquire Fetcher(&Stat);
494
495 // Read the source list
496 pkgSourceList List;
497 if (List.ReadMainList() == false)
498 return _error->Error("The list of sources could not be read.");
499
500 // Create the package manager and prepare to download
501 pkgDPkgPM PM(Cache);
502 if (PM.GetArchives(&Fetcher,&List,&Recs) == false)
503 return false;
504
505 // Display statistics
506 unsigned long FetchBytes = Fetcher.FetchNeeded();
507 unsigned long DebBytes = Fetcher.TotalNeeded();
508 if (DebBytes != Cache.DebSize())
509 c0out << "How odd.. The sizes didn't match, email apt@packages.debian.org" << endl;
510
511 // Number of bytes
512 c1out << "Need to get ";
513 if (DebBytes != FetchBytes)
514 c1out << SizeToStr(FetchBytes) << '/' << SizeToStr(DebBytes);
515 else
516 c1out << SizeToStr(DebBytes);
517
518 c1out << " of archives. After unpacking ";
519
520 // Size delta
521 if (Cache.UsrSize() >= 0)
522 c1out << SizeToStr(Cache.UsrSize()) << " will be used." << endl;
523 else
524 c1out << SizeToStr(-1*Cache.UsrSize()) << " will be freed." << endl;
525
526 if (_error->PendingError() == true)
527 return false;
528
529 // Prompt to continue
530 if (Ask == true)
531 {
532 if (_config->FindI("quiet",0) < 2 ||
533 _config->FindB("APT::Get::Assume-Yes",false) == false)
534 c2out << "Do you want to continue? [Y/n] " << flush;
535 if (YnPrompt() == false)
536 exit(1);
537 }
538
539 // Run it
540 if (Fetcher.Run() == false)
541 return false;
542
543 // Print out errors
544 bool Failed = false;
545 for (pkgAcquire::Item **I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
546 {
547 if ((*I)->Status == pkgAcquire::Item::StatDone &&
548 (*I)->Complete == true)
549 continue;
550
551 cerr << "Failed to fetch " << (*I)->Describe() << endl;
552 cerr << " " << (*I)->ErrorText << endl;
553 Failed = true;
554 }
555
556 if (Failed == true && _config->FindB("APT::Fix-Missing",false) == false)
557 return _error->Error("Unable to fetch some archives, maybe try with --fix-missing?");
558
559 // Try to deal with missing package files
560 /* if (PM.FixMissing() == false)
561 {
562 cerr << "Unable to correct missing packages." << endl;
563 return _error->Error("Aborting Install.");
564 }*/
565
566 return PM.DoInstall();
567 }
568 /*}}}*/
569
570 // DoUpdate - Update the package lists /*{{{*/
571 // ---------------------------------------------------------------------
572 /* */
573 bool DoUpdate(CommandLine &)
574 {
575 // Get the source list
576 pkgSourceList List;
577 if (List.ReadMainList() == false)
578 return false;
579
580 // Create the download object
581 AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
582 pkgAcquire Fetcher(&Stat);
583
584 // Populate it with the source selection
585 pkgSourceList::const_iterator I;
586 for (I = List.begin(); I != List.end(); I++)
587 {
588 new pkgAcqIndex(&Fetcher,I);
589 if (_error->PendingError() == true)
590 return false;
591 }
592
593 // Run it
594 if (Fetcher.Run() == false)
595 return false;
596
597 // Clean out any old list files
598 if (Fetcher.Clean(_config->FindDir("Dir::State::lists")) == false ||
599 Fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/") == false)
600 return false;
601
602 // Prepare the cache.
603 CacheFile Cache;
604 if (Cache.Open() == false)
605 return false;
606
607 return true;
608 }
609 /*}}}*/
610 // DoUpgrade - Upgrade all packages /*{{{*/
611 // ---------------------------------------------------------------------
612 /* Upgrade all packages without installing new packages or erasing old
613 packages */
614 bool DoUpgrade(CommandLine &CmdL)
615 {
616 CacheFile Cache;
617 if (Cache.Open() == false)
618 return false;
619
620 // Do the upgrade
621 if (pkgAllUpgrade(Cache) == false)
622 {
623 ShowBroken(c1out,Cache);
624 return _error->Error("Internal Error, AllUpgrade broke stuff");
625 }
626
627 return InstallPackages(Cache,true);
628 }
629 /*}}}*/
630 // DoInstall - Install packages from the command line /*{{{*/
631 // ---------------------------------------------------------------------
632 /* Install named packages */
633 bool DoInstall(CommandLine &CmdL)
634 {
635 CacheFile Cache;
636 if (Cache.Open() == false)
637 return false;
638
639 unsigned int ExpectedInst = 0;
640 unsigned int Packages = 0;
641 pkgProblemResolver Fix(Cache);
642
643 bool DefRemove = false;
644 if (strcasecmp(CmdL.FileList[0],"remove") == 0)
645 DefRemove = true;
646
647 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
648 {
649 // Duplicate the string
650 unsigned int Length = strlen(*I);
651 char S[300];
652 if (Length >= sizeof(S))
653 continue;
654 strcpy(S,*I);
655
656 // See if we are removing the package
657 bool Remove = DefRemove;
658 if (Cache->FindPkg(S).end() == true)
659 {
660 // Handle an optional end tag indicating what to do
661 if (S[Length - 1] == '-')
662 {
663 Remove = true;
664 S[--Length] = 0;
665 }
666 if (S[Length - 1] == '+')
667 {
668 Remove = false;
669 S[--Length] = 0;
670 }
671 }
672
673 // Locate the package
674 pkgCache::PkgIterator Pkg = Cache->FindPkg(S);
675 Packages++;
676 if (Pkg.end() == true)
677 return _error->Error("Couldn't find package %s",S);
678
679 // Handle the no-upgrade case
680 if (_config->FindB("APT::Get::no-upgrade",false) == true &&
681 Pkg->CurrentVer != 0)
682 {
683 c1out << "Skipping " << Pkg.Name() << ", it is already installed and no-upgrade is set." << endl;
684 continue;
685 }
686
687 // Check if there is something new to install
688 pkgDepCache::StateCache &State = (*Cache)[Pkg];
689 if (State.CandidateVer == 0)
690 {
691 if (Pkg->ProvidesList != 0)
692 {
693 c1out << "Package " << S << " is a virtual package provided by:" << endl;
694
695 pkgCache::PrvIterator I = Pkg.ProvidesList();
696 for (; I.end() == false; I++)
697 {
698 pkgCache::PkgIterator Pkg = I.OwnerPkg();
699
700 if ((*Cache)[Pkg].CandidateVerIter(*Cache) == I.OwnerVer())
701 c1out << " " << Pkg.Name() << " " << I.OwnerVer().VerStr() << endl;
702
703 if ((*Cache)[Pkg].InstVerIter(*Cache) == I.OwnerVer())
704 c1out << " " << Pkg.Name() << " " << I.OwnerVer().VerStr() <<
705 " [Installed]"<< endl;
706 }
707 c1out << "You should explicly select one to install." << endl;
708 }
709 else
710 {
711 c1out << "Package " << S << " has no available version, but exists in the database." << endl;
712 c1out << "This typically means that the package was mentioned in a dependency and " << endl;
713 c1out << "never uploaded, or that it is an obsolete package." << endl;
714 }
715
716 return _error->Error("Package %s has no installation candidate",S);
717 }
718
719 Fix.Protect(Pkg);
720 if (Remove == true)
721 {
722 Fix.Remove(Pkg);
723 Cache->MarkDelete(Pkg);
724 continue;
725 }
726
727 // Install it
728 Cache->MarkInstall(Pkg,false);
729 if (State.Install() == false)
730 c1out << "Sorry, " << S << " is already the newest version" << endl;
731 else
732 ExpectedInst++;
733
734 // Install it with autoinstalling enabled.
735 if (State.InstBroken() == true)
736 Cache->MarkInstall(Pkg,true);
737 }
738
739 // Call the scored problem resolver
740 Fix.InstallProtect();
741 if (Fix.Resolve(true) == false)
742 _error->Discard();
743
744 // Now we check the state of the packages,
745 if (Cache->BrokenCount() != 0)
746 {
747 c1out << "Some packages could not be installed. This may mean that you have" << endl;
748 c1out << "requested an impossible situation or if you are using the unstable" << endl;
749 c1out << "distribution that some required packages have not yet been created" << endl;
750 c1out << "or been moved out of Incoming." << endl;
751 if (Packages == 1)
752 {
753 c1out << endl;
754 c1out << "Since you only requested a single operation it is extremely likely that" << endl;
755 c1out << "the package is simply not installable and a bug report against" << endl;
756 c1out << "that package should be filed." << endl;
757 }
758
759 c1out << "The following information may help to resolve the situation:" << endl;
760 c1out << endl;
761 ShowBroken(c1out,Cache);
762 return _error->Error("Sorry, broken packages");
763 }
764
765 /* Print out a list of packages that are going to be installed extra
766 to what the user asked */
767 if (Cache->InstCount() != ExpectedInst)
768 {
769 string List;
770 pkgCache::PkgIterator I = Cache->PkgBegin();
771 for (;I.end() != true; I++)
772 {
773 if ((*Cache)[I].Install() == false)
774 continue;
775
776 const char **J;
777 for (J = CmdL.FileList + 1; *J != 0; J++)
778 if (strcmp(*J,I.Name()) == 0)
779 break;
780
781 if (*J == 0)
782 List += string(I.Name()) + " ";
783 }
784
785 ShowList(c1out,"The following extra packages will be installed:",List);
786 }
787
788 // See if we need to prompt
789 if (Cache->InstCount() == ExpectedInst && Cache->DelCount() == 0)
790 return InstallPackages(Cache,false,false);
791
792 return InstallPackages(Cache,false);
793 }
794 /*}}}*/
795 // DoDistUpgrade - Automatic smart upgrader /*{{{*/
796 // ---------------------------------------------------------------------
797 /* Intelligent upgrader that will install and remove packages at will */
798 bool DoDistUpgrade(CommandLine &CmdL)
799 {
800 CacheFile Cache;
801 if (Cache.Open() == false)
802 return false;
803
804 c0out << "Calculating Upgrade... " << flush;
805 if (pkgDistUpgrade(*Cache) == false)
806 {
807 c0out << "Failed" << endl;
808 ShowBroken(c1out,Cache);
809 return false;
810 }
811
812 c0out << "Done" << endl;
813
814 return InstallPackages(Cache,true);
815 }
816 /*}}}*/
817 // DoDSelectUpgrade - Do an upgrade by following dselects selections /*{{{*/
818 // ---------------------------------------------------------------------
819 /* Follows dselect's selections */
820 bool DoDSelectUpgrade(CommandLine &CmdL)
821 {
822 CacheFile Cache;
823 if (Cache.Open() == false)
824 return false;
825
826 // Install everything with the install flag set
827 pkgCache::PkgIterator I = Cache->PkgBegin();
828 for (;I.end() != true; I++)
829 {
830 /* Install the package only if it is a new install, the autoupgrader
831 will deal with the rest */
832 if (I->SelectedState == pkgCache::State::Install)
833 Cache->MarkInstall(I,false);
834 }
835
836 /* Now install their deps too, if we do this above then order of
837 the status file is significant for | groups */
838 for (I = Cache->PkgBegin();I.end() != true; I++)
839 {
840 /* Install the package only if it is a new install, the autoupgrader
841 will deal with the rest */
842 if (I->SelectedState == pkgCache::State::Install)
843 Cache->MarkInstall(I);
844 }
845
846 // Apply erasures now, they override everything else.
847 for (I = Cache->PkgBegin();I.end() != true; I++)
848 {
849 // Remove packages
850 if (I->SelectedState == pkgCache::State::DeInstall ||
851 I->SelectedState == pkgCache::State::Purge)
852 Cache->MarkDelete(I);
853 }
854
855 /* Use updates smart upgrade to do the rest, it will automatically
856 ignore held items */
857 if (pkgAllUpgrade(Cache) == false)
858 {
859 ShowBroken(c1out,Cache);
860 return _error->Error("Internal Error, AllUpgrade broke stuff");
861 }
862
863 return InstallPackages(Cache,false);
864 }
865 /*}}}*/
866 // DoClean - Remove download archives /*{{{*/
867 // ---------------------------------------------------------------------
868 /* */
869 bool DoClean(CommandLine &CmdL)
870 {
871 pkgAcquire Fetcher;
872 Fetcher.Clean(_config->FindDir("Dir::Cache::archives"));
873 Fetcher.Clean(_config->FindDir("Dir::Cache::archives") + "partial/");
874 return true;
875 }
876 /*}}}*/
877 // DoCheck - Perform the check operation /*{{{*/
878 // ---------------------------------------------------------------------
879 /* Opening automatically checks the system, this command is mostly used
880 for debugging */
881 bool DoCheck(CommandLine &CmdL)
882 {
883 CacheFile Cache;
884 Cache.Open();
885
886 return true;
887 }
888 /*}}}*/
889
890 // ShowHelp - Show a help screen /*{{{*/
891 // ---------------------------------------------------------------------
892 /* */
893 int ShowHelp()
894 {
895 cout << PACKAGE << ' ' << VERSION << " for " << ARCHITECTURE <<
896 " compiled on " << __DATE__ << " " << __TIME__ << endl;
897
898 cout << "Usage: apt-get [options] command" << endl;
899 cout << " apt-get [options] install pkg1 [pkg2 ...]" << endl;
900 cout << endl;
901 cout << "apt-get is a simple command line interface for downloading and" << endl;
902 cout << "installing packages. The most frequently used commands are update" << endl;
903 cout << "and install." << endl;
904 cout << endl;
905 cout << "Commands:" << endl;
906 cout << " update - Retrieve new lists of packages" << endl;
907 cout << " upgrade - Perform an upgrade" << endl;
908 cout << " install - Install new packages (pkg is libc6 not libc6.deb)" << endl;
909 cout << " remove - Remove packages" << endl;
910 cout << " dist-upgrade - Distribution upgrade, see apt-get(8)" << endl;
911 cout << " dselect-upgrade - Follow dselect selections" << endl;
912 cout << " clean - Erase downloaded archive files" << endl;
913 cout << " check - Verify that there are no broken dependencies" << endl;
914 cout << endl;
915 cout << "Options:" << endl;
916 cout << " -h This help text." << endl;
917 cout << " -q Loggable output - no progress indicator" << endl;
918 cout << " -qq No output except for errors" << endl;
919 cout << " -d Download only - do NOT install or unpack archives" << endl;
920 cout << " -s No-act. Perform ordering simulation" << endl;
921 cout << " -y Assume Yes to all queries and do not prompt" << endl;
922 cout << " -f Attempt to continue if the integrity check fails" << endl;
923 cout << " -m Attempt to continue if archives are unlocatable" << endl;
924 cout << " -u Show a list of upgraded packages as well" << endl;
925 cout << " -c=? Read this configuration file" << endl;
926 cout << " -o=? Set an arbitary configuration option, ie -o dir::cache=/tmp" << endl;
927 cout << "See the apt-get(8), sources.list(8) and apt.conf(8) manual" << endl;
928 cout << "pages for more information." << endl;
929 return 100;
930 }
931 /*}}}*/
932 // GetInitialize - Initialize things for apt-get /*{{{*/
933 // ---------------------------------------------------------------------
934 /* */
935 void GetInitialize()
936 {
937 _config->Set("quiet",0);
938 _config->Set("help",false);
939 _config->Set("APT::Get::Download-Only",false);
940 _config->Set("APT::Get::Simulate",false);
941 _config->Set("APT::Get::Assume-Yes",false);
942 _config->Set("APT::Get::Fix-Broken",false);
943 }
944 /*}}}*/
945 // SigWinch - Window size change signal handler /*{{{*/
946 // ---------------------------------------------------------------------
947 /* */
948 void SigWinch(int)
949 {
950 // Riped from GNU ls
951 #ifdef TIOCGWINSZ
952 struct winsize ws;
953
954 if (ioctl(1, TIOCGWINSZ, &ws) != -1 && ws.ws_col >= 5)
955 ScreenWidth = ws.ws_col - 1;
956 #endif
957 }
958 /*}}}*/
959
960 int main(int argc,const char *argv[])
961 {
962 CommandLine::Args Args[] = {
963 {'h',"help","help",0},
964 {'q',"quiet","quiet",CommandLine::IntLevel},
965 {'q',"silent","quiet",CommandLine::IntLevel},
966 {'d',"download-only","APT::Get::Download-Only",0},
967 {'s',"simulate","APT::Get::Simulate",0},
968 {'s',"just-print","APT::Get::Simulate",0},
969 {'s',"recon","APT::Get::Simulate",0},
970 {'s',"no-act","APT::Get::Simulate",0},
971 {'y',"yes","APT::Get::Assume-Yes",0},
972 {'y',"assume-yes","APT::Get::Assume-Yes",0},
973 {'f',"fix-broken","APT::Get::Fix-Broken",0},
974 {'u',"show-upgraded","APT::Get::Show-Upgraded",0},
975 {'m',"ignore-missing","APT::Get::Fix-Missing",0},
976 {0,"fix-missing","APT::Get::Fix-Missing",0},
977 {0,"ignore-hold","APT::Ingore-Hold",0},
978 {0,"no-upgrade","APT::Get::no-upgrade",0},
979 {'c',"config-file",0,CommandLine::ConfigFile},
980 {'o',"option",0,CommandLine::ArbItem},
981 {0,0,0,0}};
982
983 // Parse the command line and initialize the package library
984 CommandLine CmdL(Args,_config);
985 if (pkgInitialize(*_config) == false ||
986 CmdL.Parse(argc,argv) == false)
987 {
988 _error->DumpErrors();
989 return 100;
990 }
991
992 // See if the help should be shown
993 if (_config->FindB("help") == true ||
994 CmdL.FileSize() == 0)
995 return ShowHelp();
996
997 // Setup the output streams
998 c0out.rdbuf(cout.rdbuf());
999 c1out.rdbuf(cout.rdbuf());
1000 c2out.rdbuf(cout.rdbuf());
1001 if (_config->FindI("quiet",0) > 0)
1002 c0out.rdbuf(devnull.rdbuf());
1003 if (_config->FindI("quiet",0) > 1)
1004 c1out.rdbuf(devnull.rdbuf());
1005
1006 // Setup the signals
1007 signal(SIGPIPE,SIG_IGN);
1008 signal(SIGWINCH,SigWinch);
1009 SigWinch(0);
1010
1011 // Match the operation
1012 struct
1013 {
1014 const char *Match;
1015 bool (*Handler)(CommandLine &);
1016 } Map[] = {{"update",&DoUpdate},
1017 {"upgrade",&DoUpgrade},
1018 {"install",&DoInstall},
1019 {"remove",&DoInstall},
1020 {"dist-upgrade",&DoDistUpgrade},
1021 {"dselect-upgrade",&DoDSelectUpgrade},
1022 {"clean",&DoClean},
1023 {"check",&DoCheck},
1024 {0,0}};
1025 int I;
1026 for (I = 0; Map[I].Match != 0; I++)
1027 {
1028 if (strcmp(CmdL.FileList[0],Map[I].Match) == 0)
1029 {
1030 if (Map[I].Handler(CmdL) == false && _error->PendingError() == false)
1031 _error->Error("Handler silently failed");
1032 break;
1033 }
1034 }
1035
1036 // No matching name
1037 if (Map[I].Match == 0)
1038 _error->Error("Invalid operation %s", CmdL.FileList[0]);
1039
1040 // Print any errors or warnings found during parsing
1041 if (_error->empty() == false)
1042 {
1043 bool Errors = _error->PendingError();
1044 _error->DumpErrors();
1045 if (Errors == true)
1046 cout << "Returning 100." << endl;
1047 return Errors == true?100:0;
1048 }
1049
1050 return 0;
1051 }