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