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