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