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