383
420
TokSplitString(':', line, list, sizeof(list)/sizeof(list[0]));
384
421
if( list[0] == NULL || list[1] == NULL || list[2] == NULL)
386
if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
387
424
std::clog << "ignoring line: not enough ':'" << std::endl;
391
char *action = _strstrip(list[2]);
427
const char* const pkg = list[1];
428
const char* action = _strstrip(list[2]);
393
430
// 'processing' from dpkg looks like
394
431
// 'processing: action: pkg'
395
432
if(strncmp(list[0], "processing", strlen("processing")) == 0)
398
char *pkg_or_trigger = _strstrip(list[2]);
399
action =_strstrip( list[1]);
435
const char* const pkg_or_trigger = _strstrip(list[2]);
436
action = _strstrip( list[1]);
400
437
const std::pair<const char *, const char *> * const iter =
401
438
std::find_if(PackageProcessingOpsBegin,
402
439
PackageProcessingOpsEnd,
403
440
MatchProcessingOp(action));
404
441
if(iter == PackageProcessingOpsEnd)
406
if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
407
std::clog << "ignoring unknwon action: " << action << std::endl;
444
std::clog << "ignoring unknown action: " << action << std::endl;
410
447
snprintf(s, sizeof(s), _(iter->second), pkg_or_trigger);
513
550
dpkgbuf_pos = dpkgbuf+dpkgbuf_pos-p;
553
// DPkgPM::WriteHistoryTag /*{{{*/
554
void pkgDPkgPM::WriteHistoryTag(string tag, string value)
556
if (value.size() > 0)
558
// poor mans rstrip(", ")
559
if (value[value.size()-2] == ',' && value[value.size()-1] == ' ')
560
value.erase(value.size() - 2, 2);
561
fprintf(history_out, "%s: %s\n", tag.c_str(), value.c_str());
564
// DPkgPM::OpenLog /*{{{*/
517
565
bool pkgDPkgPM::OpenLog()
519
567
string logdir = _config->FindDir("Dir::Log");
520
568
if(not FileExists(logdir))
521
569
return _error->Error(_("Directory '%s' missing"), logdir.c_str());
573
time_t t = time(NULL);
574
struct tm *tmp = localtime(&t);
575
strftime(timestr, sizeof(timestr), "%F %T", tmp);
522
578
string logfile_name = flCombine(logdir,
523
579
_config->Find("Dir::Log::Terminal"));
524
580
if (!logfile_name.empty())
526
582
term_out = fopen(logfile_name.c_str(),"a");
583
if (term_out == NULL)
584
return _error->WarningE(_("Could not open file '%s'"), logfile_name.c_str());
527
586
chmod(logfile_name.c_str(), 0600);
528
// output current time
530
time_t t = time(NULL);
531
struct tm *tmp = localtime(&t);
532
strftime(outstr, sizeof(outstr), "%F %T", tmp);
533
fprintf(term_out, "\nLog started: ");
534
fprintf(term_out, "%s", outstr);
535
fprintf(term_out, "\n");
587
fprintf(term_out, "\nLog started: %s\n", timestr);
591
string history_name = flCombine(logdir,
592
_config->Find("Dir::Log::History"));
593
if (!history_name.empty())
595
history_out = fopen(history_name.c_str(),"a");
596
chmod(history_name.c_str(), 0644);
597
fprintf(history_out, "\nStart-Date: %s\n", timestr);
598
string remove, purge, install, upgrade, downgrade;
599
for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
601
if (Cache[I].NewInstall())
602
install += I.Name() + string(" (") + Cache[I].CandVersion + string("), ");
603
else if (Cache[I].Upgrade())
604
upgrade += I.Name() + string(" (") + Cache[I].CurVersion + string(", ") + Cache[I].CandVersion + string("), ");
605
else if (Cache[I].Downgrade())
606
downgrade += I.Name() + string(" (") + Cache[I].CurVersion + string(", ") + Cache[I].CandVersion + string("), ");
607
else if (Cache[I].Delete())
609
if ((Cache[I].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge)
610
purge += I.Name() + string(" (") + Cache[I].CurVersion + string("), ");
612
remove += I.Name() + string(" (") + Cache[I].CurVersion + string("), ");
615
WriteHistoryTag("Install", install);
616
WriteHistoryTag("Upgrade", upgrade);
617
WriteHistoryTag("Downgrade",downgrade);
618
WriteHistoryTag("Remove",remove);
619
WriteHistoryTag("Purge",purge);
626
// DPkg::CloseLog /*{{{*/
540
627
bool pkgDPkgPM::CloseLog()
630
time_t t = time(NULL);
631
struct tm *tmp = localtime(&t);
632
strftime(timestr, sizeof(timestr), "%F %T", tmp);
545
time_t t = time(NULL);
546
struct tm *tmp = localtime(&t);
547
strftime(outstr, sizeof(outstr), "%F %T", tmp);
548
636
fprintf(term_out, "Log ended: ");
549
fprintf(term_out, "%s", outstr);
637
fprintf(term_out, "%s", timestr);
550
638
fprintf(term_out, "\n");
551
639
fclose(term_out);
645
if (dpkg_error.size() > 0)
646
fprintf(history_out, "Error: %s\n", dpkg_error.c_str());
647
fprintf(history_out, "End-Date: %s\n", timestr);
558
655
// This implements a racy version of pselect for those architectures
559
656
// that don't have a working implementation.
611
719
{"unpacked",N_("Preparing to configure %s") },
612
720
{"half-configured", N_("Configuring %s") },
614
{"triggers-awaited", N_("Processing triggers for %s") },
615
{"triggers-pending", N_("Processing triggers for %s") },
617
721
{ "installed", N_("Installed %s")},
620
724
// Remove operation
622
726
{"half-configured", N_("Preparing for removal of %s")},
624
{"triggers-awaited", N_("Preparing for removal of %s")},
625
{"triggers-pending", N_("Preparing for removal of %s")},
627
727
{"half-installed", N_("Removing %s")},
628
728
{"config-files", N_("Removed %s")},
659
762
// this loop is runs once per operation
660
for (vector<Item>::iterator I = List.begin(); I != List.end();)
763
for (vector<Item>::const_iterator I = List.begin(); I != List.end();)
662
vector<Item>::iterator J = I;
663
for (; J != List.end() && J->Op == I->Op; J++);
765
// Do all actions with the same Op in one run
766
vector<Item>::const_iterator J = I;
767
if (TriggersPending == true)
768
for (; J != List.end(); J++)
772
if (J->Op != Item::TriggersPending)
774
vector<Item>::const_iterator T = J + 1;
775
if (T != List.end() && T->Op == I->Op)
780
for (; J != List.end() && J->Op == I->Op; J++)
665
783
// Generate the argument list
666
784
const char *Args[MaxArgs + 50];
786
// Now check if we are within the MaxArgs limit
788
// this code below is problematic, because it may happen that
789
// the argument list is split in a way that A depends on B
790
// and they are in the same "--configure A B" run
791
// - with the split they may now be configured in different
667
793
if (J - I > (signed)MaxArgs)
670
796
unsigned int n = 0;
671
797
unsigned long Size = 0;
672
string Tmp = _config->Find("Dir::Bin::dpkg","dpkg");
798
string const Tmp = _config->Find("Dir::Bin::dpkg","dpkg");
673
799
Args[n++] = Tmp.c_str();
674
800
Size += strlen(Args[n-1]);
777
924
sighandler_t old_SIGHUP = signal(SIGHUP,SIG_IGN);
779
926
struct termios tt;
780
struct termios tt_out;
781
927
struct winsize win;
785
// FIXME: setup sensible signal handling (*ick*)
787
tcgetattr(1, &tt_out);
788
ioctl(0, TIOCGWINSZ, (char *)&win);
789
if (openpty(&master, &slave, NULL, &tt_out, &win) < 0)
931
// if tcgetattr does not return zero there was a error
932
// and we do not do any pty magic
933
if (tcgetattr(0, &tt) == 0)
791
const char *s = _("Can not write log, openpty() "
792
"failed (/dev/pts not mounted?)\n");
793
fprintf(stderr, "%s",s);
794
fprintf(term_out, "%s",s);
800
rtt.c_lflag &= ~ECHO;
801
tcsetattr(0, TCSAFLUSH, &rtt);
935
ioctl(0, TIOCGWINSZ, (char *)&win);
936
if (openpty(&master, &slave, NULL, &tt, &win) < 0)
938
const char *s = _("Can not write log, openpty() "
939
"failed (/dev/pts not mounted?)\n");
940
fprintf(stderr, "%s",s);
942
fprintf(term_out, "%s",s);
948
rtt.c_lflag &= ~ECHO;
949
// block SIGTTOU during tcsetattr to prevent a hang if
950
// the process is a member of the background process group
951
// http://www.opengroup.org/onlinepubs/000095399/functions/tcsetattr.html
952
sigemptyset(&sigmask);
953
sigaddset(&sigmask, SIGTTOU);
954
sigprocmask(SIG_BLOCK,&sigmask, &original_sigmask);
955
tcsetattr(0, TCSAFLUSH, &rtt);
956
sigprocmask(SIG_SETMASK, &original_sigmask, 0);
806
962
_config->Set("APT::Keep-Fds::",fd[1]);
963
// send status information that we are about to fork dpkg
964
if(OutStatusFd > 0) {
965
ostringstream status;
966
status << "pmstatus:dpkg-exec:"
967
<< (PackagesDone/float(PackagesTotal)*100.0)
968
<< ":" << _("Running dpkg")
970
write(OutStatusFd, status.str().c_str(), status.str().size());
807
972
Child = ExecFork();
809
974
// This is the child
938
1111
// if it was set to "keep-dpkg-runing" then we won't return
939
1112
// here but keep the loop going and just report it as a error
941
bool stopOnError = _config->FindB("Dpkg::StopOnError",true);
1114
bool const stopOnError = _config->FindB("Dpkg::StopOnError",true);
944
1117
RunScripts("DPkg::Post-Invoke");
946
1119
if (WIFSIGNALED(Status) != 0 && WTERMSIG(Status) == SIGSEGV)
947
_error->Error("Sub-process %s received a segmentation fault.",Args[0]);
1120
strprintf(dpkg_error, "Sub-process %s received a segmentation fault.",Args[0]);
948
1121
else if (WIFEXITED(Status) != 0)
949
_error->Error("Sub-process %s returned an error code (%u)",Args[0],WEXITSTATUS(Status));
1122
strprintf(dpkg_error, "Sub-process %s returned an error code (%u)",Args[0],WEXITSTATUS(Status));
951
_error->Error("Sub-process %s exited unexpectedly",Args[0]);
1124
strprintf(dpkg_error, "Sub-process %s exited unexpectedly",Args[0]);
1126
if(dpkg_error.size() > 0)
1127
_error->Error(dpkg_error.c_str());