]> git.saurik.com Git - apt.git/blame - apt-private/private-output.cc
reimplement the last uses of sprintf
[apt.git] / apt-private / private-output.cc
CommitLineData
b9179170
MV
1// Include files /*{{{*/
2#include<config.h>
3
4#include <apt-pkg/configuration.h>
5#include <apt-pkg/strutl.h>
6#include <apt-pkg/error.h>
7#include <apt-pkg/cachefile.h>
8#include <apt-pkg/pkgrecords.h>
9#include <apt-pkg/policy.h>
453b82a3
DK
10#include <apt-pkg/depcache.h>
11#include <apt-pkg/pkgcache.h>
12#include <apt-pkg/cacheiterators.h>
b9179170 13
453b82a3
DK
14#include <apt-private/private-output.h>
15#include <apt-private/private-cachefile.h>
16
17#include <regex.h>
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
b9179170
MV
21#include <iomanip>
22#include <iostream>
b9179170
MV
23#include <langinfo.h>
24#include <unistd.h>
3163087b 25#include <signal.h>
d287a035 26#include <sys/ioctl.h>
b9179170 27
b9179170
MV
28#include <apti18n.h>
29 /*}}}*/
30
31using namespace std;
32
33std::ostream c0out(0);
34std::ostream c1out(0);
35std::ostream c2out(0);
36std::ofstream devnull("/dev/null");
3163087b
MV
37
38
b9179170
MV
39unsigned int ScreenWidth = 80 - 1; /* - 1 for the cursor */
40
3163087b
MV
41// SigWinch - Window size change signal handler /*{{{*/
42// ---------------------------------------------------------------------
43/* */
44static void SigWinch(int)
45{
46 // Riped from GNU ls
47#ifdef TIOCGWINSZ
48 struct winsize ws;
49
50 if (ioctl(1, TIOCGWINSZ, &ws) != -1 && ws.ws_col >= 5)
51 ScreenWidth = ws.ws_col - 1;
52#endif
53}
54 /*}}}*/
d9e518c6 55bool InitOutput(std::basic_streambuf<char> * const out) /*{{{*/
b9179170 56{
33b813ce
MV
57 if (!isatty(STDOUT_FILENO) && _config->FindI("quiet", -1) == -1)
58 _config->Set("quiet","1");
59
d9e518c6
DK
60 c0out.rdbuf(out);
61 c1out.rdbuf(out);
62 c2out.rdbuf(out);
b9179170
MV
63 if (_config->FindI("quiet",0) > 0)
64 c0out.rdbuf(devnull.rdbuf());
65 if (_config->FindI("quiet",0) > 1)
66 c1out.rdbuf(devnull.rdbuf());
67
3163087b
MV
68 // deal with window size changes
69 signal(SIGWINCH,SigWinch);
70 SigWinch(0);
71
b9179170
MV
72 if(!isatty(1))
73 {
74 _config->Set("APT::Color", "false");
75 _config->Set("APT::Color::Highlight", "");
76 _config->Set("APT::Color::Neutral", "");
77 } else {
78 // Colors
79 _config->CndSet("APT::Color::Highlight", "\x1B[32m");
80 _config->CndSet("APT::Color::Neutral", "\x1B[0m");
81
82 _config->CndSet("APT::Color::Red", "\x1B[31m");
83 _config->CndSet("APT::Color::Green", "\x1B[32m");
84 _config->CndSet("APT::Color::Yellow", "\x1B[33m");
85 _config->CndSet("APT::Color::Blue", "\x1B[34m");
86 _config->CndSet("APT::Color::Magenta", "\x1B[35m");
87 _config->CndSet("APT::Color::Cyan", "\x1B[36m");
88 _config->CndSet("APT::Color::White", "\x1B[37m");
89 }
90
91 return true;
92}
ee0167c4 93 /*}}}*/
65512241 94static std::string GetArchiveSuite(pkgCacheFile &/*CacheFile*/, pkgCache::VerIterator ver) /*{{{*/
b9179170
MV
95{
96 std::string suite = "";
2847bed0 97 if (ver && ver.FileList())
b9179170
MV
98 {
99 pkgCache::VerFileIterator VF = ver.FileList();
100 for (; VF.end() == false ; ++VF)
101 {
960975a1
MV
102 if(VF.File() == NULL || VF.File().Archive() == NULL)
103 suite = suite + "," + _("unknown");
104 else
105 suite = suite + "," + VF.File().Archive();
b9179170
MV
106 //suite = VF.File().Archive();
107 }
108 suite = suite.erase(0, 1);
109 }
110 return suite;
111}
ee0167c4 112 /*}}}*/
c3ccac92 113static std::string GetFlagsStr(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)/*{{{*/
b9179170
MV
114{
115 pkgDepCache *DepCache = CacheFile.GetDepCache();
116 pkgDepCache::StateCache &state = (*DepCache)[P];
117
118 std::string flags_str;
119 if (state.NowBroken())
120 flags_str = "B";
7d1b93d9 121 if (P.CurrentVer() && state.Upgradable() && state.CandidateVer != NULL)
b9179170
MV
122 flags_str = "g";
123 else if (P.CurrentVer() != NULL)
124 flags_str = "i";
125 else
126 flags_str = "-";
127 return flags_str;
128}
ee0167c4 129 /*}}}*/
c3ccac92 130static std::string GetCandidateVersion(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)/*{{{*/
b9179170
MV
131{
132 pkgPolicy *policy = CacheFile.GetPolicy();
133 pkgCache::VerIterator cand = policy->GetCandidateVer(P);
134
135 return cand ? cand.VerStr() : "(none)";
136}
ee0167c4 137 /*}}}*/
65512241 138static std::string GetInstalledVersion(pkgCacheFile &/*CacheFile*/, pkgCache::PkgIterator P)/*{{{*/
b9179170
MV
139{
140 pkgCache::VerIterator inst = P.CurrentVer();
141
142 return inst ? inst.VerStr() : "(none)";
143}
ee0167c4 144 /*}}}*/
65512241 145static std::string GetVersion(pkgCacheFile &/*CacheFile*/, pkgCache::VerIterator V)/*{{{*/
b9179170
MV
146{
147 pkgCache::PkgIterator P = V.ParentPkg();
148 if (V == P.CurrentVer())
149 {
14109555
MV
150 std::string inst_str = DeNull(V.VerStr());
151#if 0 // FIXME: do we want this or something like this?
b9179170
MV
152 pkgDepCache *DepCache = CacheFile.GetDepCache();
153 pkgDepCache::StateCache &state = (*DepCache)[P];
b9179170
MV
154 if (state.Upgradable())
155 return "**"+inst_str;
14109555 156#endif
b9179170
MV
157 return inst_str;
158 }
159
160 if(V)
161 return DeNull(V.VerStr());
162 return "(none)";
163}
ee0167c4 164 /*}}}*/
c3ccac92 165static std::string GetArchitecture(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)/*{{{*/
b9179170 166{
2409df55
DK
167 if (P->CurrentVer == 0)
168 {
169 pkgDepCache * const DepCache = CacheFile.GetDepCache();
170 pkgDepCache::StateCache const &state = (*DepCache)[P];
171 if (state.CandidateVer != NULL)
172 {
173 pkgCache::VerIterator const CandV(CacheFile, state.CandidateVer);
174 return CandV.Arch();
175 }
176 else
177 {
178 pkgCache::VerIterator const V = P.VersionList();
179 if (V.end() == false)
180 return V.Arch();
181 else
182 return P.Arch();
183 }
184 }
185 else
186 return P.CurrentVer().Arch();
b9179170 187}
ee0167c4 188 /*}}}*/
c3ccac92 189static std::string GetShortDescription(pkgCacheFile &CacheFile, pkgRecords &records, pkgCache::PkgIterator P)/*{{{*/
b9179170
MV
190{
191 pkgPolicy *policy = CacheFile.GetPolicy();
192
193 pkgCache::VerIterator ver;
194 if (P.CurrentVer())
195 ver = P.CurrentVer();
196 else
197 ver = policy->GetCandidateVer(P);
198
199 std::string ShortDescription = "(none)";
200 if(ver)
201 {
202 pkgCache::DescIterator Desc = ver.TranslatedDescription();
203 pkgRecords::Parser & parser = records.Lookup(Desc.FileList());
204
205 ShortDescription = parser.ShortDesc();
206 }
207 return ShortDescription;
208}
ee0167c4 209 /*}}}*/
1a68655d
DK
210static std::string GetLongDescription(pkgCacheFile &CacheFile, pkgRecords &records, pkgCache::PkgIterator P)/*{{{*/
211{
212 pkgPolicy *policy = CacheFile.GetPolicy();
213
214 pkgCache::VerIterator ver;
215 if (P->CurrentVer != 0)
216 ver = P.CurrentVer();
217 else
218 ver = policy->GetCandidateVer(P);
219
220 std::string const EmptyDescription = "(none)";
221 if(ver.end() == true)
222 return EmptyDescription;
223
224 pkgCache::DescIterator const Desc = ver.TranslatedDescription();
225 pkgRecords::Parser & parser = records.Lookup(Desc.FileList());
226 std::string const longdesc = parser.LongDesc();
227 if (longdesc.empty() == true)
228 return EmptyDescription;
229 return SubstVar(longdesc, "\n ", "\n ");
230}
231 /*}}}*/
ee0167c4 232void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records, /*{{{*/
1a68655d
DK
233 pkgCache::VerIterator const &V, std::ostream &out,
234 std::string const &format)
b9179170 235{
2409df55
DK
236 pkgCache::PkgIterator const P = V.ParentPkg();
237 pkgDepCache * const DepCache = CacheFile.GetDepCache();
238 pkgDepCache::StateCache const &state = (*DepCache)[P];
b9179170 239
2409df55 240 std::string output;
b9179170 241 if (_config->FindB("APT::Cmd::use-format", false))
2409df55
DK
242 output = _config->Find("APT::Cmd::format", "${db::Status-Abbrev} ${Package} ${Version} ${Origin} ${Description}");
243 else
1a68655d 244 output = format;
2409df55
DK
245
246 // FIXME: some of these names are really icky – and all is nowhere documented
247 output = SubstVar(output, "${db::Status-Abbrev}", GetFlagsStr(CacheFile, P));
248 output = SubstVar(output, "${Package}", P.Name());
249 std::string const ArchStr = GetArchitecture(CacheFile, P);
250 output = SubstVar(output, "${Architecture}", ArchStr);
251 std::string const InstalledVerStr = GetInstalledVersion(CacheFile, P);
252 output = SubstVar(output, "${installed:Version}", InstalledVerStr);
253 std::string const CandidateVerStr = GetCandidateVersion(CacheFile, P);
254 output = SubstVar(output, "${candidate:Version}", CandidateVerStr);
255 std::string const VersionStr = GetVersion(CacheFile, V);
256 output = SubstVar(output, "${Version}", VersionStr);
257 output = SubstVar(output, "${Origin}", GetArchiveSuite(CacheFile, V));
258
259 std::string StatusStr = "";
260 if (P->CurrentVer != 0)
261 {
262 if (P.CurrentVer() == V)
7d1b93d9 263 {
2409df55
DK
264 if (state.Upgradable() && state.CandidateVer != NULL)
265 strprintf(StatusStr, _("[installed,upgradable to: %s]"),
266 CandidateVerStr.c_str());
267 else if (V.Downloadable() == false)
268 StatusStr = _("[installed,local]");
269 else if(V.Automatic() == true && state.Garbage == true)
270 StatusStr = _("[installed,auto-removable]");
271 else if ((state.Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto)
272 StatusStr = _("[installed,automatic]");
273 else
274 StatusStr = _("[installed]");
b9179170 275 }
2409df55
DK
276 else if (state.CandidateVer == V && state.Upgradable())
277 strprintf(StatusStr, _("[upgradable from: %s]"),
278 InstalledVerStr.c_str());
279 }
280 else if (V.ParentPkg()->CurrentState == pkgCache::State::ConfigFiles)
281 StatusStr = _("[residual-config]");
282 output = SubstVar(output, "${apt:Status}", StatusStr);
283 output = SubstVar(output, "${color:highlight}", _config->Find("APT::Color::Highlight", ""));
284 output = SubstVar(output, "${color:neutral}", _config->Find("APT::Color::Neutral", ""));
2409df55 285 output = SubstVar(output, "${Description}", GetShortDescription(CacheFile, records, P));
1a68655d
DK
286 output = SubstVar(output, "${LongDescription}", GetLongDescription(CacheFile, records, P));
287 output = SubstVar(output, "${ }${ }", "${ }");
288 output = SubstVar(output, "${ }\n", "\n");
289 output = SubstVar(output, "${ }", " ");
290 if (APT::String::Endswith(output, " ") == true)
291 output.erase(output.length() - 1);
2409df55
DK
292
293 out << output;
b9179170 294}
ee0167c4 295 /*}}}*/
b9179170
MV
296// ShowList - Show a list /*{{{*/
297// ---------------------------------------------------------------------
298/* This prints out a string of space separated words with a title and
299 a two space indent line wraped to the current screen width. */
300bool ShowList(ostream &out,string Title,string List,string VersionsList)
301{
302 if (List.empty() == true)
303 return true;
304 // trim trailing space
305 int NonSpace = List.find_last_not_of(' ');
306 if (NonSpace != -1)
307 {
308 List = List.erase(NonSpace + 1);
309 if (List.empty() == true)
310 return true;
311 }
312
313 // Acount for the leading space
314 int ScreenWidth = ::ScreenWidth - 3;
315
316 out << Title << endl;
317 string::size_type Start = 0;
318 string::size_type VersionsStart = 0;
319 while (Start < List.size())
320 {
321 if(_config->FindB("APT::Get::Show-Versions",false) == true &&
322 VersionsList.size() > 0) {
323 string::size_type End;
324 string::size_type VersionsEnd;
325
326 End = List.find(' ',Start);
327 VersionsEnd = VersionsList.find('\n', VersionsStart);
328
329 out << " " << string(List,Start,End - Start) << " (" <<
330 string(VersionsList,VersionsStart,VersionsEnd - VersionsStart) <<
331 ")" << endl;
332
333 if (End == string::npos || End < Start)
334 End = Start + ScreenWidth;
335
336 Start = End + 1;
337 VersionsStart = VersionsEnd + 1;
338 } else {
339 string::size_type End;
340
341 if (Start + ScreenWidth >= List.size())
342 End = List.size();
343 else
344 End = List.rfind(' ',Start+ScreenWidth);
345
346 if (End == string::npos || End < Start)
347 End = Start + ScreenWidth;
348 out << " " << string(List,Start,End - Start) << endl;
349 Start = End + 1;
350 }
351 }
352
353 return false;
354}
355 /*}}}*/
356// ShowBroken - Debugging aide /*{{{*/
357// ---------------------------------------------------------------------
358/* This prints out the names of all the packages that are broken along
359 with the name of each each broken dependency and a quite version
360 description.
361
362 The output looks like:
363 The following packages have unmet dependencies:
364 exim: Depends: libc6 (>= 2.1.94) but 2.1.3-10 is to be installed
365 Depends: libldap2 (>= 2.0.2-2) but it is not going to be installed
366 Depends: libsasl7 but it is not going to be installed
367 */
d39d7f88 368static void ShowBrokenPackage(ostream &out, pkgCacheFile * const Cache, pkgCache::PkgIterator const &Pkg, bool const Now)
b9179170 369{
d39d7f88
DK
370 if (Now == true)
371 {
372 if ((*Cache)[Pkg].NowBroken() == false)
373 return;
374 }
375 else
376 {
377 if ((*Cache)[Pkg].InstBroken() == false)
378 return;
379 }
380
381 // Print out each package and the failed dependencies
382 out << " " << Pkg.FullName(true) << " :";
383 unsigned const Indent = Pkg.FullName(true).size() + 3;
384 bool First = true;
385 pkgCache::VerIterator Ver;
386
387 if (Now == true)
388 Ver = Pkg.CurrentVer();
389 else
390 Ver = (*Cache)[Pkg].InstVerIter(*Cache);
391
392 if (Ver.end() == true)
393 {
394 out << endl;
b9179170 395 return;
d39d7f88 396 }
b9179170 397
d39d7f88 398 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false;)
b9179170 399 {
d39d7f88
DK
400 // Compute a single dependency element (glob or)
401 pkgCache::DepIterator Start;
402 pkgCache::DepIterator End;
403 D.GlobOr(Start,End); // advances D
404
405 if ((*Cache)->IsImportantDep(End) == false)
406 continue;
407
b9179170
MV
408 if (Now == true)
409 {
d39d7f88 410 if (((*Cache)[End] & pkgDepCache::DepGNow) == pkgDepCache::DepGNow)
b9179170
MV
411 continue;
412 }
413 else
414 {
d39d7f88 415 if (((*Cache)[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
b9179170
MV
416 continue;
417 }
d39d7f88
DK
418
419 bool FirstOr = true;
420 while (1)
b9179170 421 {
d39d7f88
DK
422 if (First == false)
423 for (unsigned J = 0; J != Indent; J++)
424 out << ' ';
425 First = false;
b9179170 426
d39d7f88 427 if (FirstOr == false)
b9179170 428 {
d39d7f88
DK
429 for (unsigned J = 0; J != strlen(End.DepType()) + 3; J++)
430 out << ' ';
b9179170
MV
431 }
432 else
d39d7f88
DK
433 out << ' ' << End.DepType() << ": ";
434 FirstOr = false;
435
436 out << Start.TargetPkg().FullName(true);
437
438 // Show a quick summary of the version requirements
439 if (Start.TargetVer() != 0)
440 out << " (" << Start.CompType() << " " << Start.TargetVer() << ")";
441
442 /* Show a summary of the target package if possible. In the case
443 of virtual packages we show nothing */
444 pkgCache::PkgIterator Targ = Start.TargetPkg();
445 if (Targ->ProvidesList == 0)
b9179170 446 {
d39d7f88
DK
447 out << ' ';
448 pkgCache::VerIterator Ver = (*Cache)[Targ].InstVerIter(*Cache);
449 if (Now == true)
450 Ver = Targ.CurrentVer();
b9179170 451
d39d7f88 452 if (Ver.end() == false)
b9179170 453 {
d39d7f88
DK
454 if (Now == true)
455 ioprintf(out,_("but %s is installed"),Ver.VerStr());
456 else
457 ioprintf(out,_("but %s is to be installed"),Ver.VerStr());
b9179170
MV
458 }
459 else
b9179170 460 {
d39d7f88 461 if ((*Cache)[Targ].CandidateVerIter(*Cache).end() == true)
b9179170 462 {
d39d7f88
DK
463 if (Targ->ProvidesList == 0)
464 out << _("but it is not installable");
b9179170 465 else
d39d7f88
DK
466 out << _("but it is a virtual package");
467 }
b9179170 468 else
d39d7f88 469 out << (Now?_("but it is not installed"):_("but it is not going to be installed"));
b9179170 470 }
d39d7f88
DK
471 }
472
473 if (Start != End)
474 out << _(" or");
475 out << endl;
476
477 if (Start == End)
478 break;
479 ++Start;
480 }
481 }
482}
483void ShowBroken(ostream &out, CacheFile &Cache, bool const Now)
484{
485 if (Cache->BrokenCount() == 0)
486 return;
487
488 out << _("The following packages have unmet dependencies:") << endl;
489 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
490 {
491 pkgCache::PkgIterator const I(Cache,Cache.List[J]);
492 ShowBrokenPackage(out, &Cache, I, Now);
493 }
494}
495void ShowBroken(ostream &out, pkgCacheFile &Cache, bool const Now)
496{
497 if (Cache->BrokenCount() == 0)
498 return;
499
500 out << _("The following packages have unmet dependencies:") << endl;
501 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
502 ShowBrokenPackage(out, &Cache, Pkg, Now);
b9179170
MV
503}
504 /*}}}*/
505// ShowNew - Show packages to newly install /*{{{*/
506// ---------------------------------------------------------------------
507/* */
508void ShowNew(ostream &out,CacheFile &Cache)
509{
510 /* Print out a list of packages that are going to be installed extra
511 to what the user asked */
512 string List;
513 string VersionsList;
514 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
515 {
516 pkgCache::PkgIterator I(Cache,Cache.List[J]);
517 if (Cache[I].NewInstall() == true) {
518 List += I.FullName(true) + " ";
519 VersionsList += string(Cache[I].CandVersion) + "\n";
520 }
521 }
522
523 ShowList(out,_("The following NEW packages will be installed:"),List,VersionsList);
524}
525 /*}}}*/
526// ShowDel - Show packages to delete /*{{{*/
527// ---------------------------------------------------------------------
528/* */
529void ShowDel(ostream &out,CacheFile &Cache)
530{
531 /* Print out a list of packages that are going to be removed extra
532 to what the user asked */
533 string List;
534 string VersionsList;
535 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
536 {
537 pkgCache::PkgIterator I(Cache,Cache.List[J]);
538 if (Cache[I].Delete() == true)
539 {
540 if ((Cache[I].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge)
541 List += I.FullName(true) + "* ";
542 else
543 List += I.FullName(true) + " ";
544
545 VersionsList += string(Cache[I].CandVersion)+ "\n";
546 }
547 }
548
549 ShowList(out,_("The following packages will be REMOVED:"),List,VersionsList);
550}
551 /*}}}*/
552// ShowKept - Show kept packages /*{{{*/
553// ---------------------------------------------------------------------
554/* */
555void ShowKept(ostream &out,CacheFile &Cache)
556{
557 string List;
558 string VersionsList;
559 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
560 {
561 pkgCache::PkgIterator I(Cache,Cache.List[J]);
562
563 // Not interesting
564 if (Cache[I].Upgrade() == true || Cache[I].Upgradable() == false ||
565 I->CurrentVer == 0 || Cache[I].Delete() == true)
566 continue;
567
568 List += I.FullName(true) + " ";
569 VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
570 }
571 ShowList(out,_("The following packages have been kept back:"),List,VersionsList);
572}
573 /*}}}*/
574// ShowUpgraded - Show upgraded packages /*{{{*/
575// ---------------------------------------------------------------------
576/* */
577void ShowUpgraded(ostream &out,CacheFile &Cache)
578{
579 string List;
580 string VersionsList;
581 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
582 {
583 pkgCache::PkgIterator I(Cache,Cache.List[J]);
584
585 // Not interesting
586 if (Cache[I].Upgrade() == false || Cache[I].NewInstall() == true)
587 continue;
588
589 List += I.FullName(true) + " ";
590 VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
591 }
592 ShowList(out,_("The following packages will be upgraded:"),List,VersionsList);
593}
594 /*}}}*/
595// ShowDowngraded - Show downgraded packages /*{{{*/
596// ---------------------------------------------------------------------
597/* */
598bool ShowDowngraded(ostream &out,CacheFile &Cache)
599{
600 string List;
601 string VersionsList;
602 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
603 {
604 pkgCache::PkgIterator I(Cache,Cache.List[J]);
605
606 // Not interesting
607 if (Cache[I].Downgrade() == false || Cache[I].NewInstall() == true)
608 continue;
609
610 List += I.FullName(true) + " ";
611 VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
612 }
613 return ShowList(out,_("The following packages will be DOWNGRADED:"),List,VersionsList);
614}
615 /*}}}*/
616// ShowHold - Show held but changed packages /*{{{*/
617// ---------------------------------------------------------------------
618/* */
619bool ShowHold(ostream &out,CacheFile &Cache)
620{
621 string List;
622 string VersionsList;
623 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
624 {
625 pkgCache::PkgIterator I(Cache,Cache.List[J]);
626 if (Cache[I].InstallVer != (pkgCache::Version *)I.CurrentVer() &&
627 I->SelectedState == pkgCache::State::Hold) {
628 List += I.FullName(true) + " ";
629 VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
630 }
631 }
632
633 return ShowList(out,_("The following held packages will be changed:"),List,VersionsList);
634}
635 /*}}}*/
636// ShowEssential - Show an essential package warning /*{{{*/
637// ---------------------------------------------------------------------
638/* This prints out a warning message that is not to be ignored. It shows
639 all essential packages and their dependents that are to be removed.
640 It is insanely risky to remove the dependents of an essential package! */
641bool ShowEssential(ostream &out,CacheFile &Cache)
642{
643 string List;
644 string VersionsList;
645 bool *Added = new bool[Cache->Head().PackageCount];
646 for (unsigned int I = 0; I != Cache->Head().PackageCount; I++)
647 Added[I] = false;
648
649 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
650 {
651 pkgCache::PkgIterator I(Cache,Cache.List[J]);
652 if ((I->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential &&
653 (I->Flags & pkgCache::Flag::Important) != pkgCache::Flag::Important)
654 continue;
655
656 // The essential package is being removed
657 if (Cache[I].Delete() == true)
658 {
659 if (Added[I->ID] == false)
660 {
661 Added[I->ID] = true;
662 List += I.FullName(true) + " ";
663 //VersionsList += string(Cache[I].CurVersion) + "\n"; ???
664 }
665 }
666 else
667 continue;
668
669 if (I->CurrentVer == 0)
670 continue;
671
672 // Print out any essential package depenendents that are to be removed
673 for (pkgCache::DepIterator D = I.CurrentVer().DependsList(); D.end() == false; ++D)
674 {
675 // Skip everything but depends
676 if (D->Type != pkgCache::Dep::PreDepends &&
677 D->Type != pkgCache::Dep::Depends)
678 continue;
679
680 pkgCache::PkgIterator P = D.SmartTargetPkg();
681 if (Cache[P].Delete() == true)
682 {
683 if (Added[P->ID] == true)
684 continue;
685 Added[P->ID] = true;
686
687 char S[300];
688 snprintf(S,sizeof(S),_("%s (due to %s) "),P.FullName(true).c_str(),I.FullName(true).c_str());
689 List += S;
690 //VersionsList += "\n"; ???
691 }
692 }
693 }
694
695 delete [] Added;
696 return ShowList(out,_("WARNING: The following essential packages will be removed.\n"
697 "This should NOT be done unless you know exactly what you are doing!"),List,VersionsList);
698}
699
700 /*}}}*/
701// Stats - Show some statistics /*{{{*/
702// ---------------------------------------------------------------------
703/* */
704void Stats(ostream &out,pkgDepCache &Dep)
705{
706 unsigned long Upgrade = 0;
707 unsigned long Downgrade = 0;
708 unsigned long Install = 0;
709 unsigned long ReInstall = 0;
710 for (pkgCache::PkgIterator I = Dep.PkgBegin(); I.end() == false; ++I)
711 {
712 if (Dep[I].NewInstall() == true)
713 Install++;
714 else
715 {
716 if (Dep[I].Upgrade() == true)
717 Upgrade++;
718 else
719 if (Dep[I].Downgrade() == true)
720 Downgrade++;
721 }
722
723 if (Dep[I].Delete() == false && (Dep[I].iFlags & pkgDepCache::ReInstall) == pkgDepCache::ReInstall)
724 ReInstall++;
725 }
726
727 ioprintf(out,_("%lu upgraded, %lu newly installed, "),
728 Upgrade,Install);
729
730 if (ReInstall != 0)
731 ioprintf(out,_("%lu reinstalled, "),ReInstall);
732 if (Downgrade != 0)
733 ioprintf(out,_("%lu downgraded, "),Downgrade);
734
735 ioprintf(out,_("%lu to remove and %lu not upgraded.\n"),
736 Dep.DelCount(),Dep.KeepCount());
737
738 if (Dep.BadCount() != 0)
739 ioprintf(out,_("%lu not fully installed or removed.\n"),
740 Dep.BadCount());
741}
742 /*}}}*/
743// YnPrompt - Yes No Prompt. /*{{{*/
744// ---------------------------------------------------------------------
745/* Returns true on a Yes.*/
746bool YnPrompt(bool Default)
747{
748 /* nl_langinfo does not support LANGUAGE setting, so we unset it here
749 to have the help-message (hopefully) match the expected characters */
750 char * language = getenv("LANGUAGE");
751 if (language != NULL)
752 language = strdup(language);
753 if (language != NULL)
754 unsetenv("LANGUAGE");
755
756 if (Default == true)
757 // TRANSLATOR: Yes/No question help-text: defaulting to Y[es]
758 // e.g. "Do you want to continue? [Y/n] "
759 // The user has to answer with an input matching the
760 // YESEXPR/NOEXPR defined in your l10n.
761 c2out << " " << _("[Y/n]") << " " << std::flush;
762 else
763 // TRANSLATOR: Yes/No question help-text: defaulting to N[o]
764 // e.g. "Should this file be removed? [y/N] "
765 // The user has to answer with an input matching the
766 // YESEXPR/NOEXPR defined in your l10n.
767 c2out << " " << _("[y/N]") << " " << std::flush;
768
769 if (language != NULL)
770 {
771 setenv("LANGUAGE", language, 0);
772 free(language);
773 }
774
775 if (_config->FindB("APT::Get::Assume-Yes",false) == true)
776 {
777 // TRANSLATOR: "Yes" answer printed for a yes/no question if --assume-yes is set
778 c1out << _("Y") << std::endl;
779 return true;
780 }
781 else if (_config->FindB("APT::Get::Assume-No",false) == true)
782 {
783 // TRANSLATOR: "No" answer printed for a yes/no question if --assume-no is set
784 c1out << _("N") << std::endl;
785 return false;
786 }
787
788 char response[1024] = "";
789 std::cin.getline(response, sizeof(response));
790
791 if (!std::cin)
792 return false;
793
794 if (strlen(response) == 0)
795 return Default;
796
797 regex_t Pattern;
798 int Res;
799
800 Res = regcomp(&Pattern, nl_langinfo(YESEXPR),
801 REG_EXTENDED|REG_ICASE|REG_NOSUB);
802
803 if (Res != 0) {
804 char Error[300];
805 regerror(Res,&Pattern,Error,sizeof(Error));
806 return _error->Error(_("Regex compilation error - %s"),Error);
807 }
808
809 Res = regexec(&Pattern, response, 0, NULL, 0);
810 if (Res == 0)
811 return true;
812 return false;
813}
814 /*}}}*/
815// AnalPrompt - Annoying Yes No Prompt. /*{{{*/
816// ---------------------------------------------------------------------
817/* Returns true on a Yes.*/
818bool AnalPrompt(const char *Text)
819{
820 char Buf[1024];
821 std::cin.getline(Buf,sizeof(Buf));
822 if (strcmp(Buf,Text) == 0)
823 return true;
824 return false;
825}
826 /*}}}*/