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