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