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