]> git.saurik.com Git - apt.git/blame_incremental - cmdline/apt-get.cc
Core correctness patches
[apt.git] / cmdline / apt-get.cc
... / ...
CommitLineData
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
3// $Id: apt-get.cc,v 1.104 2001/03/13 05:23:42 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/algorithms.h>
34#include <apt-pkg/acquire-item.h>
35#include <apt-pkg/strutl.h>
36#include <apt-pkg/clean.h>
37#include <apt-pkg/srcrecords.h>
38#include <apt-pkg/version.h>
39#include <apt-pkg/cachefile.h>
40#include <apt-pkg/sptr.h>
41#include <apt-pkg/versionmatch.h>
42
43#include <config.h>
44#include <apti18n.h>
45
46#include "acqprogress.h"
47
48#include <fstream.h>
49#include <termios.h>
50#include <sys/ioctl.h>
51#include <sys/stat.h>
52#include <sys/statvfs.h>
53#include <signal.h>
54#include <unistd.h>
55#include <stdio.h>
56#include <errno.h>
57#include <regex.h>
58#include <sys/wait.h>
59 /*}}}*/
60
61ostream c0out;
62ostream c1out;
63ostream c2out;
64ofstream devnull("/dev/null");
65unsigned int ScreenWidth = 80;
66
67// class CacheFile - Cover class for some dependency cache functions /*{{{*/
68// ---------------------------------------------------------------------
69/* */
70class CacheFile : public pkgCacheFile
71{
72 static pkgCache *SortCache;
73 static int NameComp(const void *a,const void *b);
74
75 public:
76 pkgCache::Package **List;
77
78 void Sort();
79 bool CheckDeps(bool AllowBroken = false);
80 bool Open(bool WithLock = true)
81 {
82 OpTextProgress Prog(*_config);
83 if (pkgCacheFile::Open(Prog,WithLock) == false)
84 return false;
85 Sort();
86
87 return true;
88 };
89 CacheFile() : List(0) {};
90};
91 /*}}}*/
92
93// YnPrompt - Yes No Prompt. /*{{{*/
94// ---------------------------------------------------------------------
95/* Returns true on a Yes.*/
96bool YnPrompt()
97{
98 // This needs to be a capital
99 const char *Yes = _("Y");
100
101 if (_config->FindB("APT::Get::Assume-Yes",false) == true)
102 {
103 c1out << Yes << endl;
104 return true;
105 }
106
107 char C = 0;
108 char Jnk = 0;
109 if (read(STDIN_FILENO,&C,1) != 1)
110 return false;
111 while (C != '\n' && Jnk != '\n')
112 if (read(STDIN_FILENO,&Jnk,1) != 1)
113 return false;
114
115 if (!(toupper(C) == *Yes || C == '\n' || C == '\r'))
116 return false;
117 return true;
118}
119 /*}}}*/
120// AnalPrompt - Annoying Yes No Prompt. /*{{{*/
121// ---------------------------------------------------------------------
122/* Returns true on a Yes.*/
123bool AnalPrompt(const char *Text)
124{
125 char Buf[1024];
126 cin.getline(Buf,sizeof(Buf));
127 if (strcmp(Buf,Text) == 0)
128 return true;
129 return false;
130}
131 /*}}}*/
132// ShowList - Show a list /*{{{*/
133// ---------------------------------------------------------------------
134/* This prints out a string of space separated words with a title and
135 a two space indent line wraped to the current screen width. */
136bool ShowList(ostream &out,string Title,string List)
137{
138 if (List.empty() == true)
139 return true;
140
141 // Acount for the leading space
142 int ScreenWidth = ::ScreenWidth - 3;
143
144 out << Title << endl;
145 string::size_type Start = 0;
146 while (Start < List.size())
147 {
148 string::size_type End;
149 if (Start + ScreenWidth >= List.size())
150 End = List.size();
151 else
152 End = List.rfind(' ',Start+ScreenWidth);
153
154 if (End == string::npos || End < Start)
155 End = Start + ScreenWidth;
156 out << " " << string(List,Start,End - Start) << endl;
157 Start = End + 1;
158 }
159 return false;
160}
161 /*}}}*/
162// ShowBroken - Debugging aide /*{{{*/
163// ---------------------------------------------------------------------
164/* This prints out the names of all the packages that are broken along
165 with the name of each each broken dependency and a quite version
166 description.
167
168 The output looks like:
169 Sorry, but the following packages have unmet dependencies:
170 exim: Depends: libc6 (>= 2.1.94) but 2.1.3-10 is to be installed
171 Depends: libldap2 (>= 2.0.2-2) but it is not going to be installed
172 Depends: libsasl7 but it is not going to be installed
173 */
174void ShowBroken(ostream &out,CacheFile &Cache,bool Now)
175{
176 out << _("Sorry, but the following packages have unmet dependencies:") << endl;
177 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
178 {
179 pkgCache::PkgIterator I(Cache,Cache.List[J]);
180
181 if (Cache[I].InstBroken() == false)
182 continue;
183
184 // Print out each package and the failed dependencies
185 out <<" " << I.Name() << ":";
186 unsigned Indent = strlen(I.Name()) + 3;
187 bool First = true;
188 if (Cache[I].InstVerIter(Cache).end() == true)
189 {
190 cout << endl;
191 continue;
192 }
193
194 for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); D.end() == false;)
195 {
196 // Compute a single dependency element (glob or)
197 pkgCache::DepIterator Start;
198 pkgCache::DepIterator End;
199 D.GlobOr(Start,End);
200
201 if (Cache->IsImportantDep(End) == false ||
202 (Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
203 continue;
204
205 bool FirstOr = true;
206 while (1)
207 {
208 if (First == false)
209 for (unsigned J = 0; J != Indent; J++)
210 out << ' ';
211 First = false;
212
213 if (FirstOr == false)
214 {
215 for (unsigned J = 0; J != strlen(End.DepType()) + 3; J++)
216 out << ' ';
217 }
218 else
219 out << ' ' << End.DepType() << ": ";
220 FirstOr = false;
221
222 out << Start.TargetPkg().Name();
223
224 // Show a quick summary of the version requirements
225 if (Start.TargetVer() != 0)
226 out << " (" << Start.CompType() << " " << Start.TargetVer() << ")";
227
228 /* Show a summary of the target package if possible. In the case
229 of virtual packages we show nothing */
230 pkgCache::PkgIterator Targ = Start.TargetPkg();
231 if (Targ->ProvidesList == 0)
232 {
233 out << ' ';
234 pkgCache::VerIterator Ver = Cache[Targ].InstVerIter(Cache);
235 if (Ver.end() == false)
236 {
237 if (Now == true)
238 ioprintf(out,_("but %s is installed"),Ver.VerStr());
239 else
240 ioprintf(out,_("but %s is to be installed"),Ver.VerStr());
241 }
242 else
243 {
244 if (Cache[Targ].CandidateVerIter(Cache).end() == true)
245 {
246 if (Targ->ProvidesList == 0)
247 out << _("but it is not installable");
248 else
249 out << _("but it is a virtual package");
250 }
251 else
252 out << (Now?_("but it is not installed"):_("but it is not going to be installed"));
253 }
254 }
255
256 if (Start != End)
257 out << _(" or");
258 out << endl;
259
260 if (Start == End)
261 break;
262 Start++;
263 }
264 }
265 }
266}
267 /*}}}*/
268// ShowNew - Show packages to newly install /*{{{*/
269// ---------------------------------------------------------------------
270/* */
271void ShowNew(ostream &out,CacheFile &Cache)
272{
273 /* Print out a list of packages that are going to be removed extra
274 to what the user asked */
275 string List;
276 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
277 {
278 pkgCache::PkgIterator I(Cache,Cache.List[J]);
279 if (Cache[I].NewInstall() == true)
280 List += string(I.Name()) + " ";
281 }
282
283 ShowList(out,_("The following NEW packages will be installed:"),List);
284}
285 /*}}}*/
286// ShowDel - Show packages to delete /*{{{*/
287// ---------------------------------------------------------------------
288/* */
289void ShowDel(ostream &out,CacheFile &Cache)
290{
291 /* Print out a list of packages that are going to be removed extra
292 to what the user asked */
293 string List;
294 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
295 {
296 pkgCache::PkgIterator I(Cache,Cache.List[J]);
297 if (Cache[I].Delete() == true)
298 {
299 if ((Cache[I].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge)
300 List += string(I.Name()) + "* ";
301 else
302 List += string(I.Name()) + " ";
303 }
304 }
305
306 ShowList(out,_("The following packages will be REMOVED:"),List);
307}
308 /*}}}*/
309// ShowKept - Show kept packages /*{{{*/
310// ---------------------------------------------------------------------
311/* */
312void ShowKept(ostream &out,CacheFile &Cache)
313{
314 string List;
315 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
316 {
317 pkgCache::PkgIterator I(Cache,Cache.List[J]);
318
319 // Not interesting
320 if (Cache[I].Upgrade() == true || Cache[I].Upgradable() == false ||
321 I->CurrentVer == 0 || Cache[I].Delete() == true)
322 continue;
323
324 List += string(I.Name()) + " ";
325 }
326 ShowList(out,_("The following packages have been kept back"),List);
327}
328 /*}}}*/
329// ShowUpgraded - Show upgraded packages /*{{{*/
330// ---------------------------------------------------------------------
331/* */
332void ShowUpgraded(ostream &out,CacheFile &Cache)
333{
334 string List;
335 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
336 {
337 pkgCache::PkgIterator I(Cache,Cache.List[J]);
338
339 // Not interesting
340 if (Cache[I].Upgrade() == false || Cache[I].NewInstall() == true)
341 continue;
342
343 List += string(I.Name()) + " ";
344 }
345 ShowList(out,_("The following packages will be upgraded"),List);
346}
347 /*}}}*/
348// ShowDowngraded - Show downgraded packages /*{{{*/
349// ---------------------------------------------------------------------
350/* */
351bool ShowDowngraded(ostream &out,CacheFile &Cache)
352{
353 string List;
354 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
355 {
356 pkgCache::PkgIterator I(Cache,Cache.List[J]);
357
358 // Not interesting
359 if (Cache[I].Downgrade() == false || Cache[I].NewInstall() == true)
360 continue;
361
362 List += string(I.Name()) + " ";
363 }
364 return ShowList(out,_("The following packages will be DOWNGRADED"),List);
365}
366 /*}}}*/
367// ShowHold - Show held but changed packages /*{{{*/
368// ---------------------------------------------------------------------
369/* */
370bool ShowHold(ostream &out,CacheFile &Cache)
371{
372 string List;
373 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
374 {
375 pkgCache::PkgIterator I(Cache,Cache.List[J]);
376 if (Cache[I].InstallVer != (pkgCache::Version *)I.CurrentVer() &&
377 I->SelectedState == pkgCache::State::Hold)
378 List += string(I.Name()) + " ";
379 }
380
381 return ShowList(out,_("The following held packages will be changed:"),List);
382}
383 /*}}}*/
384// ShowEssential - Show an essential package warning /*{{{*/
385// ---------------------------------------------------------------------
386/* This prints out a warning message that is not to be ignored. It shows
387 all essential packages and their dependents that are to be removed.
388 It is insanely risky to remove the dependents of an essential package! */
389bool ShowEssential(ostream &out,CacheFile &Cache)
390{
391 string List;
392 bool *Added = new bool[Cache->Head().PackageCount];
393 for (unsigned int I = 0; I != Cache->Head().PackageCount; I++)
394 Added[I] = false;
395
396 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
397 {
398 pkgCache::PkgIterator I(Cache,Cache.List[J]);
399 if ((I->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential &&
400 (I->Flags & pkgCache::Flag::Important) != pkgCache::Flag::Important)
401 continue;
402
403 // The essential package is being removed
404 if (Cache[I].Delete() == true)
405 {
406 if (Added[I->ID] == false)
407 {
408 Added[I->ID] = true;
409 List += string(I.Name()) + " ";
410 }
411 }
412
413 if (I->CurrentVer == 0)
414 continue;
415
416 // Print out any essential package depenendents that are to be removed
417 for (pkgCache::DepIterator D = I.CurrentVer().DependsList(); D.end() == false; D++)
418 {
419 // Skip everything but depends
420 if (D->Type != pkgCache::Dep::PreDepends &&
421 D->Type != pkgCache::Dep::Depends)
422 continue;
423
424 pkgCache::PkgIterator P = D.SmartTargetPkg();
425 if (Cache[P].Delete() == true)
426 {
427 if (Added[P->ID] == true)
428 continue;
429 Added[P->ID] = true;
430
431 char S[300];
432 snprintf(S,sizeof(S),_("%s (due to %s) "),P.Name(),I.Name());
433 List += S;
434 }
435 }
436 }
437
438 delete [] Added;
439 return ShowList(out,_("WARNING: The following essential packages will be removed\n"
440 "This should NOT be done unless you know exactly what you are doing!"),List);
441}
442 /*}}}*/
443// Stats - Show some statistics /*{{{*/
444// ---------------------------------------------------------------------
445/* */
446void Stats(ostream &out,pkgDepCache &Dep)
447{
448 unsigned long Upgrade = 0;
449 unsigned long Downgrade = 0;
450 unsigned long Install = 0;
451 unsigned long ReInstall = 0;
452 for (pkgCache::PkgIterator I = Dep.PkgBegin(); I.end() == false; I++)
453 {
454 if (Dep[I].NewInstall() == true)
455 Install++;
456 else
457 {
458 if (Dep[I].Upgrade() == true)
459 Upgrade++;
460 else
461 if (Dep[I].Downgrade() == true)
462 Downgrade++;
463 }
464
465 if (Dep[I].Delete() == false && (Dep[I].iFlags & pkgDepCache::ReInstall) == pkgDepCache::ReInstall)
466 ReInstall++;
467 }
468
469 ioprintf(out,_("%lu packages upgraded, %lu newly installed, "),
470 Upgrade,Install);
471
472 if (ReInstall != 0)
473 ioprintf(out,_("%lu reinstalled, "),ReInstall);
474 if (Downgrade != 0)
475 ioprintf(out,_("%lu downgraded, "),Downgrade);
476
477 ioprintf(out,_("%lu to remove and %lu not upgraded.\n"),
478 Dep.DelCount(),Dep.KeepCount());
479
480 if (Dep.BadCount() != 0)
481 ioprintf(out,_("%lu packages not fully installed or removed.\n"),
482 Dep.BadCount());
483}
484 /*}}}*/
485
486// CacheFile::NameComp - QSort compare by name /*{{{*/
487// ---------------------------------------------------------------------
488/* */
489pkgCache *CacheFile::SortCache = 0;
490int CacheFile::NameComp(const void *a,const void *b)
491{
492 if (*(pkgCache::Package **)a == 0 || *(pkgCache::Package **)b == 0)
493 return *(pkgCache::Package **)a - *(pkgCache::Package **)b;
494
495 const pkgCache::Package &A = **(pkgCache::Package **)a;
496 const pkgCache::Package &B = **(pkgCache::Package **)b;
497
498 return strcmp(SortCache->StrP + A.Name,SortCache->StrP + B.Name);
499}
500 /*}}}*/
501// CacheFile::Sort - Sort by name /*{{{*/
502// ---------------------------------------------------------------------
503/* */
504void CacheFile::Sort()
505{
506 delete [] List;
507 List = new pkgCache::Package *[Cache->Head().PackageCount];
508 memset(List,0,sizeof(*List)*Cache->Head().PackageCount);
509 pkgCache::PkgIterator I = Cache->PkgBegin();
510 for (;I.end() != true; I++)
511 List[I->ID] = I;
512
513 SortCache = *this;
514 qsort(List,Cache->Head().PackageCount,sizeof(*List),NameComp);
515}
516 /*}}}*/
517// CacheFile::CheckDeps - Open the cache file /*{{{*/
518// ---------------------------------------------------------------------
519/* This routine generates the caches and then opens the dependency cache
520 and verifies that the system is OK. */
521bool CacheFile::CheckDeps(bool AllowBroken)
522{
523 if (_error->PendingError() == true)
524 return false;
525
526 // Check that the system is OK
527 if (DCache->DelCount() != 0 || DCache->InstCount() != 0)
528 return _error->Error("Internal Error, non-zero counts");
529
530 // Apply corrections for half-installed packages
531 if (pkgApplyStatus(*DCache) == false)
532 return false;
533
534 // Nothing is broken
535 if (DCache->BrokenCount() == 0 || AllowBroken == true)
536 return true;
537
538 // Attempt to fix broken things
539 if (_config->FindB("APT::Get::Fix-Broken",false) == true)
540 {
541 c1out << _("Correcting dependencies...") << flush;
542 if (pkgFixBroken(*DCache) == false || DCache->BrokenCount() != 0)
543 {
544 c1out << _(" failed.") << endl;
545 ShowBroken(c1out,*this,true);
546
547 return _error->Error(_("Unable to correct dependencies"));
548 }
549 if (pkgMinimizeUpgrade(*DCache) == false)
550 return _error->Error(_("Unable to minimize the upgrade set"));
551
552 c1out << _(" Done") << endl;
553 }
554 else
555 {
556 c1out << _("You might want to run `apt-get -f install' to correct these.") << endl;
557 ShowBroken(c1out,*this,true);
558
559 return _error->Error(_("Unmet dependencies. Try using -f."));
560 }
561
562 return true;
563}
564 /*}}}*/
565
566// InstallPackages - Actually download and install the packages /*{{{*/
567// ---------------------------------------------------------------------
568/* This displays the informative messages describing what is going to
569 happen and then calls the download routines */
570bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
571 bool Saftey = true)
572{
573 if (_config->FindB("APT::Get::Purge",false) == true)
574 {
575 pkgCache::PkgIterator I = Cache->PkgBegin();
576 for (; I.end() == false; I++)
577 {
578 if (I.Purge() == false && Cache[I].Mode == pkgDepCache::ModeDelete)
579 Cache->MarkDelete(I,true);
580 }
581 }
582
583 bool Fail = false;
584 bool Essential = false;
585
586 // Show all the various warning indicators
587 ShowDel(c1out,Cache);
588 ShowNew(c1out,Cache);
589 if (ShwKept == true)
590 ShowKept(c1out,Cache);
591 Fail |= !ShowHold(c1out,Cache);
592 if (_config->FindB("APT::Get::Show-Upgraded",false) == true)
593 ShowUpgraded(c1out,Cache);
594 Fail |= !ShowDowngraded(c1out,Cache);
595 Essential = !ShowEssential(c1out,Cache);
596 Fail |= Essential;
597 Stats(c1out,Cache);
598
599 // Sanity check
600 if (Cache->BrokenCount() != 0)
601 {
602 ShowBroken(c1out,Cache,false);
603 return _error->Error("Internal Error, InstallPackages was called with broken packages!");
604 }
605
606 if (Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
607 Cache->BadCount() == 0)
608 return true;
609
610 // No remove flag
611 if (Cache->DelCount() != 0 && _config->FindB("APT::Get::Remove",true) == false)
612 return _error->Error(_("Packages need to be removed but Remove is disabled."));
613
614 // Run the simulator ..
615 if (_config->FindB("APT::Get::Simulate") == true)
616 {
617 pkgSimulate PM(Cache);
618 pkgPackageManager::OrderResult Res = PM.DoInstall();
619 if (Res == pkgPackageManager::Failed)
620 return false;
621 if (Res != pkgPackageManager::Completed)
622 return _error->Error("Internal Error, Ordering didn't finish");
623 return true;
624 }
625
626 // Create the text record parser
627 pkgRecords Recs(Cache);
628 if (_error->PendingError() == true)
629 return false;
630
631 // Lock the archive directory
632 FileFd Lock;
633 if (_config->FindB("Debug::NoLocking",false) == false)
634 {
635 Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
636 if (_error->PendingError() == true)
637 return _error->Error(_("Unable to lock the download directory"));
638 }
639
640 // Create the download object
641 AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
642 pkgAcquire Fetcher(&Stat);
643
644 // Read the source list
645 pkgSourceList List;
646 if (List.ReadMainList() == false)
647 return _error->Error(_("The list of sources could not be read."));
648
649 // Create the package manager and prepare to download
650 SPtr<pkgPackageManager> PM= _system->CreatePM(Cache);
651 if (PM->GetArchives(&Fetcher,&List,&Recs) == false ||
652 _error->PendingError() == true)
653 return false;
654
655 // Display statistics
656 double FetchBytes = Fetcher.FetchNeeded();
657 double FetchPBytes = Fetcher.PartialPresent();
658 double DebBytes = Fetcher.TotalNeeded();
659 if (DebBytes != Cache->DebSize())
660 {
661 c0out << DebBytes << ',' << Cache->DebSize() << endl;
662 c0out << "How odd.. The sizes didn't match, email apt@packages.debian.org" << endl;
663 }
664
665 // Number of bytes
666 if (DebBytes != FetchBytes)
667 ioprintf(c1out,_("Need to get %sB/%sB of archives. "),
668 SizeToStr(FetchBytes).c_str(),SizeToStr(DebBytes).c_str());
669 else
670 ioprintf(c1out,_("Need to get %sB of archives. "),
671 SizeToStr(DebBytes).c_str());
672
673 // Size delta
674 if (Cache->UsrSize() >= 0)
675 ioprintf(c1out,_("After unpacking %sB will be used.\n"),
676 SizeToStr(Cache->UsrSize()).c_str());
677 else
678 ioprintf(c1out,_("After unpacking %sB will be freed.\n"),
679 SizeToStr(-1*Cache->UsrSize()).c_str());
680
681 if (_error->PendingError() == true)
682 return false;
683
684 /* Check for enough free space, but only if we are actually going to
685 download */
686 if (_config->FindB("APT::Get::Print-URIs") == false)
687 {
688 struct statvfs Buf;
689 string OutputDir = _config->FindDir("Dir::Cache::Archives");
690 if (statvfs(OutputDir.c_str(),&Buf) != 0)
691 return _error->Errno("statvfs","Couldn't determine free space in %s",
692 OutputDir.c_str());
693 if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
694 return _error->Error(_("Sorry, you don't have enough free space in %s to hold all the .debs."),
695 OutputDir.c_str());
696 }
697
698 // Fail safe check
699 if (_config->FindI("quiet",0) >= 2 ||
700 _config->FindB("APT::Get::Assume-Yes",false) == true)
701 {
702 if (Fail == true && _config->FindB("APT::Get::Force-Yes",false) == false)
703 return _error->Error(_("There are problems and -y was used without --force-yes"));
704 }
705
706 if (Essential == true && Saftey == true)
707 {
708 if (_config->FindB("APT::Get::Trivial-Only",false) == true)
709 return _error->Error(_("Trivial Only specified but this is not a trivial operation."));
710
711 const char *Prompt = _("Yes, do as I say!");
712 ioprintf(c2out,
713 _("You are about to do something potentially harmful\n"
714 "To continue type in the phrase '%s'\n"
715 " ?] "),Prompt);
716 c2out << flush;
717 if (AnalPrompt(Prompt) == false)
718 {
719 c2out << _("Abort.") << endl;
720 exit(1);
721 }
722 }
723 else
724 {
725 // Prompt to continue
726 if (Ask == true || Fail == true)
727 {
728 if (_config->FindB("APT::Get::Trivial-Only",false) == true)
729 return _error->Error(_("Trivial Only specified but this is not a trivial operation."));
730
731 if (_config->FindI("quiet",0) < 2 &&
732 _config->FindB("APT::Get::Assume-Yes",false) == false)
733 {
734 c2out << _("Do you want to continue? [Y/n] ") << flush;
735
736 if (YnPrompt() == false)
737 {
738 c2out << _("Abort.") << endl;
739 exit(1);
740 }
741 }
742 }
743 }
744
745 // Just print out the uris an exit if the --print-uris flag was used
746 if (_config->FindB("APT::Get::Print-URIs") == true)
747 {
748 pkgAcquire::UriIterator I = Fetcher.UriBegin();
749 for (; I != Fetcher.UriEnd(); I++)
750 cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' <<
751 I->Owner->FileSize << ' ' << I->Owner->MD5Sum() << endl;
752 return true;
753 }
754
755 /* Unlock the dpkg lock if we are not going to be doing an install
756 after. */
757 if (_config->FindB("APT::Get::Download-Only",false) == true)
758 _system->UnLock();
759
760 // Run it
761 while (1)
762 {
763 bool Transient = false;
764 if (_config->FindB("APT::Get::Download",true) == false)
765 {
766 for (pkgAcquire::Item **I = Fetcher.ItemsBegin(); I < Fetcher.ItemsEnd();)
767 {
768 if ((*I)->Local == true)
769 {
770 I++;
771 continue;
772 }
773
774 // Close the item and check if it was found in cache
775 (*I)->Finished();
776 if ((*I)->Complete == false)
777 Transient = true;
778
779 // Clear it out of the fetch list
780 delete *I;
781 I = Fetcher.ItemsBegin();
782 }
783 }
784
785 if (Fetcher.Run() == pkgAcquire::Failed)
786 return false;
787
788 // Print out errors
789 bool Failed = false;
790 for (pkgAcquire::Item **I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
791 {
792 if ((*I)->Status == pkgAcquire::Item::StatDone &&
793 (*I)->Complete == true)
794 continue;
795
796 if ((*I)->Status == pkgAcquire::Item::StatIdle)
797 {
798 Transient = true;
799 // Failed = true;
800 continue;
801 }
802
803 fprintf(stderr,_("Failed to fetch %s %s\n"),(*I)->DescURI().c_str(),
804 (*I)->ErrorText.c_str());
805 Failed = true;
806 }
807
808 /* If we are in no download mode and missing files and there were
809 'failures' then the user must specify -m. Furthermore, there
810 is no such thing as a transient error in no-download mode! */
811 if (Transient == true &&
812 _config->FindB("APT::Get::Download",true) == false)
813 {
814 Transient = false;
815 Failed = true;
816 }
817
818 if (_config->FindB("APT::Get::Download-Only",false) == true)
819 {
820 if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
821 return _error->Error(_("Some files failed to download"));
822 c1out << _("Download complete and in download only mode") << endl;
823 return true;
824 }
825
826 if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
827 {
828 return _error->Error(_("Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?"));
829 }
830
831 if (Transient == true && Failed == true)
832 return _error->Error(_("--fix-missing and media swapping is not currently supported"));
833
834 // Try to deal with missing package files
835 if (Failed == true && PM->FixMissing() == false)
836 {
837 cerr << _("Unable to correct missing packages.") << endl;
838 return _error->Error(_("Aborting Install."));
839 }
840
841 _system->UnLock();
842 pkgPackageManager::OrderResult Res = PM->DoInstall();
843 if (Res == pkgPackageManager::Failed || _error->PendingError() == true)
844 return false;
845 if (Res == pkgPackageManager::Completed)
846 return true;
847
848 // Reload the fetcher object and loop again for media swapping
849 Fetcher.Shutdown();
850 if (PM->GetArchives(&Fetcher,&List,&Recs) == false)
851 return false;
852
853 _system->Lock();
854 }
855}
856 /*}}}*/
857// TryToInstall - Try to install a single package /*{{{*/
858// ---------------------------------------------------------------------
859/* This used to be inlined in DoInstall, but with the advent of regex package
860 name matching it was split out.. */
861bool TryToInstall(pkgCache::PkgIterator Pkg,pkgDepCache &Cache,
862 pkgProblemResolver &Fix,bool Remove,bool BrokenFix,
863 unsigned int &ExpectedInst,bool AllowFail = true)
864{
865 /* This is a pure virtual package and there is a single available
866 provides */
867 if (Cache[Pkg].CandidateVer == 0 && Pkg->ProvidesList != 0 &&
868 Pkg.ProvidesList()->NextProvides == 0)
869 {
870 pkgCache::PkgIterator Tmp = Pkg.ProvidesList().OwnerPkg();
871 ioprintf(c1out,_("Note, selecting %s instead of %s\n"),
872 Tmp.Name(),Pkg.Name());
873 Pkg = Tmp;
874 }
875
876 // Handle the no-upgrade case
877 if (_config->FindB("APT::Get::upgrade",true) == false &&
878 Pkg->CurrentVer != 0)
879 {
880 if (AllowFail == true)
881 ioprintf(c1out,_("Skipping %s, it is already installed and upgrade is not set.\n"),
882 Pkg.Name());
883 return true;
884 }
885
886 // Check if there is something at all to install
887 pkgDepCache::StateCache &State = Cache[Pkg];
888 if (Remove == true && Pkg->CurrentVer == 0)
889 {
890 /* We want to continue searching for regex hits, so we return false here
891 otherwise this is not really an error. */
892 if (AllowFail == false)
893 return false;
894 ioprintf(c1out,_("Package %s is not installed, so not removed\n"),Pkg.Name());
895 return true;
896 }
897
898 if (State.CandidateVer == 0 && Remove == false)
899 {
900 if (AllowFail == false)
901 return false;
902
903 if (Pkg->ProvidesList != 0)
904 {
905 ioprintf(c1out,_("Package %s is a virtual package provided by:\n"),
906 Pkg.Name());
907
908 pkgCache::PrvIterator I = Pkg.ProvidesList();
909 for (; I.end() == false; I++)
910 {
911 pkgCache::PkgIterator Pkg = I.OwnerPkg();
912
913 if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer())
914 {
915 if (Cache[Pkg].Install() == true && Cache[Pkg].NewInstall() == false)
916 c1out << " " << Pkg.Name() << " " << I.OwnerVer().VerStr() <<
917 _(" [Installed]") << endl;
918 else
919 c1out << " " << Pkg.Name() << " " << I.OwnerVer().VerStr() << endl;
920 }
921 }
922 c1out << _("You should explicitly select one to install.") << endl;
923 }
924 else
925 {
926 ioprintf(c1out,
927 _("Package %s has no available version, but exists in the database.\n"
928 "This typically means that the package was mentioned in a dependency and\n"
929 "never uploaded, has been obsoleted or is not available with the contents\n"
930 "of sources.list\n"),Pkg.Name());
931
932 string List;
933 SPtrArray<bool> Seen = new bool[Cache.Head().PackageCount];
934 memset(Seen,0,Cache.Head().PackageCount*sizeof(*Seen));
935 pkgCache::DepIterator Dep = Pkg.RevDependsList();
936 for (; Dep.end() == false; Dep++)
937 {
938 if (Dep->Type != pkgCache::Dep::Replaces)
939 continue;
940 if (Seen[Dep.ParentPkg()->ID] == true)
941 continue;
942 Seen[Dep.ParentPkg()->ID] = true;
943 List += string(Dep.ParentPkg().Name()) + " ";
944 }
945 ShowList(c1out,_("However the following packages replace it:"),List);
946 }
947
948 _error->Error(_("Package %s has no installation candidate"),Pkg.Name());
949 return false;
950 }
951
952 Fix.Clear(Pkg);
953 Fix.Protect(Pkg);
954 if (Remove == true)
955 {
956 Fix.Remove(Pkg);
957 Cache.MarkDelete(Pkg,_config->FindB("APT::Get::Purge",false));
958 return true;
959 }
960
961 // Install it
962 Cache.MarkInstall(Pkg,false);
963 if (State.Install() == false)
964 {
965 if (_config->FindB("APT::Get::ReInstall",false) == true)
966 {
967 if (Pkg->CurrentVer == 0 || Pkg.CurrentVer().Downloadable() == false)
968 ioprintf(c1out,_("Sorry, re-installation of %s is not possible, it cannot be downloaded."),
969 Pkg.Name());
970 else
971 Cache.SetReInstall(Pkg,true);
972 }
973 else
974 {
975 if (AllowFail == true)
976 ioprintf(c1out,_("Sorry, %s is already the newest version.\n"),
977 Pkg.Name());
978 }
979 }
980 else
981 ExpectedInst++;
982
983 // Install it with autoinstalling enabled.
984 if (State.InstBroken() == true && BrokenFix == false)
985 Cache.MarkInstall(Pkg,true);
986 return true;
987}
988 /*}}}*/
989// TryToChangeVer - Try to change a candidate version /*{{{*/
990// ---------------------------------------------------------------------
991/* */
992bool TryToChangeVer(pkgCache::PkgIterator Pkg,pkgDepCache &Cache,
993 const char *VerTag,bool IsRel)
994{
995 pkgVersionMatch Match(VerTag,(IsRel == true?pkgVersionMatch::Release:pkgVersionMatch::Version));
996
997 pkgCache::VerIterator Ver = Match.Find(Pkg);
998
999 if (Ver.end() == true)
1000 {
1001 if (IsRel == true)
1002 return _error->Error(_("Release '%s' for '%s' was not found"),
1003 VerTag,Pkg.Name());
1004 return _error->Error(_("Version '%s' for '%s' was not found"),
1005 VerTag,Pkg.Name());
1006 }
1007
1008 if (strcmp(VerTag,Ver.VerStr()) != 0)
1009 {
1010 ioprintf(c1out,_("Selected version %s (%s) for %s\n"),
1011 Ver.VerStr(),Ver.RelStr().c_str(),Pkg.Name());
1012 }
1013
1014 Cache.SetCandidateVersion(Ver);
1015 return true;
1016}
1017 /*}}}*/
1018// FindSrc - Find a source record /*{{{*/
1019// ---------------------------------------------------------------------
1020/* */
1021pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs,
1022 pkgSrcRecords &SrcRecs,string &Src,
1023 pkgDepCache &Cache)
1024{
1025 // We want to pull the version off the package specification..
1026 string VerTag;
1027 string TmpSrc = Name;
1028 string::size_type Slash = TmpSrc.rfind('=');
1029 if (Slash != string::npos)
1030 {
1031 VerTag = string(TmpSrc.begin() + Slash + 1,TmpSrc.end());
1032 TmpSrc = string(TmpSrc.begin(),TmpSrc.begin() + Slash);
1033 }
1034
1035 /* Lookup the version of the package we would install if we were to
1036 install a version and determine the source package name, then look
1037 in the archive for a source package of the same name. In theory
1038 we could stash the version string as well and match that too but
1039 today there aren't multi source versions in the archive. */
1040 if (_config->FindB("APT::Get::Only-Source") == false &&
1041 VerTag.empty() == true)
1042 {
1043 pkgCache::PkgIterator Pkg = Cache.FindPkg(TmpSrc);
1044 if (Pkg.end() == false)
1045 {
1046 pkgCache::VerIterator Ver = Cache.GetCandidateVer(Pkg);
1047 if (Ver.end() == false)
1048 {
1049 pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList());
1050 Src = Parse.SourcePkg();
1051 }
1052 }
1053 }
1054
1055 // No source package name..
1056 if (Src.empty() == true)
1057 Src = TmpSrc;
1058
1059 // The best hit
1060 pkgSrcRecords::Parser *Last = 0;
1061 unsigned long Offset = 0;
1062 string Version;
1063 bool IsMatch = false;
1064
1065 // If we are matching by version then we need exact matches to be happy
1066 if (VerTag.empty() == false)
1067 IsMatch = true;
1068
1069 /* Iterate over all of the hits, which includes the resulting
1070 binary packages in the search */
1071 pkgSrcRecords::Parser *Parse;
1072 SrcRecs.Restart();
1073 while ((Parse = SrcRecs.Find(Src.c_str(),false)) != 0)
1074 {
1075 string Ver = Parse->Version();
1076
1077 // Skip name mismatches
1078 if (IsMatch == true && Parse->Package() != Src)
1079 continue;
1080
1081 if (VerTag.empty() == false)
1082 {
1083 /* Don't want to fall through because we are doing exact version
1084 matching. */
1085 if (Cache.VS().CmpVersion(VerTag,Ver) != 0)
1086 continue;
1087
1088 Last = Parse;
1089 Offset = Parse->Offset();
1090 break;
1091 }
1092
1093 // Newer version or an exact match
1094 if (Last == 0 || Cache.VS().CmpVersion(Version,Ver) < 0 ||
1095 (Parse->Package() == Src && IsMatch == false))
1096 {
1097 IsMatch = Parse->Package() == Src;
1098 Last = Parse;
1099 Offset = Parse->Offset();
1100 Version = Ver;
1101 }
1102 }
1103
1104 if (Last == 0)
1105 return 0;
1106
1107 if (Last->Jump(Offset) == false)
1108 return 0;
1109
1110 return Last;
1111}
1112 /*}}}*/
1113
1114// DoUpdate - Update the package lists /*{{{*/
1115// ---------------------------------------------------------------------
1116/* */
1117bool DoUpdate(CommandLine &CmdL)
1118{
1119 if (CmdL.FileSize() != 1)
1120 return _error->Error(_("The update command takes no arguments"));
1121
1122 // Get the source list
1123 pkgSourceList List;
1124 if (List.ReadMainList() == false)
1125 return false;
1126
1127 // Lock the list directory
1128 FileFd Lock;
1129 if (_config->FindB("Debug::NoLocking",false) == false)
1130 {
1131 Lock.Fd(GetLock(_config->FindDir("Dir::State::Lists") + "lock"));
1132 if (_error->PendingError() == true)
1133 return _error->Error(_("Unable to lock the list directory"));
1134 }
1135
1136 // Create the download object
1137 AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
1138 pkgAcquire Fetcher(&Stat);
1139
1140 // Populate it with the source selection
1141 if (List.GetIndexes(&Fetcher) == false)
1142 return false;
1143
1144 // Run it
1145 if (Fetcher.Run() == pkgAcquire::Failed)
1146 return false;
1147
1148 bool Failed = false;
1149 for (pkgAcquire::Item **I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
1150 {
1151 if ((*I)->Status == pkgAcquire::Item::StatDone)
1152 continue;
1153
1154 (*I)->Finished();
1155
1156 fprintf(stderr,_("Failed to fetch %s %s\n"),(*I)->DescURI().c_str(),
1157 (*I)->ErrorText.c_str());
1158 Failed = true;
1159 }
1160
1161 // Clean out any old list files
1162 if (_config->FindB("APT::Get::List-Cleanup",true) == true)
1163 {
1164 if (Fetcher.Clean(_config->FindDir("Dir::State::lists")) == false ||
1165 Fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/") == false)
1166 return false;
1167 }
1168
1169 // Prepare the cache.
1170 CacheFile Cache;
1171 if (Cache.Open() == false)
1172 return false;
1173
1174 if (Failed == true)
1175 return _error->Error(_("Some index files failed to download, they have been ignored, or old ones used instead."));
1176
1177 return true;
1178}
1179 /*}}}*/
1180// DoUpgrade - Upgrade all packages /*{{{*/
1181// ---------------------------------------------------------------------
1182/* Upgrade all packages without installing new packages or erasing old
1183 packages */
1184bool DoUpgrade(CommandLine &CmdL)
1185{
1186 CacheFile Cache;
1187 if (Cache.Open() == false || Cache.CheckDeps() == false)
1188 return false;
1189
1190 // Do the upgrade
1191 if (pkgAllUpgrade(Cache) == false)
1192 {
1193 ShowBroken(c1out,Cache,false);
1194 return _error->Error(_("Internal Error, AllUpgrade broke stuff"));
1195 }
1196
1197 return InstallPackages(Cache,true);
1198}
1199 /*}}}*/
1200// DoInstall - Install packages from the command line /*{{{*/
1201// ---------------------------------------------------------------------
1202/* Install named packages */
1203bool DoInstall(CommandLine &CmdL)
1204{
1205 CacheFile Cache;
1206 if (Cache.Open() == false || Cache.CheckDeps(CmdL.FileSize() != 1) == false)
1207 return false;
1208
1209 // Enter the special broken fixing mode if the user specified arguments
1210 bool BrokenFix = false;
1211 if (Cache->BrokenCount() != 0)
1212 BrokenFix = true;
1213
1214 unsigned int ExpectedInst = 0;
1215 unsigned int Packages = 0;
1216 pkgProblemResolver Fix(Cache);
1217
1218 bool DefRemove = false;
1219 if (strcasecmp(CmdL.FileList[0],"remove") == 0)
1220 DefRemove = true;
1221
1222 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1223 {
1224 // Duplicate the string
1225 unsigned int Length = strlen(*I);
1226 char S[300];
1227 if (Length >= sizeof(S))
1228 continue;
1229 strcpy(S,*I);
1230
1231 // See if we are removing and special indicators..
1232 bool Remove = DefRemove;
1233 char *VerTag = 0;
1234 bool VerIsRel = false;
1235 while (Cache->FindPkg(S).end() == true)
1236 {
1237 // Handle an optional end tag indicating what to do
1238 if (S[Length - 1] == '-')
1239 {
1240 Remove = true;
1241 S[--Length] = 0;
1242 continue;
1243 }
1244
1245 if (S[Length - 1] == '+')
1246 {
1247 Remove = false;
1248 S[--Length] = 0;
1249 continue;
1250 }
1251
1252 char *Slash = strchr(S,'=');
1253 if (Slash != 0)
1254 {
1255 VerIsRel = false;
1256 *Slash = 0;
1257 VerTag = Slash + 1;
1258 }
1259
1260 Slash = strchr(S,'/');
1261 if (Slash != 0)
1262 {
1263 VerIsRel = true;
1264 *Slash = 0;
1265 VerTag = Slash + 1;
1266 }
1267
1268 break;
1269 }
1270
1271 // Locate the package
1272 pkgCache::PkgIterator Pkg = Cache->FindPkg(S);
1273 Packages++;
1274 if (Pkg.end() == true)
1275 {
1276 // Check if the name is a regex
1277 const char *I;
1278 for (I = S; *I != 0; I++)
1279 if (*I == '.' || *I == '?' || *I == '*' || *I == '|')
1280 break;
1281 if (*I == 0)
1282 return _error->Error(_("Couldn't find package %s"),S);
1283
1284 // Regexs must always be confirmed
1285 ExpectedInst += 1000;
1286
1287 // Compile the regex pattern
1288 regex_t Pattern;
1289 int Res;
1290 if ((Res = regcomp(&Pattern,S,REG_EXTENDED | REG_ICASE |
1291 REG_NOSUB)) != 0)
1292 {
1293 char Error[300];
1294 regerror(Res,&Pattern,Error,sizeof(Error));
1295 return _error->Error(_("Regex compilation error - %s"),Error);
1296 }
1297
1298 // Run over the matches
1299 bool Hit = false;
1300 for (Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
1301 {
1302 if (regexec(&Pattern,Pkg.Name(),0,0,0) != 0)
1303 continue;
1304
1305 if (VerTag != 0)
1306 if (TryToChangeVer(Pkg,Cache,VerTag,VerIsRel) == false)
1307 return false;
1308
1309 Hit |= TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix,
1310 ExpectedInst,false);
1311 }
1312 regfree(&Pattern);
1313
1314 if (Hit == false)
1315 return _error->Error(_("Couldn't find package %s"),S);
1316 }
1317 else
1318 {
1319 if (VerTag != 0)
1320 if (TryToChangeVer(Pkg,Cache,VerTag,VerIsRel) == false)
1321 return false;
1322 if (TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix,ExpectedInst) == false)
1323 return false;
1324 }
1325 }
1326
1327 /* If we are in the Broken fixing mode we do not attempt to fix the
1328 problems. This is if the user invoked install without -f and gave
1329 packages */
1330 if (BrokenFix == true && Cache->BrokenCount() != 0)
1331 {
1332 c1out << _("You might want to run `apt-get -f install' to correct these:") << endl;
1333 ShowBroken(c1out,Cache,false);
1334
1335 return _error->Error(_("Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution)."));
1336 }
1337
1338 // Call the scored problem resolver
1339 Fix.InstallProtect();
1340 if (Fix.Resolve(true) == false)
1341 _error->Discard();
1342
1343 // Now we check the state of the packages,
1344 if (Cache->BrokenCount() != 0)
1345 {
1346 c1out <<
1347 _("Some packages could not be installed. This may mean that you have\n"
1348 "requested an impossible situation or if you are using the unstable\n"
1349 "distribution that some required packages have not yet been created\n"
1350 "or been moved out of Incoming.") << endl;
1351 if (Packages == 1)
1352 {
1353 c1out << endl;
1354 c1out <<
1355 _("Since you only requested a single operation it is extremely likely that\n"
1356 "the package is simply not installable and a bug report against\n"
1357 "that package should be filed.") << endl;
1358 }
1359
1360 c1out << _("The following information may help to resolve the situation:") << endl;
1361 c1out << endl;
1362 ShowBroken(c1out,Cache,false);
1363 return _error->Error(_("Sorry, broken packages"));
1364 }
1365
1366 /* Print out a list of packages that are going to be installed extra
1367 to what the user asked */
1368 if (Cache->InstCount() != ExpectedInst)
1369 {
1370 string List;
1371 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
1372 {
1373 pkgCache::PkgIterator I(Cache,Cache.List[J]);
1374 if ((*Cache)[I].Install() == false)
1375 continue;
1376
1377 const char **J;
1378 for (J = CmdL.FileList + 1; *J != 0; J++)
1379 if (strcmp(*J,I.Name()) == 0)
1380 break;
1381
1382 if (*J == 0)
1383 List += string(I.Name()) + " ";
1384 }
1385
1386 ShowList(c1out,_("The following extra packages will be installed:"),List);
1387 }
1388
1389 // See if we need to prompt
1390 if (Cache->InstCount() == ExpectedInst && Cache->DelCount() == 0)
1391 return InstallPackages(Cache,false,false);
1392
1393 return InstallPackages(Cache,false);
1394}
1395 /*}}}*/
1396// DoDistUpgrade - Automatic smart upgrader /*{{{*/
1397// ---------------------------------------------------------------------
1398/* Intelligent upgrader that will install and remove packages at will */
1399bool DoDistUpgrade(CommandLine &CmdL)
1400{
1401 CacheFile Cache;
1402 if (Cache.Open() == false || Cache.CheckDeps() == false)
1403 return false;
1404
1405 c0out << _("Calculating Upgrade... ") << flush;
1406 if (pkgDistUpgrade(*Cache) == false)
1407 {
1408 c0out << _("Failed") << endl;
1409 ShowBroken(c1out,Cache,false);
1410 return false;
1411 }
1412
1413 c0out << _("Done") << endl;
1414
1415 return InstallPackages(Cache,true);
1416}
1417 /*}}}*/
1418// DoDSelectUpgrade - Do an upgrade by following dselects selections /*{{{*/
1419// ---------------------------------------------------------------------
1420/* Follows dselect's selections */
1421bool DoDSelectUpgrade(CommandLine &CmdL)
1422{
1423 CacheFile Cache;
1424 if (Cache.Open() == false || Cache.CheckDeps() == false)
1425 return false;
1426
1427 // Install everything with the install flag set
1428 pkgCache::PkgIterator I = Cache->PkgBegin();
1429 for (;I.end() != true; I++)
1430 {
1431 /* Install the package only if it is a new install, the autoupgrader
1432 will deal with the rest */
1433 if (I->SelectedState == pkgCache::State::Install)
1434 Cache->MarkInstall(I,false);
1435 }
1436
1437 /* Now install their deps too, if we do this above then order of
1438 the status file is significant for | groups */
1439 for (I = Cache->PkgBegin();I.end() != true; I++)
1440 {
1441 /* Install the package only if it is a new install, the autoupgrader
1442 will deal with the rest */
1443 if (I->SelectedState == pkgCache::State::Install)
1444 Cache->MarkInstall(I,true);
1445 }
1446
1447 // Apply erasures now, they override everything else.
1448 for (I = Cache->PkgBegin();I.end() != true; I++)
1449 {
1450 // Remove packages
1451 if (I->SelectedState == pkgCache::State::DeInstall ||
1452 I->SelectedState == pkgCache::State::Purge)
1453 Cache->MarkDelete(I,I->SelectedState == pkgCache::State::Purge);
1454 }
1455
1456 /* Resolve any problems that dselect created, allupgrade cannot handle
1457 such things. We do so quite agressively too.. */
1458 if (Cache->BrokenCount() != 0)
1459 {
1460 pkgProblemResolver Fix(Cache);
1461
1462 // Hold back held packages.
1463 if (_config->FindB("APT::Ignore-Hold",false) == false)
1464 {
1465 for (pkgCache::PkgIterator I = Cache->PkgBegin(); I.end() == false; I++)
1466 {
1467 if (I->SelectedState == pkgCache::State::Hold)
1468 {
1469 Fix.Protect(I);
1470 Cache->MarkKeep(I);
1471 }
1472 }
1473 }
1474
1475 if (Fix.Resolve() == false)
1476 {
1477 ShowBroken(c1out,Cache,false);
1478 return _error->Error("Internal Error, problem resolver broke stuff");
1479 }
1480 }
1481
1482 // Now upgrade everything
1483 if (pkgAllUpgrade(Cache) == false)
1484 {
1485 ShowBroken(c1out,Cache,false);
1486 return _error->Error("Internal Error, problem resolver broke stuff");
1487 }
1488
1489 return InstallPackages(Cache,false);
1490}
1491 /*}}}*/
1492// DoClean - Remove download archives /*{{{*/
1493// ---------------------------------------------------------------------
1494/* */
1495bool DoClean(CommandLine &CmdL)
1496{
1497 if (_config->FindB("APT::Get::Simulate") == true)
1498 {
1499 cout << "Del " << _config->FindDir("Dir::Cache::archives") << "* " <<
1500 _config->FindDir("Dir::Cache::archives") << "partial/*" << endl;
1501 return true;
1502 }
1503
1504 // Lock the archive directory
1505 FileFd Lock;
1506 if (_config->FindB("Debug::NoLocking",false) == false)
1507 {
1508 Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
1509 if (_error->PendingError() == true)
1510 return _error->Error(_("Unable to lock the download directory"));
1511 }
1512
1513 pkgAcquire Fetcher;
1514 Fetcher.Clean(_config->FindDir("Dir::Cache::archives"));
1515 Fetcher.Clean(_config->FindDir("Dir::Cache::archives") + "partial/");
1516 return true;
1517}
1518 /*}}}*/
1519// DoAutoClean - Smartly remove downloaded archives /*{{{*/
1520// ---------------------------------------------------------------------
1521/* This is similar to clean but it only purges things that cannot be
1522 downloaded, that is old versions of cached packages. */
1523class LogCleaner : public pkgArchiveCleaner
1524{
1525 protected:
1526 virtual void Erase(const char *File,string Pkg,string Ver,struct stat &St)
1527 {
1528 c1out << "Del " << Pkg << " " << Ver << " [" << SizeToStr(St.st_size) << "B]" << endl;
1529
1530 if (_config->FindB("APT::Get::Simulate") == false)
1531 unlink(File);
1532 };
1533};
1534
1535bool DoAutoClean(CommandLine &CmdL)
1536{
1537 // Lock the archive directory
1538 FileFd Lock;
1539 if (_config->FindB("Debug::NoLocking",false) == false)
1540 {
1541 Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
1542 if (_error->PendingError() == true)
1543 return _error->Error(_("Unable to lock the download directory"));
1544 }
1545
1546 CacheFile Cache;
1547 if (Cache.Open() == false)
1548 return false;
1549
1550 LogCleaner Cleaner;
1551
1552 return Cleaner.Go(_config->FindDir("Dir::Cache::archives"),*Cache) &&
1553 Cleaner.Go(_config->FindDir("Dir::Cache::archives") + "partial/",*Cache);
1554}
1555 /*}}}*/
1556// DoCheck - Perform the check operation /*{{{*/
1557// ---------------------------------------------------------------------
1558/* Opening automatically checks the system, this command is mostly used
1559 for debugging */
1560bool DoCheck(CommandLine &CmdL)
1561{
1562 CacheFile Cache;
1563 Cache.Open();
1564 Cache.CheckDeps();
1565
1566 return true;
1567}
1568 /*}}}*/
1569// DoSource - Fetch a source archive /*{{{*/
1570// ---------------------------------------------------------------------
1571/* Fetch souce packages */
1572struct DscFile
1573{
1574 string Package;
1575 string Version;
1576 string Dsc;
1577};
1578
1579bool DoSource(CommandLine &CmdL)
1580{
1581 CacheFile Cache;
1582 if (Cache.Open(false) == false)
1583 return false;
1584
1585 if (CmdL.FileSize() <= 1)
1586 return _error->Error(_("Must specify at least one package to fetch source for"));
1587
1588 // Read the source list
1589 pkgSourceList List;
1590 if (List.ReadMainList() == false)
1591 return _error->Error(_("The list of sources could not be read."));
1592
1593 // Create the text record parsers
1594 pkgRecords Recs(Cache);
1595 pkgSrcRecords SrcRecs(List);
1596 if (_error->PendingError() == true)
1597 return false;
1598
1599 // Create the download object
1600 AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
1601 pkgAcquire Fetcher(&Stat);
1602
1603 DscFile *Dsc = new DscFile[CmdL.FileSize()];
1604
1605 // Load the requestd sources into the fetcher
1606 unsigned J = 0;
1607 for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++)
1608 {
1609 string Src;
1610 pkgSrcRecords::Parser *Last = FindSrc(*I,Recs,SrcRecs,Src,*Cache);
1611
1612 if (Last == 0)
1613 return _error->Error(_("Unable to find a source package for %s"),Src.c_str());
1614
1615 // Back track
1616 vector<pkgSrcRecords::File> Lst;
1617 if (Last->Files(Lst) == false)
1618 return false;
1619
1620 // Load them into the fetcher
1621 for (vector<pkgSrcRecords::File>::const_iterator I = Lst.begin();
1622 I != Lst.end(); I++)
1623 {
1624 // Try to guess what sort of file it is we are getting.
1625 if (I->Type == "dsc")
1626 {
1627 Dsc[J].Package = Last->Package();
1628 Dsc[J].Version = Last->Version();
1629 Dsc[J].Dsc = flNotDir(I->Path);
1630 }
1631
1632 // Diff only mode only fetches .diff files
1633 if (_config->FindB("APT::Get::Diff-Only",false) == true &&
1634 I->Type != "diff")
1635 continue;
1636
1637 // Tar only mode only fetches .tar files
1638 if (_config->FindB("APT::Get::Tar-Only",false) == true &&
1639 I->Type != "tar")
1640 continue;
1641
1642 new pkgAcqFile(&Fetcher,Last->Index().ArchiveURI(I->Path),
1643 I->MD5Hash,I->Size,
1644 Last->Index().SourceInfo(*Last,*I),Src);
1645 }
1646 }
1647
1648 // Display statistics
1649 double FetchBytes = Fetcher.FetchNeeded();
1650 double FetchPBytes = Fetcher.PartialPresent();
1651 double DebBytes = Fetcher.TotalNeeded();
1652
1653 // Check for enough free space
1654 struct statvfs Buf;
1655 string OutputDir = ".";
1656 if (statvfs(OutputDir.c_str(),&Buf) != 0)
1657 return _error->Errno("statvfs","Couldn't determine free space in %s",
1658 OutputDir.c_str());
1659 if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
1660 return _error->Error(_("Sorry, you don't have enough free space in %s"),
1661 OutputDir.c_str());
1662
1663 // Number of bytes
1664 if (DebBytes != FetchBytes)
1665 ioprintf(c1out,_("Need to get %sB/%sB of source archives.\n"),
1666 SizeToStr(FetchBytes).c_str(),SizeToStr(DebBytes).c_str());
1667 else
1668 ioprintf(c1out,_("Need to get %sB of source archives.\n"),
1669 SizeToStr(DebBytes).c_str());
1670
1671 if (_config->FindB("APT::Get::Simulate",false) == true)
1672 {
1673 for (unsigned I = 0; I != J; I++)
1674 ioprintf(cout,_("Fetch Source %s\n"),Dsc[I].Package.c_str());
1675 return true;
1676 }
1677
1678 // Just print out the uris an exit if the --print-uris flag was used
1679 if (_config->FindB("APT::Get::Print-URIs") == true)
1680 {
1681 pkgAcquire::UriIterator I = Fetcher.UriBegin();
1682 for (; I != Fetcher.UriEnd(); I++)
1683 cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' <<
1684 I->Owner->FileSize << ' ' << I->Owner->MD5Sum() << endl;
1685 return true;
1686 }
1687
1688 // Run it
1689 if (Fetcher.Run() == pkgAcquire::Failed)
1690 return false;
1691
1692 // Print error messages
1693 bool Failed = false;
1694 for (pkgAcquire::Item **I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
1695 {
1696 if ((*I)->Status == pkgAcquire::Item::StatDone &&
1697 (*I)->Complete == true)
1698 continue;
1699
1700 fprintf(stderr,_("Failed to fetch %s %s\n"),(*I)->DescURI().c_str(),
1701 (*I)->ErrorText.c_str());
1702 Failed = true;
1703 }
1704 if (Failed == true)
1705 return _error->Error(_("Failed to fetch some archives."));
1706
1707 if (_config->FindB("APT::Get::Download-only",false) == true)
1708 {
1709 c1out << _("Download complete and in download only mode") << endl;
1710 return true;
1711 }
1712
1713 // Unpack the sources
1714 pid_t Process = ExecFork();
1715
1716 if (Process == 0)
1717 {
1718 for (unsigned I = 0; I != J; I++)
1719 {
1720 string Dir = Dsc[I].Package + '-' + Cache->VS().UpstreamVersion(Dsc[I].Version.c_str());
1721
1722 // Diff only mode only fetches .diff files
1723 if (_config->FindB("APT::Get::Diff-Only",false) == true ||
1724 _config->FindB("APT::Get::Tar-Only",false) == true ||
1725 Dsc[I].Dsc.empty() == true)
1726 continue;
1727
1728 // See if the package is already unpacked
1729 struct stat Stat;
1730 if (stat(Dir.c_str(),&Stat) == 0 &&
1731 S_ISDIR(Stat.st_mode) != 0)
1732 {
1733 ioprintf(c0out ,_("Skipping unpack of already unpacked source in %s\n"),
1734 Dir.c_str());
1735 }
1736 else
1737 {
1738 // Call dpkg-source
1739 char S[500];
1740 snprintf(S,sizeof(S),"%s -x %s",
1741 _config->Find("Dir::Bin::dpkg-source","dpkg-source").c_str(),
1742 Dsc[I].Dsc.c_str());
1743 if (system(S) != 0)
1744 {
1745 fprintf(stderr,_("Unpack command '%s' failed.\n"),S);
1746 _exit(1);
1747 }
1748 }
1749
1750 // Try to compile it with dpkg-buildpackage
1751 if (_config->FindB("APT::Get::Compile",false) == true)
1752 {
1753 // Call dpkg-buildpackage
1754 char S[500];
1755 snprintf(S,sizeof(S),"cd %s && %s %s",
1756 Dir.c_str(),
1757 _config->Find("Dir::Bin::dpkg-buildpackage","dpkg-buildpackage").c_str(),
1758 _config->Find("DPkg::Build-Options","-b -uc").c_str());
1759
1760 if (system(S) != 0)
1761 {
1762 fprintf(stderr,_("Build command '%s' failed.\n"),S);
1763 _exit(1);
1764 }
1765 }
1766 }
1767
1768 _exit(0);
1769 }
1770
1771 // Wait for the subprocess
1772 int Status = 0;
1773 while (waitpid(Process,&Status,0) != Process)
1774 {
1775 if (errno == EINTR)
1776 continue;
1777 return _error->Errno("waitpid","Couldn't wait for subprocess");
1778 }
1779
1780 if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0)
1781 return _error->Error(_("Child process failed"));
1782
1783 return true;
1784}
1785 /*}}}*/
1786// DoBuildDep - Install/removes packages to satisfy build dependencies /*{{{*/
1787// ---------------------------------------------------------------------
1788/* This function will look at the build depends list of the given source
1789 package and install the necessary packages to make it true, or fail. */
1790bool DoBuildDep(CommandLine &CmdL)
1791{
1792 CacheFile Cache;
1793 if (Cache.Open(true) == false)
1794 return false;
1795
1796 if (CmdL.FileSize() <= 1)
1797 return _error->Error(_("Must specify at least one package to check builddeps for"));
1798
1799 // Read the source list
1800 pkgSourceList List;
1801 if (List.ReadMainList() == false)
1802 return _error->Error(_("The list of sources could not be read."));
1803
1804 // Create the text record parsers
1805 pkgRecords Recs(Cache);
1806 pkgSrcRecords SrcRecs(List);
1807 if (_error->PendingError() == true)
1808 return false;
1809
1810 // Create the download object
1811 AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
1812 pkgAcquire Fetcher(&Stat);
1813
1814 unsigned J = 0;
1815 for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++)
1816 {
1817 string Src;
1818 pkgSrcRecords::Parser *Last = FindSrc(*I,Recs,SrcRecs,Src,*Cache);
1819 if (Last == 0)
1820 return _error->Error(_("Unable to find a source package for %s"),Src.c_str());
1821
1822 // Process the build-dependencies
1823 vector<pkgSrcRecords::Parser::BuildDepRec> BuildDeps;
1824 if (Last->BuildDepends(BuildDeps) == false)
1825 return _error->Error(_("Unable to get build-dependency information for %s"),Src.c_str());
1826
1827 if (BuildDeps.size() == 0)
1828 {
1829 ioprintf(c1out,_("%s has no build depends.\n"),Src.c_str());
1830 continue;
1831 }
1832
1833 // Install the requested packages
1834 unsigned int ExpectedInst = 0;
1835 vector <pkgSrcRecords::Parser::BuildDepRec>::iterator D;
1836 pkgProblemResolver Fix(Cache);
1837 for (D = BuildDeps.begin(); D != BuildDeps.end(); D++)
1838 {
1839 pkgCache::PkgIterator Pkg = Cache->FindPkg((*D).Package);
1840 if (Pkg.end() == true)
1841 return _error->Error(_("%s dependency on %s cannot be satisfied because the package %s cannot be found"),
1842 Last->BuildDepType((*D).Type),Src.c_str(),(*D).Package.c_str());
1843 pkgCache::VerIterator IV = (*Cache)[Pkg].InstVerIter(*Cache);
1844
1845 if ((*D).Type == pkgSrcRecords::Parser::BuildConflict ||
1846 (*D).Type == pkgSrcRecords::Parser::BuildConflictIndep)
1847 {
1848 /*
1849 * conflict; need to remove if we have an installed version
1850 * that satisfies the version criterial
1851 */
1852 if (IV.end() == false &&
1853 Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
1854 TryToInstall(Pkg,Cache,Fix,true,false,ExpectedInst);
1855 }
1856 else
1857 {
1858 /*
1859 * If this is a virtual package, we need to check the list of
1860 * packages that provide it and see if any of those are
1861 * installed
1862 */
1863 pkgCache::PrvIterator Prv = Pkg.ProvidesList();
1864 for (; Prv.end() != true; Prv++)
1865 if ((*Cache)[Prv.OwnerPkg()].InstVerIter(*Cache).end() == false)
1866 break;
1867
1868 if (Prv.end() == true)
1869 {
1870 /*
1871 * depends; need to install or upgrade if we don't have the
1872 * package installed or if the version does not satisfy the
1873 * build dep. This is complicated by the fact that if we
1874 * depend on a version lower than what we already have
1875 * installed it is not clear what should be done; in practice
1876 * this case should be rare though and right now nothing
1877 * is done about it :-(
1878 */
1879 if (IV.end() == true ||
1880 Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == false)
1881 TryToInstall(Pkg,Cache,Fix,false,false,ExpectedInst);
1882 }
1883 }
1884 }
1885
1886 Fix.InstallProtect();
1887 if (Fix.Resolve(true) == false)
1888 _error->Discard();
1889
1890 // Now we check the state of the packages,
1891 if (Cache->BrokenCount() != 0)
1892 return _error->Error(_("Some broken packages were found while trying to process build-dependencies.\n"
1893 "You might want to run `apt-get -f install' to correct these."));
1894 }
1895
1896 if (InstallPackages(Cache, false, true) == false)
1897 return _error->Error(_("Failed to process build dependencies"));
1898 return true;
1899}
1900 /*}}}*/
1901
1902// DoMoo - Never Ask, Never Tell /*{{{*/
1903// ---------------------------------------------------------------------
1904/* */
1905bool DoMoo(CommandLine &CmdL)
1906{
1907 cout <<
1908 " (__) \n"
1909 " (oo) \n"
1910 " /------\\/ \n"
1911 " / | || \n"
1912 " * /\\---/\\ \n"
1913 " ~~ ~~ \n"
1914 "....\"Have you mooed today?\"...\n";
1915
1916 return true;
1917}
1918 /*}}}*/
1919// ShowHelp - Show a help screen /*{{{*/
1920// ---------------------------------------------------------------------
1921/* */
1922bool ShowHelp(CommandLine &CmdL)
1923{
1924 ioprintf(cout,_("%s %s for %s %s compiled on %s %s\n"),PACKAGE,VERSION,
1925 COMMON_OS,COMMON_CPU,__DATE__,__TIME__);
1926
1927 if (_config->FindB("version") == true)
1928 {
1929 cout << _("Supported Modules:") << endl;
1930
1931 for (unsigned I = 0; I != pkgVersioningSystem::GlobalListLen; I++)
1932 {
1933 pkgVersioningSystem *VS = pkgVersioningSystem::GlobalList[I];
1934 if (_system != 0 && _system->VS == VS)
1935 cout << '*';
1936 else
1937 cout << ' ';
1938 cout << "Ver: " << VS->Label << endl;
1939
1940 /* Print out all the packaging systems that will work with
1941 this VS */
1942 for (unsigned J = 0; J != pkgSystem::GlobalListLen; J++)
1943 {
1944 pkgSystem *Sys = pkgSystem::GlobalList[J];
1945 if (_system == Sys)
1946 cout << '*';
1947 else
1948 cout << ' ';
1949 if (Sys->VS->TestCompatibility(*VS) == true)
1950 cout << "Pkg: " << Sys->Label << " (Priority " << Sys->Score(*_config) << ")" << endl;
1951 }
1952 }
1953
1954 for (unsigned I = 0; I != pkgSourceList::Type::GlobalListLen; I++)
1955 {
1956 pkgSourceList::Type *Type = pkgSourceList::Type::GlobalList[I];
1957 cout << " S.L: '" << Type->Name << "' " << Type->Label << endl;
1958 }
1959
1960 for (unsigned I = 0; I != pkgIndexFile::Type::GlobalListLen; I++)
1961 {
1962 pkgIndexFile::Type *Type = pkgIndexFile::Type::GlobalList[I];
1963 cout << " Idx: " << Type->Label << endl;
1964 }
1965
1966 return true;
1967 }
1968
1969 cout <<
1970 _("Usage: apt-get [options] command\n"
1971 " apt-get [options] install|remove pkg1 [pkg2 ...]\n"
1972 " apt-get [options] source pkg1 [pkg2 ...]\n"
1973 "\n"
1974 "apt-get is a simple command line interface for downloading and\n"
1975 "installing packages. The most frequently used commands are update\n"
1976 "and install.\n"
1977 "\n"
1978 "Commands:\n"
1979 " update - Retrieve new lists of packages\n"
1980 " upgrade - Perform an upgrade\n"
1981 " install - Install new packages (pkg is libc6 not libc6.deb)\n"
1982 " remove - Remove packages\n"
1983 " source - Download source archives\n"
1984 " build-dep - Configure build-dependencies for source packages\n"
1985 " dist-upgrade - Distribution upgrade, see apt-get(8)\n"
1986 " dselect-upgrade - Follow dselect selections\n"
1987 " clean - Erase downloaded archive files\n"
1988 " autoclean - Erase old downloaded archive files\n"
1989 " check - Verify that there are no broken dependencies\n"
1990 "\n"
1991 "Options:\n"
1992 " -h This help text.\n"
1993 " -q Loggable output - no progress indicator\n"
1994 " -qq No output except for errors\n"
1995 " -d Download only - do NOT install or unpack archives\n"
1996 " -s No-act. Perform ordering simulation\n"
1997 " -y Assume Yes to all queries and do not prompt\n"
1998 " -f Attempt to continue if the integrity check fails\n"
1999 " -m Attempt to continue if archives are unlocatable\n"
2000 " -u Show a list of upgraded packages as well\n"
2001 " -b Build the source package after fetching it\n"
2002 " -c=? Read this configuration file\n"
2003 " -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
2004 "See the apt-get(8), sources.list(5) and apt.conf(5) manual\n"
2005 "pages for more information and options.\n"
2006 " This APT has Super Cow Powers.\n");
2007 return true;
2008}
2009 /*}}}*/
2010// GetInitialize - Initialize things for apt-get /*{{{*/
2011// ---------------------------------------------------------------------
2012/* */
2013void GetInitialize()
2014{
2015 _config->Set("quiet",0);
2016 _config->Set("help",false);
2017 _config->Set("APT::Get::Download-Only",false);
2018 _config->Set("APT::Get::Simulate",false);
2019 _config->Set("APT::Get::Assume-Yes",false);
2020 _config->Set("APT::Get::Fix-Broken",false);
2021 _config->Set("APT::Get::Force-Yes",false);
2022 _config->Set("APT::Get::APT::Get::No-List-Cleanup",true);
2023}
2024 /*}}}*/
2025// SigWinch - Window size change signal handler /*{{{*/
2026// ---------------------------------------------------------------------
2027/* */
2028void SigWinch(int)
2029{
2030 // Riped from GNU ls
2031#ifdef TIOCGWINSZ
2032 struct winsize ws;
2033
2034 if (ioctl(1, TIOCGWINSZ, &ws) != -1 && ws.ws_col >= 5)
2035 ScreenWidth = ws.ws_col - 1;
2036#endif
2037}
2038 /*}}}*/
2039
2040int main(int argc,const char *argv[])
2041{
2042 CommandLine::Args Args[] = {
2043 {'h',"help","help",0},
2044 {'v',"version","version",0},
2045 {'q',"quiet","quiet",CommandLine::IntLevel},
2046 {'q',"silent","quiet",CommandLine::IntLevel},
2047 {'d',"download-only","APT::Get::Download-Only",0},
2048 {'b',"compile","APT::Get::Compile",0},
2049 {'b',"build","APT::Get::Compile",0},
2050 {'s',"simulate","APT::Get::Simulate",0},
2051 {'s',"just-print","APT::Get::Simulate",0},
2052 {'s',"recon","APT::Get::Simulate",0},
2053 {'s',"dry-run","APT::Get::Simulate",0},
2054 {'s',"no-act","APT::Get::Simulate",0},
2055 {'y',"yes","APT::Get::Assume-Yes",0},
2056 {'y',"assume-yes","APT::Get::Assume-Yes",0},
2057 {'f',"fix-broken","APT::Get::Fix-Broken",0},
2058 {'u',"show-upgraded","APT::Get::Show-Upgraded",0},
2059 {'m',"ignore-missing","APT::Get::Fix-Missing",0},
2060 {'t',"target-release","APT::Default-Release",CommandLine::HasArg},
2061 {'t',"default-release","APT::Default-Release",CommandLine::HasArg},
2062 {0,"download","APT::Get::Download",0},
2063 {0,"fix-missing","APT::Get::Fix-Missing",0},
2064 {0,"ignore-hold","APT::Ignore-Hold",0},
2065 {0,"upgrade","APT::Get::upgrade",0},
2066 {0,"force-yes","APT::Get::force-yes",0},
2067 {0,"print-uris","APT::Get::Print-URIs",0},
2068 {0,"diff-only","APT::Get::Diff-Only",0},
2069 {0,"tar-only","APT::Get::tar-Only",0},
2070 {0,"purge","APT::Get::Purge",0},
2071 {0,"list-cleanup","APT::Get::List-Cleanup",0},
2072 {0,"reinstall","APT::Get::ReInstall",0},
2073 {0,"trivial-only","APT::Get::Trivial-Only",0},
2074 {0,"remove","APT::Get::Remove",0},
2075 {0,"only-source","APT::Get::Only-Source",0},
2076 {'c',"config-file",0,CommandLine::ConfigFile},
2077 {'o',"option",0,CommandLine::ArbItem},
2078 {0,0,0,0}};
2079 CommandLine::Dispatch Cmds[] = {{"update",&DoUpdate},
2080 {"upgrade",&DoUpgrade},
2081 {"install",&DoInstall},
2082 {"remove",&DoInstall},
2083 {"dist-upgrade",&DoDistUpgrade},
2084 {"dselect-upgrade",&DoDSelectUpgrade},
2085 {"build-dep",&DoBuildDep},
2086 {"clean",&DoClean},
2087 {"autoclean",&DoAutoClean},
2088 {"check",&DoCheck},
2089 {"source",&DoSource},
2090 {"moo",&DoMoo},
2091 {"help",&ShowHelp},
2092 {0,0}};
2093
2094 // Parse the command line and initialize the package library
2095 CommandLine CmdL(Args,_config);
2096 if (pkgInitConfig(*_config) == false ||
2097 CmdL.Parse(argc,argv) == false ||
2098 pkgInitSystem(*_config,_system) == false)
2099 {
2100 if (_config->FindB("version") == true)
2101 ShowHelp(CmdL);
2102
2103 _error->DumpErrors();
2104 return 100;
2105 }
2106
2107 // See if the help should be shown
2108 if (_config->FindB("help") == true ||
2109 _config->FindB("version") == true ||
2110 CmdL.FileSize() == 0)
2111 {
2112 ShowHelp(CmdL);
2113 return 0;
2114 }
2115
2116 // Deal with stdout not being a tty
2117 if (ttyname(STDOUT_FILENO) == 0 && _config->FindI("quiet",0) < 1)
2118 _config->Set("quiet","1");
2119
2120 // Setup the output streams
2121 c0out.rdbuf(cout.rdbuf());
2122 c1out.rdbuf(cout.rdbuf());
2123 c2out.rdbuf(cout.rdbuf());
2124 if (_config->FindI("quiet",0) > 0)
2125 c0out.rdbuf(devnull.rdbuf());
2126 if (_config->FindI("quiet",0) > 1)
2127 c1out.rdbuf(devnull.rdbuf());
2128
2129 // Setup the signals
2130 signal(SIGPIPE,SIG_IGN);
2131 signal(SIGWINCH,SigWinch);
2132 SigWinch(0);
2133
2134 // Match the operation
2135 CmdL.DispatchArg(Cmds);
2136
2137 // Print any errors or warnings found during parsing
2138 if (_error->empty() == false)
2139 {
2140 bool Errors = _error->PendingError();
2141 _error->DumpErrors();
2142 return Errors == true?100:0;
2143 }
2144
2145 return 0;
2146}