]> git.saurik.com Git - apt.git/blob - cmdline/apt-get.cc
Working apt-get source build stuff
[apt.git] / cmdline / apt-get.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: apt-get.cc,v 1.55 1999/04/20 05:02:09 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/dpkgpm.h>
36 #include <apt-pkg/strutl.h>
37 #include <apt-pkg/clean.h>
38 #include <apt-pkg/srcrecords.h>
39 #include <apt-pkg/version.h>
40 #include <apt-pkg/cachefile.h>
41
42 #include <config.h>
43
44 #include "acqprogress.h"
45
46 #include <fstream.h>
47 #include <termios.h>
48 #include <sys/ioctl.h>
49 #include <sys/stat.h>
50 #include <sys/vfs.h>
51 #include <signal.h>
52 #include <unistd.h>
53 #include <stdio.h>
54 #include <sys/wait.h>
55 /*}}}*/
56
57 ostream c0out;
58 ostream c1out;
59 ostream c2out;
60 ofstream devnull("/dev/null");
61 unsigned int ScreenWidth = 80;
62
63 // YnPrompt - Yes No Prompt. /*{{{*/
64 // ---------------------------------------------------------------------
65 /* Returns true on a Yes.*/
66 bool YnPrompt()
67 {
68 if (_config->FindB("APT::Get::Assume-Yes",false) == true)
69 {
70 c1out << 'Y' << endl;
71 return true;
72 }
73
74 char C = 0;
75 char Jnk = 0;
76 read(STDIN_FILENO,&C,1);
77 while (C != '\n' && Jnk != '\n') read(STDIN_FILENO,&Jnk,1);
78
79 if (!(C == 'Y' || C == 'y' || C == '\n' || C == '\r'))
80 return false;
81 return true;
82 }
83 /*}}}*/
84 // AnalPrompt - Annoying Yes No Prompt. /*{{{*/
85 // ---------------------------------------------------------------------
86 /* Returns true on a Yes.*/
87 bool AnalPrompt(const char *Text)
88 {
89 char Buf[1024];
90 cin.getline(Buf,sizeof(Buf));
91 if (strcmp(Buf,Text) == 0)
92 return true;
93 return false;
94 }
95 /*}}}*/
96 // ShowList - Show a list /*{{{*/
97 // ---------------------------------------------------------------------
98 /* This prints out a string of space seperated words with a title and
99 a two space indent line wraped to the current screen width. */
100 bool ShowList(ostream &out,string Title,string List)
101 {
102 if (List.empty() == true)
103 return true;
104
105 // Acount for the leading space
106 int ScreenWidth = ::ScreenWidth - 3;
107
108 out << Title << endl;
109 string::size_type Start = 0;
110 while (Start < List.size())
111 {
112 string::size_type End;
113 if (Start + ScreenWidth >= List.size())
114 End = List.size();
115 else
116 End = List.rfind(' ',Start+ScreenWidth);
117
118 if (End == string::npos || End < Start)
119 End = Start + ScreenWidth;
120 out << " " << string(List,Start,End - Start) << endl;
121 Start = End + 1;
122 }
123 return false;
124 }
125 /*}}}*/
126 // ShowBroken - Debugging aide /*{{{*/
127 // ---------------------------------------------------------------------
128 /* This prints out the names of all the packages that are broken along
129 with the name of each each broken dependency and a quite version
130 description. */
131 void ShowBroken(ostream &out,pkgDepCache &Cache)
132 {
133 out << "Sorry, but the following packages have unmet dependencies:" << endl;
134 pkgCache::PkgIterator I = Cache.PkgBegin();
135 for (;I.end() != true; I++)
136 {
137 if (Cache[I].InstBroken() == false)
138 continue;
139
140 // Print out each package and the failed dependencies
141 out <<" " << I.Name() << ":";
142 int Indent = strlen(I.Name()) + 3;
143 bool First = true;
144 if (Cache[I].InstVerIter(Cache).end() == true)
145 {
146 cout << endl;
147 continue;
148 }
149
150 for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); D.end() == false;)
151 {
152 // Compute a single dependency element (glob or)
153 pkgCache::DepIterator Start;
154 pkgCache::DepIterator End;
155 D.GlobOr(Start,End);
156
157 if (Cache.IsImportantDep(End) == false ||
158 (Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
159 continue;
160
161 if (First == false)
162 for (int J = 0; J != Indent; J++)
163 out << ' ';
164 First = false;
165
166 out << ' ' << End.DepType() << ": " << End.TargetPkg().Name();
167
168 // Show a quick summary of the version requirements
169 if (End.TargetVer() != 0)
170 out << " (" << End.CompType() << " " << End.TargetVer() <<
171 ")";
172
173 /* Show a summary of the target package if possible. In the case
174 of virtual packages we show nothing */
175
176 pkgCache::PkgIterator Targ = End.TargetPkg();
177 if (Targ->ProvidesList == 0)
178 {
179 out << " but ";
180 pkgCache::VerIterator Ver = Cache[Targ].InstVerIter(Cache);
181 if (Ver.end() == false)
182 out << Ver.VerStr() << " is installed";
183 else
184 {
185 if (Cache[Targ].CandidateVerIter(Cache).end() == true)
186 {
187 if (Targ->ProvidesList == 0)
188 out << "it is not installable";
189 else
190 out << "it is a virtual package";
191 }
192 else
193 out << "it is not installed";
194 }
195 }
196
197 out << endl;
198 }
199 }
200 }
201 /*}}}*/
202 // ShowNew - Show packages to newly install /*{{{*/
203 // ---------------------------------------------------------------------
204 /* */
205 void ShowNew(ostream &out,pkgDepCache &Dep)
206 {
207 /* Print out a list of packages that are going to be removed extra
208 to what the user asked */
209 pkgCache::PkgIterator I = Dep.PkgBegin();
210 string List;
211 for (;I.end() != true; I++)
212 if (Dep[I].NewInstall() == true)
213 List += string(I.Name()) + " ";
214 ShowList(out,"The following NEW packages will be installed:",List);
215 }
216 /*}}}*/
217 // ShowDel - Show packages to delete /*{{{*/
218 // ---------------------------------------------------------------------
219 /* */
220 void ShowDel(ostream &out,pkgDepCache &Dep)
221 {
222 /* Print out a list of packages that are going to be removed extra
223 to what the user asked */
224 pkgCache::PkgIterator I = Dep.PkgBegin();
225 string List;
226 for (;I.end() != true; I++)
227 if (Dep[I].Delete() == true)
228 List += string(I.Name()) + " ";
229
230 ShowList(out,"The following packages will be REMOVED:",List);
231 }
232 /*}}}*/
233 // ShowKept - Show kept packages /*{{{*/
234 // ---------------------------------------------------------------------
235 /* */
236 void ShowKept(ostream &out,pkgDepCache &Dep)
237 {
238 pkgCache::PkgIterator I = Dep.PkgBegin();
239 string List;
240 for (;I.end() != true; I++)
241 {
242 // Not interesting
243 if (Dep[I].Upgrade() == true || Dep[I].Upgradable() == false ||
244 I->CurrentVer == 0 || Dep[I].Delete() == true)
245 continue;
246
247 List += string(I.Name()) + " ";
248 }
249 ShowList(out,"The following packages have been kept back",List);
250 }
251 /*}}}*/
252 // ShowUpgraded - Show upgraded packages /*{{{*/
253 // ---------------------------------------------------------------------
254 /* */
255 void ShowUpgraded(ostream &out,pkgDepCache &Dep)
256 {
257 pkgCache::PkgIterator I = Dep.PkgBegin();
258 string List;
259 for (;I.end() != true; I++)
260 {
261 // Not interesting
262 if (Dep[I].Upgrade() == false || Dep[I].NewInstall() == true)
263 continue;
264
265 List += string(I.Name()) + " ";
266 }
267 ShowList(out,"The following packages will be upgraded",List);
268 }
269 /*}}}*/
270 // ShowHold - Show held but changed packages /*{{{*/
271 // ---------------------------------------------------------------------
272 /* */
273 bool ShowHold(ostream &out,pkgDepCache &Dep)
274 {
275 pkgCache::PkgIterator I = Dep.PkgBegin();
276 string List;
277 for (;I.end() != true; I++)
278 {
279 if (Dep[I].InstallVer != (pkgCache::Version *)I.CurrentVer() &&
280 I->SelectedState == pkgCache::State::Hold)
281 List += string(I.Name()) + " ";
282 }
283
284 return ShowList(out,"The following held packages will be changed:",List);
285 }
286 /*}}}*/
287 // ShowEssential - Show an essential package warning /*{{{*/
288 // ---------------------------------------------------------------------
289 /* This prints out a warning message that is not to be ignored. It shows
290 all essential packages and their dependents that are to be removed.
291 It is insanely risky to remove the dependents of an essential package! */
292 bool ShowEssential(ostream &out,pkgDepCache &Dep)
293 {
294 pkgCache::PkgIterator I = Dep.PkgBegin();
295 string List;
296 bool *Added = new bool[Dep.HeaderP->PackageCount];
297 for (unsigned int I = 0; I != Dep.HeaderP->PackageCount; I++)
298 Added[I] = false;
299
300 for (;I.end() != true; I++)
301 {
302 if ((I->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential)
303 continue;
304
305 // The essential package is being removed
306 if (Dep[I].Delete() == true)
307 {
308 if (Added[I->ID] == false)
309 {
310 Added[I->ID] = true;
311 List += string(I.Name()) + " ";
312 }
313 }
314
315 if (I->CurrentVer == 0)
316 continue;
317
318 // Print out any essential package depenendents that are to be removed
319 for (pkgDepCache::DepIterator D = I.CurrentVer().DependsList(); D.end() == false; D++)
320 {
321 // Skip everything but depends
322 if (D->Type != pkgCache::Dep::PreDepends &&
323 D->Type != pkgCache::Dep::Depends)
324 continue;
325
326 pkgCache::PkgIterator P = D.SmartTargetPkg();
327 if (Dep[P].Delete() == true)
328 {
329 if (Added[P->ID] == true)
330 continue;
331 Added[P->ID] = true;
332
333 char S[300];
334 sprintf(S,"%s (due to %s) ",P.Name(),I.Name());
335 List += S;
336 }
337 }
338 }
339
340 delete [] Added;
341 if (List.empty() == false)
342 out << "WARNING: The following essential packages will be removed" << endl;
343 return ShowList(out,"This should NOT be done unless you know exactly what you are doing!",List);
344 }
345 /*}}}*/
346 // Stats - Show some statistics /*{{{*/
347 // ---------------------------------------------------------------------
348 /* */
349 void Stats(ostream &out,pkgDepCache &Dep)
350 {
351 unsigned long Upgrade = 0;
352 unsigned long Install = 0;
353 for (pkgCache::PkgIterator I = Dep.PkgBegin(); I.end() == false; I++)
354 {
355 if (Dep[I].NewInstall() == true)
356 Install++;
357 else
358 if (Dep[I].Upgrade() == true)
359 Upgrade++;
360 }
361
362 out << Upgrade << " packages upgraded, " <<
363 Install << " newly installed, " <<
364 Dep.DelCount() << " to remove and " <<
365 Dep.KeepCount() << " not upgraded." << endl;
366
367 if (Dep.BadCount() != 0)
368 out << Dep.BadCount() << " packages not fully installed or removed." << endl;
369 }
370 /*}}}*/
371
372 // class CacheFile - Cover class for some dependency cache functions /*{{{*/
373 // ---------------------------------------------------------------------
374 /* */
375 class CacheFile : public pkgCacheFile
376 {
377 public:
378
379 bool CheckDeps(bool AllowBroken = false);
380 bool Open(bool WithLock = true)
381 {
382 OpTextProgress Prog(*_config);
383 return pkgCacheFile::Open(Prog,WithLock);
384 };
385 };
386 /*}}}*/
387 // CacheFile::Open - Open the cache file /*{{{*/
388 // ---------------------------------------------------------------------
389 /* This routine generates the caches and then opens the dependency cache
390 and verifies that the system is OK. */
391 bool CacheFile::CheckDeps(bool AllowBroken)
392 {
393 if (_error->PendingError() == true)
394 return false;
395
396 // Check that the system is OK
397 if (Cache->DelCount() != 0 || Cache->InstCount() != 0)
398 return _error->Error("Internal Error, non-zero counts");
399
400 // Apply corrections for half-installed packages
401 if (pkgApplyStatus(*Cache) == false)
402 return false;
403
404 // Nothing is broken
405 if (Cache->BrokenCount() == 0 || AllowBroken == true)
406 return true;
407
408 // Attempt to fix broken things
409 if (_config->FindB("APT::Get::Fix-Broken",false) == true)
410 {
411 c1out << "Correcting dependencies..." << flush;
412 if (pkgFixBroken(*Cache) == false || Cache->BrokenCount() != 0)
413 {
414 c1out << " failed." << endl;
415 ShowBroken(c1out,*this);
416
417 return _error->Error("Unable to correct dependencies");
418 }
419 if (pkgMinimizeUpgrade(*Cache) == false)
420 return _error->Error("Unable to minimize the upgrade set");
421
422 c1out << " Done" << endl;
423 }
424 else
425 {
426 c1out << "You might want to run `apt-get -f install' to correct these." << endl;
427 ShowBroken(c1out,*this);
428
429 return _error->Error("Unmet dependencies. Try using -f.");
430 }
431
432 return true;
433 }
434 /*}}}*/
435
436 // InstallPackages - Actually download and install the packages /*{{{*/
437 // ---------------------------------------------------------------------
438 /* This displays the informative messages describing what is going to
439 happen and then calls the download routines */
440 bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,bool Saftey = true)
441 {
442 bool Fail = false;
443 bool Essential = false;
444
445 // Show all the various warning indicators
446 ShowDel(c1out,Cache);
447 ShowNew(c1out,Cache);
448 if (ShwKept == true)
449 ShowKept(c1out,Cache);
450 Fail |= !ShowHold(c1out,Cache);
451 if (_config->FindB("APT::Get::Show-Upgraded",false) == true)
452 ShowUpgraded(c1out,Cache);
453 Essential = !ShowEssential(c1out,Cache);
454 Fail |= Essential;
455 Stats(c1out,Cache);
456
457 // Sanity check
458 if (Cache->BrokenCount() != 0)
459 {
460 ShowBroken(c1out,Cache);
461 return _error->Error("Internal Error, InstallPackages was called with broken packages!");
462 }
463
464 if (Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
465 Cache->BadCount() == 0)
466 return true;
467
468 // Run the simulator ..
469 if (_config->FindB("APT::Get::Simulate") == true)
470 {
471 pkgSimulate PM(Cache);
472 return PM.DoInstall();
473 }
474
475 // Create the text record parser
476 pkgRecords Recs(Cache);
477 if (_error->PendingError() == true)
478 return false;
479
480 // Lock the archive directory
481 FileFd Lock;
482 if (_config->FindB("Debug::NoLocking",false) == false)
483 {
484 Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
485 if (_error->PendingError() == true)
486 return _error->Error("Unable to lock the download directory");
487 }
488
489 // Create the download object
490 AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
491 pkgAcquire Fetcher(&Stat);
492
493 // Read the source list
494 pkgSourceList List;
495 if (List.ReadMainList() == false)
496 return _error->Error("The list of sources could not be read.");
497
498 // Create the package manager and prepare to download
499 pkgDPkgPM PM(Cache);
500 if (PM.GetArchives(&Fetcher,&List,&Recs) == false ||
501 _error->PendingError() == true)
502 return false;
503
504 // Display statistics
505 unsigned long FetchBytes = Fetcher.FetchNeeded();
506 unsigned long FetchPBytes = Fetcher.PartialPresent();
507 unsigned long DebBytes = Fetcher.TotalNeeded();
508 if (DebBytes != Cache->DebSize())
509 {
510 c0out << DebBytes << ',' << Cache->DebSize() << endl;
511 c0out << "How odd.. The sizes didn't match, email apt@packages.debian.org" << endl;
512 }
513
514 // Check for enough free space
515 struct statfs Buf;
516 string OutputDir = _config->FindDir("Dir::Cache::Archives");
517 if (statfs(OutputDir.c_str(),&Buf) != 0)
518 return _error->Errno("statfs","Couldn't determine free space in %s",
519 OutputDir.c_str());
520 if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
521 return _error->Error("Sorry, you don't have enough free space in %s",
522 OutputDir.c_str());
523
524 // Number of bytes
525 c1out << "Need to get ";
526 if (DebBytes != FetchBytes)
527 c1out << SizeToStr(FetchBytes) << "b/" << SizeToStr(DebBytes) << 'b';
528 else
529 c1out << SizeToStr(DebBytes) << 'b';
530
531 c1out << " of archives. After unpacking ";
532
533 // Size delta
534 if (Cache->UsrSize() >= 0)
535 c1out << SizeToStr(Cache->UsrSize()) << "b will be used." << endl;
536 else
537 c1out << SizeToStr(-1*Cache->UsrSize()) << "b will be freed." << endl;
538
539 if (_error->PendingError() == true)
540 return false;
541
542 // Fail safe check
543 if (_config->FindI("quiet",0) >= 2 ||
544 _config->FindB("APT::Get::Assume-Yes",false) == true)
545 {
546 if (Fail == true && _config->FindB("APT::Get::Force-Yes",false) == false)
547 return _error->Error("There are problems and -y was used without --force-yes");
548 }
549
550 if (Essential == true && Saftey == true)
551 {
552 c2out << "You are about to do something potentially harmful" << endl;
553 c2out << "To continue type in the phrase 'Yes, I understand this may be bad'" << endl;
554 c2out << " ?] " << flush;
555 if (AnalPrompt("Yes, I understand this may be bad") == false)
556 {
557 c2out << "Abort." << endl;
558 exit(1);
559 }
560 }
561 else
562 {
563 // Prompt to continue
564 if (Ask == true || Fail == true)
565 {
566 if (_config->FindI("quiet",0) < 2 &&
567 _config->FindB("APT::Get::Assume-Yes",false) == false)
568 {
569 c2out << "Do you want to continue? [Y/n] " << flush;
570
571 if (YnPrompt() == false)
572 {
573 c2out << "Abort." << endl;
574 exit(1);
575 }
576 }
577 }
578 }
579
580 // Just print out the uris an exit if the --print-uris flag was used
581 if (_config->FindB("APT::Get::Print-URIs") == true)
582 {
583 pkgAcquire::UriIterator I = Fetcher.UriBegin();
584 for (; I != Fetcher.UriEnd(); I++)
585 cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' <<
586 I->Owner->FileSize << ' ' << I->Owner->MD5Sum() << endl;
587 return true;
588 }
589
590 // Run it
591 if (Fetcher.Run() == false)
592 return false;
593
594 // Print out errors
595 bool Failed = false;
596 bool Transient = false;
597 for (pkgAcquire::Item **I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
598 {
599 if ((*I)->Status == pkgAcquire::Item::StatDone &&
600 (*I)->Complete == true)
601 continue;
602
603 if ((*I)->Status == pkgAcquire::Item::StatIdle)
604 {
605 Transient = true;
606 Failed = true;
607 continue;
608 }
609
610 cerr << "Failed to fetch " << (*I)->DescURI() << endl;
611 cerr << " " << (*I)->ErrorText << endl;
612 Failed = true;
613 }
614
615 if (_config->FindB("APT::Get::Download-Only",false) == true)
616 return true;
617
618 if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
619 {
620 if (Transient == true)
621 {
622 c2out << "Upgrading with disk swapping is not supported in this version." << endl;
623 c2out << "Try running multiple times with --fix-missing" << endl;
624 }
625
626 return _error->Error("Unable to fetch some archives, maybe try with --fix-missing?");
627 }
628
629 // Try to deal with missing package files
630 if (PM.FixMissing() == false)
631 {
632 cerr << "Unable to correct missing packages." << endl;
633 return _error->Error("Aborting Install.");
634 }
635
636 Cache.ReleaseLock();
637 return PM.DoInstall();
638 }
639 /*}}}*/
640
641 // DoUpdate - Update the package lists /*{{{*/
642 // ---------------------------------------------------------------------
643 /* */
644 bool DoUpdate(CommandLine &)
645 {
646 // Get the source list
647 pkgSourceList List;
648 if (List.ReadMainList() == false)
649 return false;
650
651 // Lock the list directory
652 FileFd Lock;
653 if (_config->FindB("Debug::NoLocking",false) == false)
654 {
655 Lock.Fd(GetLock(_config->FindDir("Dir::State::Lists") + "lock"));
656 if (_error->PendingError() == true)
657 return _error->Error("Unable to lock the list directory");
658 }
659
660 // Create the download object
661 AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
662 pkgAcquire Fetcher(&Stat);
663
664 // Populate it with the source selection
665 pkgSourceList::const_iterator I;
666 for (I = List.begin(); I != List.end(); I++)
667 {
668 new pkgAcqIndex(&Fetcher,I);
669 if (_error->PendingError() == true)
670 return false;
671 }
672
673 // Run it
674 if (Fetcher.Run() == false)
675 return false;
676
677 // Clean out any old list files
678 if (Fetcher.Clean(_config->FindDir("Dir::State::lists")) == false ||
679 Fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/") == false)
680 return false;
681
682 // Prepare the cache.
683 CacheFile Cache;
684 if (Cache.Open() == false)
685 return false;
686
687 return true;
688 }
689 /*}}}*/
690 // DoUpgrade - Upgrade all packages /*{{{*/
691 // ---------------------------------------------------------------------
692 /* Upgrade all packages without installing new packages or erasing old
693 packages */
694 bool DoUpgrade(CommandLine &CmdL)
695 {
696 CacheFile Cache;
697 if (Cache.Open() == false || Cache.CheckDeps() == false)
698 return false;
699
700 // Do the upgrade
701 if (pkgAllUpgrade(Cache) == false)
702 {
703 ShowBroken(c1out,Cache);
704 return _error->Error("Internal Error, AllUpgrade broke stuff");
705 }
706
707 return InstallPackages(Cache,true);
708 }
709 /*}}}*/
710 // DoInstall - Install packages from the command line /*{{{*/
711 // ---------------------------------------------------------------------
712 /* Install named packages */
713 bool DoInstall(CommandLine &CmdL)
714 {
715 CacheFile Cache;
716 if (Cache.Open() == false || Cache.CheckDeps(CmdL.FileSize() != 1) == false)
717 return false;
718
719 // Enter the special broken fixing mode if the user specified arguments
720 bool BrokenFix = false;
721 if (Cache->BrokenCount() != 0)
722 BrokenFix = true;
723
724 unsigned int ExpectedInst = 0;
725 unsigned int Packages = 0;
726 pkgProblemResolver Fix(Cache);
727
728 bool DefRemove = false;
729 if (strcasecmp(CmdL.FileList[0],"remove") == 0)
730 DefRemove = true;
731
732 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
733 {
734 // Duplicate the string
735 unsigned int Length = strlen(*I);
736 char S[300];
737 if (Length >= sizeof(S))
738 continue;
739 strcpy(S,*I);
740
741 // See if we are removing the package
742 bool Remove = DefRemove;
743 if (Cache->FindPkg(S).end() == true)
744 {
745 // Handle an optional end tag indicating what to do
746 if (S[Length - 1] == '-')
747 {
748 Remove = true;
749 S[--Length] = 0;
750 }
751 if (S[Length - 1] == '+')
752 {
753 Remove = false;
754 S[--Length] = 0;
755 }
756 }
757
758 // Locate the package
759 pkgCache::PkgIterator Pkg = Cache->FindPkg(S);
760 Packages++;
761 if (Pkg.end() == true)
762 return _error->Error("Couldn't find package %s",S);
763
764 // Handle the no-upgrade case
765 if (_config->FindB("APT::Get::no-upgrade",false) == true &&
766 Pkg->CurrentVer != 0)
767 {
768 c1out << "Skipping " << Pkg.Name() << ", it is already installed and no-upgrade is set." << endl;
769 continue;
770 }
771
772 // Check if there is something new to install
773 pkgDepCache::StateCache &State = (*Cache)[Pkg];
774 if (State.CandidateVer == 0)
775 {
776 if (Pkg->ProvidesList != 0)
777 {
778 c1out << "Package " << S << " is a virtual package provided by:" << endl;
779
780 pkgCache::PrvIterator I = Pkg.ProvidesList();
781 for (; I.end() == false; I++)
782 {
783 pkgCache::PkgIterator Pkg = I.OwnerPkg();
784
785 if ((*Cache)[Pkg].CandidateVerIter(*Cache) == I.OwnerVer())
786 {
787 if ((*Cache)[Pkg].Install() == true && (*Cache)[Pkg].NewInstall() == false)
788 c1out << " " << Pkg.Name() << " " << I.OwnerVer().VerStr() <<
789 " [Installed]"<< endl;
790 else
791 c1out << " " << Pkg.Name() << " " << I.OwnerVer().VerStr() << endl;
792 }
793 }
794 c1out << "You should explicly select one to install." << endl;
795 }
796 else
797 {
798 c1out << "Package " << S << " has no available version, but exists in the database." << endl;
799 c1out << "This typically means that the package was mentioned in a dependency and " << endl;
800 c1out << "never uploaded, or that it is an obsolete package." << endl;
801
802 string List;
803 pkgCache::DepIterator Dep = Pkg.RevDependsList();
804 for (; Dep.end() == false; Dep++)
805 {
806 if (Dep->Type != pkgCache::Dep::Replaces)
807 continue;
808 List += string(Dep.ParentPkg().Name()) + " ";
809 }
810 ShowList(c1out,"However the following packages replace it:",List);
811 }
812
813 return _error->Error("Package %s has no installation candidate",S);
814 }
815
816 Fix.Protect(Pkg);
817 if (Remove == true)
818 {
819 Fix.Remove(Pkg);
820 Cache->MarkDelete(Pkg);
821 continue;
822 }
823
824 // Install it
825 Cache->MarkInstall(Pkg,false);
826 if (State.Install() == false)
827 c1out << "Sorry, " << S << " is already the newest version" << endl;
828 else
829 ExpectedInst++;
830
831 // Install it with autoinstalling enabled.
832 if (State.InstBroken() == true && BrokenFix == false)
833 Cache->MarkInstall(Pkg,true);
834 }
835
836 /* If we are in the Broken fixing mode we do not attempt to fix the
837 problems. This is if the user invoked install without -f and gave
838 packages */
839 if (BrokenFix == true && Cache->BrokenCount() != 0)
840 {
841 c1out << "You might want to run `apt-get -f install' to correct these." << endl;
842 ShowBroken(c1out,Cache);
843
844 return _error->Error("Unmet dependencies. Try using -f.");
845 }
846
847 // Call the scored problem resolver
848 Fix.InstallProtect();
849 if (Fix.Resolve(true) == false)
850 _error->Discard();
851
852 // Now we check the state of the packages,
853 if (Cache->BrokenCount() != 0)
854 {
855 c1out << "Some packages could not be installed. This may mean that you have" << endl;
856 c1out << "requested an impossible situation or if you are using the unstable" << endl;
857 c1out << "distribution that some required packages have not yet been created" << endl;
858 c1out << "or been moved out of Incoming." << endl;
859 if (Packages == 1)
860 {
861 c1out << endl;
862 c1out << "Since you only requested a single operation it is extremely likely that" << endl;
863 c1out << "the package is simply not installable and a bug report against" << endl;
864 c1out << "that package should be filed." << endl;
865 }
866
867 c1out << "The following information may help to resolve the situation:" << endl;
868 c1out << endl;
869 ShowBroken(c1out,Cache);
870 return _error->Error("Sorry, broken packages");
871 }
872
873 /* Print out a list of packages that are going to be installed extra
874 to what the user asked */
875 if (Cache->InstCount() != ExpectedInst)
876 {
877 string List;
878 pkgCache::PkgIterator I = Cache->PkgBegin();
879 for (;I.end() != true; I++)
880 {
881 if ((*Cache)[I].Install() == false)
882 continue;
883
884 const char **J;
885 for (J = CmdL.FileList + 1; *J != 0; J++)
886 if (strcmp(*J,I.Name()) == 0)
887 break;
888
889 if (*J == 0)
890 List += string(I.Name()) + " ";
891 }
892
893 ShowList(c1out,"The following extra packages will be installed:",List);
894 }
895
896 // See if we need to prompt
897 if (Cache->InstCount() == ExpectedInst && Cache->DelCount() == 0)
898 return InstallPackages(Cache,false,false);
899
900 return InstallPackages(Cache,false);
901 }
902 /*}}}*/
903 // DoDistUpgrade - Automatic smart upgrader /*{{{*/
904 // ---------------------------------------------------------------------
905 /* Intelligent upgrader that will install and remove packages at will */
906 bool DoDistUpgrade(CommandLine &CmdL)
907 {
908 CacheFile Cache;
909 if (Cache.Open() == false || Cache.CheckDeps() == false)
910 return false;
911
912 c0out << "Calculating Upgrade... " << flush;
913 if (pkgDistUpgrade(*Cache) == false)
914 {
915 c0out << "Failed" << endl;
916 ShowBroken(c1out,Cache);
917 return false;
918 }
919
920 c0out << "Done" << endl;
921
922 return InstallPackages(Cache,true);
923 }
924 /*}}}*/
925 // DoDSelectUpgrade - Do an upgrade by following dselects selections /*{{{*/
926 // ---------------------------------------------------------------------
927 /* Follows dselect's selections */
928 bool DoDSelectUpgrade(CommandLine &CmdL)
929 {
930 CacheFile Cache;
931 if (Cache.Open() == false || Cache.CheckDeps() == false)
932 return false;
933
934 // Install everything with the install flag set
935 pkgCache::PkgIterator I = Cache->PkgBegin();
936 for (;I.end() != true; I++)
937 {
938 /* Install the package only if it is a new install, the autoupgrader
939 will deal with the rest */
940 if (I->SelectedState == pkgCache::State::Install)
941 Cache->MarkInstall(I,false);
942 }
943
944 /* Now install their deps too, if we do this above then order of
945 the status file is significant for | groups */
946 for (I = Cache->PkgBegin();I.end() != true; I++)
947 {
948 /* Install the package only if it is a new install, the autoupgrader
949 will deal with the rest */
950 if (I->SelectedState == pkgCache::State::Install)
951 Cache->MarkInstall(I,true);
952 }
953
954 // Apply erasures now, they override everything else.
955 for (I = Cache->PkgBegin();I.end() != true; I++)
956 {
957 // Remove packages
958 if (I->SelectedState == pkgCache::State::DeInstall ||
959 I->SelectedState == pkgCache::State::Purge)
960 Cache->MarkDelete(I);
961 }
962
963 /* Resolve any problems that dselect created, allupgrade cannot handle
964 such things. We do so quite agressively too.. */
965 if (Cache->BrokenCount() != 0)
966 {
967 pkgProblemResolver Fix(Cache);
968
969 // Hold back held packages.
970 if (_config->FindB("APT::Ingore-Hold",false) == false)
971 {
972 for (pkgCache::PkgIterator I = Cache->PkgBegin(); I.end() == false; I++)
973 {
974 if (I->SelectedState == pkgCache::State::Hold)
975 {
976 Fix.Protect(I);
977 Cache->MarkKeep(I);
978 }
979 }
980 }
981
982 if (Fix.Resolve() == false)
983 {
984 ShowBroken(c1out,Cache);
985 return _error->Error("Internal Error, problem resolver broke stuff");
986 }
987 }
988
989 // Now upgrade everything
990 if (pkgAllUpgrade(Cache) == false)
991 {
992 ShowBroken(c1out,Cache);
993 return _error->Error("Internal Error, problem resolver broke stuff");
994 }
995
996 return InstallPackages(Cache,false);
997 }
998 /*}}}*/
999 // DoClean - Remove download archives /*{{{*/
1000 // ---------------------------------------------------------------------
1001 /* */
1002 bool DoClean(CommandLine &CmdL)
1003 {
1004 pkgAcquire Fetcher;
1005 Fetcher.Clean(_config->FindDir("Dir::Cache::archives"));
1006 Fetcher.Clean(_config->FindDir("Dir::Cache::archives") + "partial/");
1007 return true;
1008 }
1009 /*}}}*/
1010 // DoAutoClean - Smartly remove downloaded archives /*{{{*/
1011 // ---------------------------------------------------------------------
1012 /* This is similar to clean but it only purges things that cannot be
1013 downloaded, that is old versions of cached packages. */
1014 class LogCleaner : public pkgArchiveCleaner
1015 {
1016 protected:
1017 virtual void Erase(const char *File,string Pkg,string Ver,struct stat &St)
1018 {
1019 cout << "Del " << Pkg << " " << Ver << " [" << SizeToStr(St.st_size) << "b]" << endl;
1020 };
1021 };
1022
1023 bool DoAutoClean(CommandLine &CmdL)
1024 {
1025 CacheFile Cache;
1026 if (Cache.Open() == false)
1027 return false;
1028
1029 LogCleaner Cleaner;
1030
1031 return Cleaner.Go(_config->FindDir("Dir::Cache::archives"),*Cache) &&
1032 Cleaner.Go(_config->FindDir("Dir::Cache::archives") + "partial/",*Cache);
1033 }
1034 /*}}}*/
1035 // DoCheck - Perform the check operation /*{{{*/
1036 // ---------------------------------------------------------------------
1037 /* Opening automatically checks the system, this command is mostly used
1038 for debugging */
1039 bool DoCheck(CommandLine &CmdL)
1040 {
1041 CacheFile Cache;
1042 Cache.Open();
1043 Cache.CheckDeps();
1044
1045 return true;
1046 }
1047 /*}}}*/
1048 // DoSource - Fetch a source archive /*{{{*/
1049 // ---------------------------------------------------------------------
1050 /* Fetch souce packages */
1051 struct DscFile
1052 {
1053 string Package;
1054 string Version;
1055 string Dsc;
1056 };
1057
1058 bool DoSource(CommandLine &CmdL)
1059 {
1060 CacheFile Cache;
1061 if (Cache.Open(false) == false)
1062 return false;
1063
1064 if (CmdL.FileSize() <= 1)
1065 return _error->Error("Must specify at least one package to fetch source for");
1066
1067 // Read the source list
1068 pkgSourceList List;
1069 if (List.ReadMainList() == false)
1070 return _error->Error("The list of sources could not be read.");
1071
1072 // Create the text record parsers
1073 pkgRecords Recs(Cache);
1074 pkgSrcRecords SrcRecs(List);
1075 if (_error->PendingError() == true)
1076 return false;
1077
1078 // Create the download object
1079 AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
1080 pkgAcquire Fetcher(&Stat);
1081
1082 DscFile *Dsc = new DscFile[CmdL.FileSize()];
1083
1084 // Load the requestd sources into the fetcher
1085 unsigned J = 0;
1086 for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++)
1087 {
1088 string Src;
1089
1090 /* Lookup the version of the package we would install if we were to
1091 install a version and determine the source package name, then look
1092 in the archive for a source package of the same name. In theory
1093 we could stash the version string as well and match that too but
1094 today there aren't multi source versions in the archive. */
1095 pkgCache::PkgIterator Pkg = Cache->FindPkg(*I);
1096 if (Pkg.end() == false)
1097 {
1098 pkgCache::VerIterator Ver = Cache->GetCandidateVer(Pkg);
1099 if (Ver.end() == false)
1100 {
1101 pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList());
1102 Src = Parse.SourcePkg();
1103 }
1104 }
1105
1106 // No source package name..
1107 if (Src.empty() == true)
1108 Src = *I;
1109
1110 // The best hit
1111 pkgSrcRecords::Parser *Last = 0;
1112 unsigned long Offset = 0;
1113 string Version;
1114
1115 // Iterate over all of the hits
1116 pkgSrcRecords::Parser *Parse;
1117 SrcRecs.Restart();
1118 while ((Parse = SrcRecs.Find(Src.c_str(),false)) != 0)
1119 {
1120 string Ver = Parse->Version();
1121 if (Last == 0 || pkgVersionCompare(Version,Ver) < 0)
1122 {
1123 Last = Parse;
1124 Offset = Parse->Offset();
1125 Version = Ver;
1126 }
1127 }
1128
1129 if (Last == 0)
1130 return _error->Error("Unable to find a source package for %s",Src.c_str());
1131
1132 // Back track
1133 vector<pkgSrcRecords::File> Lst;
1134 if (Last->Jump(Offset) == false || Last->Files(Lst) == false)
1135 return false;
1136
1137 // Load them into the fetcher
1138 for (vector<pkgSrcRecords::File>::const_iterator I = Lst.begin();
1139 I != Lst.end(); I++)
1140 {
1141 // Try to guess what sort of file it is we are getting.
1142 string Comp;
1143 if (I->Path.find(".dsc") != string::npos)
1144 {
1145 Comp = "dsc";
1146 Dsc[J].Package = Last->Package();
1147 Dsc[J].Version = Last->Version();
1148 Dsc[J].Dsc = flNotDir(I->Path);
1149 }
1150
1151 if (I->Path.find(".tar.gz") != string::npos)
1152 Comp = "tar";
1153 if (I->Path.find(".diff.gz") != string::npos)
1154 Comp = "diff";
1155
1156 new pkgAcqFile(&Fetcher,Last->Source()->ArchiveURI(I->Path),
1157 I->MD5Hash,I->Size,Last->Source()->SourceInfo(Src,
1158 Last->Version(),Comp),Src);
1159 }
1160 }
1161
1162 // Display statistics
1163 unsigned long FetchBytes = Fetcher.FetchNeeded();
1164 unsigned long FetchPBytes = Fetcher.PartialPresent();
1165 unsigned long DebBytes = Fetcher.TotalNeeded();
1166
1167 // Check for enough free space
1168 struct statfs Buf;
1169 string OutputDir = ".";
1170 if (statfs(OutputDir.c_str(),&Buf) != 0)
1171 return _error->Errno("statfs","Couldn't determine free space in %s",
1172 OutputDir.c_str());
1173 if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
1174 return _error->Error("Sorry, you don't have enough free space in %s",
1175 OutputDir.c_str());
1176
1177 // Number of bytes
1178 c1out << "Need to get ";
1179 if (DebBytes != FetchBytes)
1180 c1out << SizeToStr(FetchBytes) << "b/" << SizeToStr(DebBytes) << 'b';
1181 else
1182 c1out << SizeToStr(DebBytes) << 'b';
1183 c1out << " of source archives." << endl;
1184
1185 // Just print out the uris an exit if the --print-uris flag was used
1186 if (_config->FindB("APT::Get::Print-URIs") == true)
1187 {
1188 pkgAcquire::UriIterator I = Fetcher.UriBegin();
1189 for (; I != Fetcher.UriEnd(); I++)
1190 cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' <<
1191 I->Owner->FileSize << ' ' << I->Owner->MD5Sum() << endl;
1192 return true;
1193 }
1194
1195 // Run it
1196 if (Fetcher.Run() == false)
1197 return false;
1198
1199 // Print error messages
1200 bool Failed = false;
1201 for (pkgAcquire::Item **I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
1202 {
1203 if ((*I)->Status == pkgAcquire::Item::StatDone &&
1204 (*I)->Complete == true)
1205 continue;
1206
1207 cerr << "Failed to fetch " << (*I)->DescURI() << endl;
1208 cerr << " " << (*I)->ErrorText << endl;
1209 Failed = true;
1210 }
1211 if (Failed == true)
1212 return _error->Error("Failed to fetch some archives.");
1213
1214 if (_config->FindB("APT::Get::Download-only",false) == true)
1215 return true;
1216
1217 // Unpack the sources
1218 pid_t Process = ExecFork();
1219
1220 if (Process == 0)
1221 {
1222 for (unsigned I = 0; I != J; I++)
1223 {
1224 string Dir = Dsc[I].Package + '-' + pkgBaseVersion(Dsc[I].Version.c_str());
1225
1226 // See if the package is already unpacked
1227 struct stat Stat;
1228 if (stat(Dir.c_str(),&Stat) == 0 &&
1229 S_ISDIR(Stat.st_mode) != 0)
1230 {
1231 c0out << "Skipping unpack of already unpacked source in " << Dir << endl;
1232 }
1233 else
1234 {
1235 // Call dpkg-source
1236 char S[500];
1237 snprintf(S,sizeof(S),"%s -x %s",
1238 _config->Find("Dir::Bin::dpkg-source","dpkg-source").c_str(),
1239 Dsc[I].Dsc.c_str());
1240 if (system(S) != 0)
1241 {
1242 cerr << "Unpack command '" << S << "' failed." << endl;
1243 _exit(1);
1244 }
1245 }
1246
1247 // Try to compile it with dpkg-buildpackage
1248 if (_config->FindB("APT::Get::Compile",false) == true)
1249 {
1250 // Call dpkg-buildpackage
1251 char S[500];
1252 snprintf(S,sizeof(S),"cd %s && %s %s",
1253 Dir.c_str(),
1254 _config->Find("Dir::Bin::dpkg-buildpackage","dpkg-buildpackage").c_str(),
1255 _config->Find("DPkg::Build-Options","-b -uc").c_str());
1256
1257 if (system(S) != 0)
1258 {
1259 cerr << "Build command '" << S << "' failed." << endl;
1260 _exit(1);
1261 }
1262 }
1263 }
1264
1265 _exit(0);
1266 }
1267
1268 // Wait for the subprocess
1269 int Status = 0;
1270 while (waitpid(Process,&Status,0) != Process)
1271 {
1272 if (errno == EINTR)
1273 continue;
1274 return _error->Errno("waitpid","Couldn't wait for subprocess");
1275 }
1276
1277 if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0)
1278 return _error->Error("Child process failed");
1279
1280 return true;
1281 }
1282 /*}}}*/
1283
1284 // ShowHelp - Show a help screen /*{{{*/
1285 // ---------------------------------------------------------------------
1286 /* */
1287 bool ShowHelp(CommandLine &CmdL)
1288 {
1289 cout << PACKAGE << ' ' << VERSION << " for " << ARCHITECTURE <<
1290 " compiled on " << __DATE__ << " " << __TIME__ << endl;
1291 if (_config->FindB("version") == true)
1292 return 100;
1293
1294 cout << "Usage: apt-get [options] command" << endl;
1295 cout << " apt-get [options] install pkg1 [pkg2 ...]" << endl;
1296 cout << endl;
1297 cout << "apt-get is a simple command line interface for downloading and" << endl;
1298 cout << "installing packages. The most frequently used commands are update" << endl;
1299 cout << "and install." << endl;
1300 cout << endl;
1301 cout << "Commands:" << endl;
1302 cout << " update - Retrieve new lists of packages" << endl;
1303 cout << " upgrade - Perform an upgrade" << endl;
1304 cout << " install - Install new packages (pkg is libc6 not libc6.deb)" << endl;
1305 cout << " remove - Remove packages" << endl;
1306 cout << " source - Download source archives" << endl;
1307 cout << " dist-upgrade - Distribution upgrade, see apt-get(8)" << endl;
1308 cout << " dselect-upgrade - Follow dselect selections" << endl;
1309 cout << " clean - Erase downloaded archive files" << endl;
1310 cout << " autoclean - Erase old downloaded archive files" << endl;
1311 cout << " check - Verify that there are no broken dependencies" << endl;
1312 cout << endl;
1313 cout << "Options:" << endl;
1314 cout << " -h This help text." << endl;
1315 cout << " -q Loggable output - no progress indicator" << endl;
1316 cout << " -qq No output except for errors" << endl;
1317 cout << " -d Download only - do NOT install or unpack archives" << endl;
1318 cout << " -s No-act. Perform ordering simulation" << endl;
1319 cout << " -y Assume Yes to all queries and do not prompt" << endl;
1320 cout << " -f Attempt to continue if the integrity check fails" << endl;
1321 cout << " -m Attempt to continue if archives are unlocatable" << endl;
1322 cout << " -u Show a list of upgraded packages as well" << endl;
1323 cout << " -c=? Read this configuration file" << endl;
1324 cout << " -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp" << endl;
1325 cout << "See the apt-get(8), sources.list(5) and apt.conf(5) manual" << endl;
1326 cout << "pages for more information." << endl;
1327 return 100;
1328 }
1329 /*}}}*/
1330 // GetInitialize - Initialize things for apt-get /*{{{*/
1331 // ---------------------------------------------------------------------
1332 /* */
1333 void GetInitialize()
1334 {
1335 _config->Set("quiet",0);
1336 _config->Set("help",false);
1337 _config->Set("APT::Get::Download-Only",false);
1338 _config->Set("APT::Get::Simulate",false);
1339 _config->Set("APT::Get::Assume-Yes",false);
1340 _config->Set("APT::Get::Fix-Broken",false);
1341 _config->Set("APT::Get::Force-Yes",false);
1342 }
1343 /*}}}*/
1344 // SigWinch - Window size change signal handler /*{{{*/
1345 // ---------------------------------------------------------------------
1346 /* */
1347 void SigWinch(int)
1348 {
1349 // Riped from GNU ls
1350 #ifdef TIOCGWINSZ
1351 struct winsize ws;
1352
1353 if (ioctl(1, TIOCGWINSZ, &ws) != -1 && ws.ws_col >= 5)
1354 ScreenWidth = ws.ws_col - 1;
1355 #endif
1356 }
1357 /*}}}*/
1358
1359 int main(int argc,const char *argv[])
1360 {
1361 CommandLine::Args Args[] = {
1362 {'h',"help","help",0},
1363 {'v',"version","version",0},
1364 {'q',"quiet","quiet",CommandLine::IntLevel},
1365 {'q',"silent","quiet",CommandLine::IntLevel},
1366 {'d',"download-only","APT::Get::Download-Only",0},
1367 {'b',"compile","APT::Get::Compile",0},
1368 {'b',"build","APT::Get::Compile",0},
1369 {'s',"simulate","APT::Get::Simulate",0},
1370 {'s',"just-print","APT::Get::Simulate",0},
1371 {'s',"recon","APT::Get::Simulate",0},
1372 {'s',"no-act","APT::Get::Simulate",0},
1373 {'y',"yes","APT::Get::Assume-Yes",0},
1374 {'y',"assume-yes","APT::Get::Assume-Yes",0},
1375 {'f',"fix-broken","APT::Get::Fix-Broken",0},
1376 {'u',"show-upgraded","APT::Get::Show-Upgraded",0},
1377 {'m',"ignore-missing","APT::Get::Fix-Missing",0},
1378 {0,"fix-missing","APT::Get::Fix-Missing",0},
1379 {0,"ignore-hold","APT::Ingore-Hold",0},
1380 {0,"no-upgrade","APT::Get::no-upgrade",0},
1381 {0,"force-yes","APT::Get::force-yes",0},
1382 {0,"print-uris","APT::Get::Print-URIs",0},
1383 {'c',"config-file",0,CommandLine::ConfigFile},
1384 {'o',"option",0,CommandLine::ArbItem},
1385 {0,0,0,0}};
1386 CommandLine::Dispatch Cmds[] = {{"update",&DoUpdate},
1387 {"upgrade",&DoUpgrade},
1388 {"install",&DoInstall},
1389 {"remove",&DoInstall},
1390 {"dist-upgrade",&DoDistUpgrade},
1391 {"dselect-upgrade",&DoDSelectUpgrade},
1392 {"clean",&DoClean},
1393 {"autoclean",&DoAutoClean},
1394 {"check",&DoCheck},
1395 {"source",&DoSource},
1396 {"help",&ShowHelp},
1397 {0,0}};
1398
1399 // Parse the command line and initialize the package library
1400 CommandLine CmdL(Args,_config);
1401 if (pkgInitialize(*_config) == false ||
1402 CmdL.Parse(argc,argv) == false)
1403 {
1404 _error->DumpErrors();
1405 return 100;
1406 }
1407
1408 // See if the help should be shown
1409 if (_config->FindB("help") == true ||
1410 _config->FindB("version") == true ||
1411 CmdL.FileSize() == 0)
1412 return ShowHelp(CmdL);
1413
1414 // Deal with stdout not being a tty
1415 if (ttyname(STDOUT_FILENO) == 0 && _config->FindI("quiet",0) < 1)
1416 _config->Set("quiet","1");
1417
1418 // Setup the output streams
1419 c0out.rdbuf(cout.rdbuf());
1420 c1out.rdbuf(cout.rdbuf());
1421 c2out.rdbuf(cout.rdbuf());
1422 if (_config->FindI("quiet",0) > 0)
1423 c0out.rdbuf(devnull.rdbuf());
1424 if (_config->FindI("quiet",0) > 1)
1425 c1out.rdbuf(devnull.rdbuf());
1426
1427 // Setup the signals
1428 signal(SIGPIPE,SIG_IGN);
1429 signal(SIGWINCH,SigWinch);
1430 SigWinch(0);
1431
1432 // Match the operation
1433 CmdL.DispatchArg(Cmds);
1434
1435 // Print any errors or warnings found during parsing
1436 if (_error->empty() == false)
1437 {
1438 bool Errors = _error->PendingError();
1439 _error->DumpErrors();
1440 return Errors == true?100:0;
1441 }
1442
1443 return 0;
1444 }