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