]> git.saurik.com Git - apt.git/blob - cmdline/apt-cache.cc
Fixed typo in the shared lib rule
[apt.git] / cmdline / apt-cache.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: apt-cache.cc,v 1.32 1999/03/29 19:28:52 jgg Exp $
4 /* ######################################################################
5
6 apt-cache - Manages the cache files
7
8 apt-cache provides some functions fo manipulating the cache files.
9 It uses the command line interface common to all the APT tools. The
10 only really usefull function right now is dumpavail which is used
11 by the dselect method. Everything else is ment as a debug aide.
12
13 Returns 100 on failure, 0 on success.
14
15 ##################################################################### */
16 /*}}}*/
17 // Include Files /*{{{*/
18 #include <apt-pkg/error.h>
19 #include <apt-pkg/pkgcachegen.h>
20 #include <apt-pkg/deblistparser.h>
21 #include <apt-pkg/init.h>
22 #include <apt-pkg/progress.h>
23 #include <apt-pkg/sourcelist.h>
24 #include <apt-pkg/cmndline.h>
25 #include <apt-pkg/strutl.h>
26 #include <apt-pkg/pkgrecords.h>
27 #include <config.h>
28
29 #include <iostream.h>
30 #include <unistd.h>
31 #include <errno.h>
32 #include <regex.h>
33 /*}}}*/
34
35 pkgCache *GCache = 0;
36
37 // UnMet - Show unmet dependencies /*{{{*/
38 // ---------------------------------------------------------------------
39 /* */
40 bool UnMet(CommandLine &CmdL)
41 {
42 pkgCache &Cache = *GCache;
43 bool Important = _config->FindB("APT::Cache::Important",false);
44
45 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
46 {
47 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
48 {
49 bool Header = false;
50 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false;)
51 {
52 // Collect or groups
53 pkgCache::DepIterator Start;
54 pkgCache::DepIterator End;
55 D.GlobOr(Start,End);
56
57 /* cout << "s: Check " << Start.TargetPkg().Name() << ',' <<
58 End.TargetPkg().Name() << endl;*/
59
60 // Skip conflicts and replaces
61 if (End->Type != pkgCache::Dep::PreDepends &&
62 End->Type != pkgCache::Dep::Depends &&
63 End->Type != pkgCache::Dep::Suggests &&
64 End->Type != pkgCache::Dep::Recommends)
65 continue;
66
67 // Important deps only
68 if (Important == true)
69 if (End->Type != pkgCache::Dep::PreDepends &&
70 End->Type != pkgCache::Dep::Depends)
71 continue;
72
73 // Verify the or group
74 bool OK = false;
75 pkgCache::DepIterator RealStart = Start;
76 do
77 {
78 // See if this dep is Ok
79 pkgCache::Version **VList = Start.AllTargets();
80 if (*VList != 0)
81 {
82 OK = true;
83 delete [] VList;
84 break;
85 }
86 delete [] VList;
87
88 if (Start == End)
89 break;
90 Start++;
91 }
92 while (1);
93
94 // The group is OK
95 if (OK == true)
96 continue;
97
98 // Oops, it failed..
99 if (Header == false)
100 cout << "Package " << P.Name() << " version " <<
101 V.VerStr() << " has an unmet dep:" << endl;
102 Header = true;
103
104 // Print out the dep type
105 cout << " " << End.DepType() << ": ";
106
107 // Show the group
108 Start = RealStart;
109 do
110 {
111 cout << Start.TargetPkg().Name();
112 if (Start.TargetVer() != 0)
113 cout << " (" << Start.CompType() << " " << Start.TargetVer() <<
114 ")";
115 if (Start == End)
116 break;
117 cout << " | ";
118 Start++;
119 }
120 while (1);
121
122 cout << endl;
123 }
124 }
125 }
126 return true;
127 }
128 /*}}}*/
129 // DumpPackage - Show a dump of a package record /*{{{*/
130 // ---------------------------------------------------------------------
131 /* */
132 bool DumpPackage(CommandLine &CmdL)
133 {
134 pkgCache &Cache = *GCache;
135 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
136 {
137 pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
138 if (Pkg.end() == true)
139 {
140 _error->Warning("Unable to locate package %s",*I);
141 continue;
142 }
143
144 cout << "Package: " << Pkg.Name() << endl;
145 cout << "Versions: ";
146 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
147 {
148 cout << Cur.VerStr();
149 for (pkgCache::VerFileIterator Vf = Cur.FileList(); Vf.end() == false; Vf++)
150 cout << "(" << Vf.File().FileName() << ")";
151 cout << ',';
152 }
153
154 cout << endl;
155
156 cout << "Reverse Depends: " << endl;
157 for (pkgCache::DepIterator D = Pkg.RevDependsList(); D.end() != true; D++)
158 cout << " " << D.ParentPkg().Name() << ',' << D.TargetPkg().Name() << endl;
159
160 cout << "Dependencies: " << endl;
161 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
162 {
163 cout << Cur.VerStr() << " - ";
164 for (pkgCache::DepIterator Dep = Cur.DependsList(); Dep.end() != true; Dep++)
165 cout << Dep.TargetPkg().Name() << " (" << (int)Dep->CompareOp << " " << Dep.TargetVer() << ") ";
166 cout << endl;
167 }
168
169 cout << "Provides: " << endl;
170 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
171 {
172 cout << Cur.VerStr() << " - ";
173 for (pkgCache::PrvIterator Prv = Cur.ProvidesList(); Prv.end() != true; Prv++)
174 cout << Prv.ParentPkg().Name() << " ";
175 cout << endl;
176 }
177 cout << "Reverse Provides: " << endl;
178 for (pkgCache::PrvIterator Prv = Pkg.ProvidesList(); Prv.end() != true; Prv++)
179 cout << Prv.OwnerPkg().Name() << " " << Prv.OwnerVer().VerStr();
180 cout << endl;
181
182 }
183
184 return true;
185 }
186 /*}}}*/
187 // Stats - Dump some nice statistics /*{{{*/
188 // ---------------------------------------------------------------------
189 /* */
190 bool Stats(CommandLine &Cmd)
191 {
192 pkgCache &Cache = *GCache;
193 cout << "Total Package Names : " << Cache.Head().PackageCount << " (" <<
194 SizeToStr(Cache.Head().PackageCount*Cache.Head().PackageSz) << ')' << endl;
195 pkgCache::PkgIterator I = Cache.PkgBegin();
196
197 int Normal = 0;
198 int Virtual = 0;
199 int NVirt = 0;
200 int DVirt = 0;
201 int Missing = 0;
202 for (;I.end() != true; I++)
203 {
204 if (I->VersionList != 0 && I->ProvidesList == 0)
205 {
206 Normal++;
207 continue;
208 }
209
210 if (I->VersionList != 0 && I->ProvidesList != 0)
211 {
212 NVirt++;
213 continue;
214 }
215
216 if (I->VersionList == 0 && I->ProvidesList != 0)
217 {
218 // Only 1 provides
219 if (I.ProvidesList()->NextProvides == 0)
220 {
221 DVirt++;
222 }
223 else
224 Virtual++;
225 continue;
226 }
227 if (I->VersionList == 0 && I->ProvidesList == 0)
228 {
229 Missing++;
230 continue;
231 }
232 }
233 cout << " Normal Packages: " << Normal << endl;
234 cout << " Pure Virtual Packages: " << Virtual << endl;
235 cout << " Single Virtual Packages: " << DVirt << endl;
236 cout << " Mixed Virtual Packages: " << NVirt << endl;
237 cout << " Missing: " << Missing << endl;
238
239 cout << "Total Distinct Versions: " << Cache.Head().VersionCount << " (" <<
240 SizeToStr(Cache.Head().VersionCount*Cache.Head().VersionSz) << ')' << endl;
241 cout << "Total Dependencies: " << Cache.Head().DependsCount << " (" <<
242 SizeToStr(Cache.Head().DependsCount*Cache.Head().DependencySz) << ')' << endl;
243
244 cout << "Total Ver/File relations: " << Cache.Head().VerFileCount << " (" <<
245 SizeToStr(Cache.Head().VerFileCount*Cache.Head().VerFileSz) << ')' << endl;
246 cout << "Total Provides Mappings: " << Cache.Head().ProvidesCount << " (" <<
247 SizeToStr(Cache.Head().ProvidesCount*Cache.Head().ProvidesSz) << ')' << endl;
248
249 // String list stats
250 unsigned long Size = 0;
251 unsigned long Count = 0;
252 for (pkgCache::StringItem *I = Cache.StringItemP + Cache.Head().StringList;
253 I!= Cache.StringItemP; I = Cache.StringItemP + I->NextItem)
254 {
255 Count++;
256 Size += strlen(Cache.StrP + I->String);
257 }
258 cout << "Total Globbed Strings: " << Count << " (" << SizeToStr(Size) << ')' << endl;
259
260 unsigned long Slack = 0;
261 for (int I = 0; I != 7; I++)
262 Slack += Cache.Head().Pools[I].ItemSize*Cache.Head().Pools[I].Count;
263 cout << "Total Slack space: " << SizeToStr(Slack) << endl;
264
265 unsigned long Total = 0;
266 Total = Slack + Size + Cache.Head().DependsCount*Cache.Head().DependencySz +
267 Cache.Head().VersionCount*Cache.Head().VersionSz +
268 Cache.Head().PackageCount*Cache.Head().PackageSz +
269 Cache.Head().VerFileCount*Cache.Head().VerFileSz +
270 Cache.Head().ProvidesCount*Cache.Head().ProvidesSz;
271 cout << "Total Space Accounted for: " << SizeToStr(Total) << endl;
272
273 return true;
274 }
275 /*}}}*/
276 // Check - Check some things about the cache /*{{{*/
277 // ---------------------------------------------------------------------
278 /* Debug aide mostly */
279 bool Check(CommandLine &Cmd)
280 {
281 pkgCache &Cache = *GCache;
282 pkgCache::PkgIterator Pkg = Cache.PkgBegin();
283 for (;Pkg.end() != true; Pkg++)
284 {
285 if (Pkg.Section() == 0 && Pkg->VersionList != 0)
286 cout << "Bad section " << Pkg.Name() << endl;
287
288 for (pkgCache::VerIterator Cur = Pkg.VersionList();
289 Cur.end() != true; Cur++)
290 {
291 if (Cur->Priority < 1 || Cur->Priority > 5)
292 cout << "Bad prio " << Pkg.Name() << ',' << Cur.VerStr() << " == " << (int)Cur->Priority << endl;
293 }
294 }
295 return true;
296 }
297 /*}}}*/
298 // Dump - show everything /*{{{*/
299 // ---------------------------------------------------------------------
300 /* */
301 bool Dump(CommandLine &Cmd)
302 {
303 pkgCache &Cache = *GCache;
304 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
305 {
306 cout << "Package: " << P.Name() << endl;
307 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
308 {
309 cout << " Version: " << V.VerStr() << endl;
310 cout << " File: " << V.FileList().File().FileName() << endl;
311 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; D++)
312 cout << " Depends: " << D.TargetPkg().Name() << ' ' << D.TargetVer() << endl;
313 }
314 }
315
316 for (pkgCache::PkgFileIterator F(Cache); F.end() == false; F++)
317 {
318 cout << "File: " << F.FileName() << endl;
319 cout << " Size: " << F->Size << endl;
320 cout << " ID: " << F->ID << endl;
321 cout << " Flags: " << F->Flags << endl;
322 cout << " Time: " << TimeRFC1123(F->mtime) << endl;
323 cout << " Archive: " << F.Archive() << endl;
324 cout << " Component: " << F.Component() << endl;
325 cout << " Version: " << F.Version() << endl;
326 cout << " Origin: " << F.Origin() << endl;
327 cout << " Label: " << F.Label() << endl;
328 cout << " Architecture: " << F.Architecture() << endl;
329 }
330
331 return true;
332 }
333 /*}}}*/
334 // GetCandidateVer - Returns the Candidate install version /*{{{*/
335 // ---------------------------------------------------------------------
336 /* This should really use the DepCache or something.. Copied from there.
337 Allow current is required to filter out the status file when emitting
338 an available file. */
339 static pkgCache::VerIterator GetCandidateVer(pkgCache::PkgIterator Pkg,
340 bool AllowCurrent = true)
341 {
342 /* Not source/not automatic versions cannot be a candidate version
343 unless they are already installed */
344 for (pkgCache::VerIterator I = Pkg.VersionList(); I.end() == false; I++)
345 {
346 if (Pkg.CurrentVer() == I && AllowCurrent == true)
347 return I;
348
349 for (pkgCache::VerFileIterator J = I.FileList(); J.end() == false; J++)
350 if ((J.File()->Flags & pkgCache::Flag::NotSource) == 0 &&
351 (J.File()->Flags & pkgCache::Flag::NotAutomatic) == 0)
352 return I;
353 }
354
355 return pkgCache::VerIterator(*GCache,0);
356 }
357 /*}}}*/
358 // DumpAvail - Print out the available list /*{{{*/
359 // ---------------------------------------------------------------------
360 /* This is needed to make dpkg --merge happy */
361 bool DumpAvail(CommandLine &Cmd)
362 {
363 pkgCache &Cache = *GCache;
364 unsigned char *Buffer = new unsigned char[Cache.HeaderP->MaxVerFileSize];
365
366 for (pkgCache::PkgFileIterator I = Cache.FileBegin(); I.end() == false; I++)
367 {
368 if ((I->Flags & pkgCache::Flag::NotSource) != 0)
369 continue;
370
371 if (I.IsOk() == false)
372 {
373 delete [] Buffer;
374 return _error->Error("Package file %s is out of sync.",I.FileName());
375 }
376
377 FileFd PkgF(I.FileName(),FileFd::ReadOnly);
378 if (_error->PendingError() == true)
379 {
380 delete [] Buffer;
381 return false;
382 }
383
384 /* Write all of the records from this package file, we search the entire
385 structure to find them */
386 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
387 {
388 // Find the proper version to use. We should probably use the DepCache.
389 pkgCache::VerIterator V = GetCandidateVer(P,false);
390
391 if (V.end() == true || V.FileList().File() != I)
392 continue;
393
394 // Read the record and then write it out again.
395 if (PkgF.Seek(V.FileList()->Offset) == false ||
396 PkgF.Read(Buffer,V.FileList()->Size) == false ||
397 write(STDOUT_FILENO,Buffer,V.FileList()->Size) != V.FileList()->Size)
398 {
399 delete [] Buffer;
400 return false;
401 }
402 }
403 }
404
405 return true;
406 }
407 /*}}}*/
408 // DoAdd - Perform an adding operation /*{{{*/
409 // ---------------------------------------------------------------------
410 /* */
411 bool DoAdd(CommandLine &CmdL)
412 {
413 // Make sure there is at least one argument
414 if (CmdL.FileSize() <= 1)
415 return _error->Error("You must give at least one file name");
416
417 // Open the cache
418 FileFd CacheF(_config->FindFile("Dir::Cache::pkgcache"),FileFd::WriteAny);
419 if (_error->PendingError() == true)
420 return false;
421
422 DynamicMMap Map(CacheF,MMap::Public);
423 if (_error->PendingError() == true)
424 return false;
425
426 OpTextProgress Progress(*_config);
427 pkgCacheGenerator Gen(Map,Progress);
428 if (_error->PendingError() == true)
429 return false;
430
431 unsigned long Length = CmdL.FileSize() - 1;
432 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
433 {
434 Progress.OverallProgress(I - CmdL.FileList,Length,1,"Generating cache");
435 Progress.SubProgress(Length);
436
437 // Do the merge
438 FileFd TagF(*I,FileFd::ReadOnly);
439 debListParser Parser(TagF);
440 if (_error->PendingError() == true)
441 return _error->Error("Problem opening %s",*I);
442
443 if (Gen.SelectFile(*I) == false)
444 return _error->Error("Problem with SelectFile");
445
446 if (Gen.MergeList(Parser) == false)
447 return _error->Error("Problem with MergeList");
448 }
449
450 Progress.Done();
451 GCache = &Gen.GetCache();
452 Stats(CmdL);
453
454 return true;
455 }
456 /*}}}*/
457 // DisplayRecord - Displays the complete record for the package /*{{{*/
458 // ---------------------------------------------------------------------
459 /* This displays the package record from the proper package index file.
460 It is not used by DumpAvail for performance reasons. */
461 bool DisplayRecord(pkgCache::VerIterator V)
462 {
463 // Find an appropriate file
464 pkgCache::VerFileIterator Vf = V.FileList();
465 for (; Vf.end() == false; Vf++)
466 if ((Vf.File()->Flags & pkgCache::Flag::NotSource) == 0)
467 break;
468 if (Vf.end() == true)
469 Vf = V.FileList();
470
471 // Check and load the package list file
472 pkgCache::PkgFileIterator I = Vf.File();
473 if (I.IsOk() == false)
474 return _error->Error("Package file %s is out of sync.",I.FileName());
475
476 FileFd PkgF(I.FileName(),FileFd::ReadOnly);
477 if (_error->PendingError() == true)
478 return false;
479
480 // Read the record and then write it out again.
481 unsigned char *Buffer = new unsigned char[GCache->HeaderP->MaxVerFileSize];
482 if (PkgF.Seek(V.FileList()->Offset) == false ||
483 PkgF.Read(Buffer,V.FileList()->Size) == false ||
484 write(STDOUT_FILENO,Buffer,V.FileList()->Size) != V.FileList()->Size)
485 {
486 delete [] Buffer;
487 return false;
488 }
489
490 delete [] Buffer;
491
492 return true;
493 }
494 /*}}}*/
495 // Search - Perform a search /*{{{*/
496 // ---------------------------------------------------------------------
497 /* This searches the package names and pacakge descriptions for a pattern */
498 bool Search(CommandLine &CmdL)
499 {
500 pkgCache &Cache = *GCache;
501 bool ShowFull = _config->FindB("APT::Cache::ShowFull",false);
502 bool NamesOnly = _config->FindB("APT::Cache::NamesOnly",false);
503
504 // Make sure there is at least one argument
505 if (CmdL.FileSize() != 2)
506 return _error->Error("You must give exactly one pattern");
507
508 // Compile the regex pattern
509 regex_t Pattern;
510 if (regcomp(&Pattern,CmdL.FileList[1],REG_EXTENDED | REG_ICASE |
511 REG_NOSUB) != 0)
512 return _error->Error("Regex compilation error");
513
514 // Create the text record parser
515 pkgRecords Recs(Cache);
516 if (_error->PendingError() == true)
517 return false;
518
519 // Search package names
520 pkgCache::PkgIterator I = Cache.PkgBegin();
521 for (;I.end() != true; I++)
522 {
523 // We search against the install version as that makes the most sense..
524 pkgCache::VerIterator V = GetCandidateVer(I);
525 if (V.end() == true)
526 continue;
527
528 pkgRecords::Parser &P = Recs.Lookup(V.FileList());
529
530 if (regexec(&Pattern,I.Name(),0,0,0) == 0 ||
531 (NamesOnly == false &&
532 regexec(&Pattern,P.LongDesc().c_str(),0,0,0) == 0))
533 {
534 if (ShowFull == true)
535 DisplayRecord(V);
536 else
537 cout << I.Name() << " - " << P.ShortDesc() << endl;
538 }
539 }
540
541 regfree(&Pattern);
542 return true;
543 }
544 /*}}}*/
545 // ShowPackage - Dump the package record to the screen /*{{{*/
546 // ---------------------------------------------------------------------
547 /* */
548 bool ShowPackage(CommandLine &CmdL)
549 {
550 pkgCache &Cache = *GCache;
551 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
552 {
553 pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
554 if (Pkg.end() == true)
555 {
556 _error->Warning("Unable to locate package %s",*I);
557 continue;
558 }
559
560 // Find the proper version to use. We should probably use the DepCache.
561 pkgCache::VerIterator V = GetCandidateVer(Pkg);
562 if (V.end() == true || V.FileList().end() == true)
563 continue;
564 if (DisplayRecord(V) == false)
565 return false;
566 }
567 return true;
568 }
569 /*}}}*/
570 // GenCaches - Call the main cache generator /*{{{*/
571 // ---------------------------------------------------------------------
572 /* */
573 bool GenCaches(CommandLine &Cmd)
574 {
575 OpTextProgress Progress(*_config);
576
577 pkgSourceList List;
578 List.ReadMainList();
579 return pkgMakeStatusCache(List,Progress);
580 }
581 /*}}}*/
582 // ShowHelp - Show a help screen /*{{{*/
583 // ---------------------------------------------------------------------
584 /* */
585 bool ShowHelp(CommandLine &Cmd)
586 {
587 cout << PACKAGE << ' ' << VERSION << " for " << ARCHITECTURE <<
588 " compiled on " << __DATE__ << " " << __TIME__ << endl;
589 if (_config->FindB("version") == true)
590 return 100;
591
592 cout << "Usage: apt-cache [options] command" << endl;
593 cout << " apt-cache [options] add file1 [file1 ...]" << endl;
594 cout << " apt-cache [options] showpkg pkg1 [pkg2 ...]" << endl;
595 cout << endl;
596 cout << "apt-cache is a low-level tool used to manipulate APT's binary" << endl;
597 cout << "cache files stored in " << _config->FindFile("Dir::Cache") << endl;
598 cout << "It is not ment for ordinary use only as a debug aide." << endl;
599 cout << endl;
600 cout << "Commands:" << endl;
601 cout << " add - Add an package file to the source cache" << endl;
602 cout << " gencaches - Build both the package and source cache" << endl;
603 cout << " showpkg - Show some general information for a single package" << endl;
604 cout << " stats - Show some basic statistics" << endl;
605 cout << " dump - Show the entire file in a terse form" << endl;
606 cout << " dumpavail - Print an available file to stdout" << endl;
607 cout << " unmet - Show unmet dependencies" << endl;
608 cout << " check - Check the cache a bit" << endl;
609 cout << " search - Search the package list for a regex pattern" << endl;
610 cout << " show - Show a readable record for the package" << endl;
611 cout << endl;
612 cout << "Options:" << endl;
613 cout << " -h This help text." << endl;
614 cout << " -p=? The package cache. [" << _config->FindFile("Dir::Cache::pkgcache") << ']' << endl;
615 cout << " -s=? The source cache. [" << _config->FindFile("Dir::Cache::srcpkgcache") << ']' << endl;
616 cout << " -q Disable progress indicator." << endl;
617 cout << " -i Show only important deps for the unmet command." << endl;
618 cout << " -c=? Read this configuration file" << endl;
619 cout << " -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp" << endl;
620 cout << "See the apt-cache(8) and apt.conf(5) manual pages for more information." << endl;
621 return 100;
622 }
623 /*}}}*/
624 // CacheInitialize - Initialize things for apt-cache /*{{{*/
625 // ---------------------------------------------------------------------
626 /* */
627 void CacheInitialize()
628 {
629 _config->Set("quiet",0);
630 _config->Set("help",false);
631 }
632 /*}}}*/
633
634 int main(int argc,const char *argv[])
635 {
636 CommandLine::Args Args[] = {
637 {'h',"help","help",0},
638 {'v',"version","version",0},
639 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg},
640 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg},
641 {'q',"quiet","quiet",CommandLine::IntLevel},
642 {'i',"important","APT::Cache::Important",0},
643 {'f',"full","APT::Cache::ShowFull",0},
644 {0,"names-only","APT::Cache::NamesOnly",0},
645 {'c',"config-file",0,CommandLine::ConfigFile},
646 {'o',"option",0,CommandLine::ArbItem},
647 {0,0,0,0}};
648 CommandLine::Dispatch CmdsA[] = {{"help",&ShowHelp},
649 {"add",&DoAdd},
650 {"gencaches",&GenCaches},
651 {0,0}};
652 CommandLine::Dispatch CmdsB[] = {{"showpkg",&DumpPackage},
653 {"stats",&Stats},
654 {"dump",&Dump},
655 {"dumpavail",&DumpAvail},
656 {"unmet",&UnMet},
657 {"check",&Check},
658 {"search",&Search},
659 {"show",&ShowPackage},
660 {0,0}};
661
662 CacheInitialize();
663
664 // Parse the command line and initialize the package library
665 CommandLine CmdL(Args,_config);
666 if (pkgInitialize(*_config) == false ||
667 CmdL.Parse(argc,argv) == false)
668 {
669 _error->DumpErrors();
670 return 100;
671 }
672
673 // See if the help should be shown
674 if (_config->FindB("help") == true ||
675 CmdL.FileSize() == 0)
676 return ShowHelp(CmdL);
677
678 // Deal with stdout not being a tty
679 if (ttyname(STDOUT_FILENO) == 0 && _config->FindI("quiet",0) < 1)
680 _config->Set("quiet","1");
681
682 if (CmdL.DispatchArg(CmdsA,false) == false && _error->PendingError() == false)
683 {
684 // Open the cache file
685 FileFd CacheF(_config->FindFile("Dir::Cache::pkgcache"),FileFd::ReadOnly);
686 MMap Map(CacheF,MMap::Public | MMap::ReadOnly);
687 if (_error->PendingError() == false)
688 {
689 pkgCache Cache(Map);
690 GCache = &Cache;
691 if (_error->PendingError() == false)
692 CmdL.DispatchArg(CmdsB);
693 }
694 }
695
696 // Print any errors or warnings found during parsing
697 if (_error->empty() == false)
698 {
699 bool Errors = _error->PendingError();
700 _error->DumpErrors();
701 return Errors == true?100:0;
702 }
703
704 return 0;
705 }