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