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