+ if (_error->PendingError() == true)
+ {
+ if (d->master != -1)
+ {
+ close(d->master);
+ d->master = -1;
+ }
+ if (d->slave != NULL)
+ {
+ free(d->slave);
+ d->slave = NULL;
+ }
+ _error->DumpErrors(std::cerr, GlobalError::DEBUG, false);
+ }
+ _error->RevertToStack();
+}
+void pkgDPkgPM::SetupSlavePtyMagic()
+{
+ if(d->master == -1 || d->slave == NULL)
+ return;
+
+ if (close(d->master) == -1)
+ _error->FatalE("close", "Closing master %d in child failed!", d->master);
+ d->master = -1;
+ if (setsid() == -1)
+ _error->FatalE("setsid", "Starting a new session for child failed!");
+
+ int const slaveFd = open(d->slave, O_RDWR | O_NOCTTY);
+ if (slaveFd == -1)
+ _error->FatalE("open", _("Can not write log (%s)"), _("Is /dev/pts mounted?"));
+ else if (ioctl(slaveFd, TIOCSCTTY, 0) < 0)
+ _error->FatalE("ioctl", "Setting TIOCSCTTY for slave fd %d failed!", slaveFd);
+ else
+ {
+ unsigned short i = 0;
+ if (d->direct_stdin == true)
+ ++i;
+ for (; i < 3; ++i)
+ if (dup2(slaveFd, i) == -1)
+ _error->FatalE("dup2", "Dupping %d to %d in child failed!", slaveFd, i);
+
+ if (d->tt_is_valid == true && tcsetattr(STDIN_FILENO, TCSANOW, &d->tt) < 0)
+ _error->FatalE("tcsetattr", "Setting in Setup via TCSANOW for slave fd %d failed!", slaveFd);
+ }
+
+ if (slaveFd != -1)
+ close(slaveFd);
+}
+void pkgDPkgPM::StopPtyMagic()
+{
+ if (d->slave != NULL)
+ free(d->slave);
+ d->slave = NULL;
+ if (d->protect_slave_from_dying != -1)
+ {
+ close(d->protect_slave_from_dying);
+ d->protect_slave_from_dying = -1;
+ }
+ if(d->master >= 0)
+ {
+ if (d->tt_is_valid == true && tcsetattr(STDIN_FILENO, TCSAFLUSH, &d->tt) == -1)
+ _error->FatalE("tcsetattr", "Setting in Stop via TCSAFLUSH for stdin failed!");
+ close(d->master);
+ d->master = -1;
+ }
+}
+
+// DPkgPM::Go - Run the sequence /*{{{*/
+// ---------------------------------------------------------------------
+/* This globs the operations and calls dpkg
+ *
+ * If it is called with a progress object apt will report the install
+ * progress to this object. It maps the dpkg states a package goes
+ * through to human readable (and i10n-able)
+ * names and calculates a percentage for each step.
+ */
+bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress)
+{
+ pkgPackageManager::SigINTStop = false;
+ d->progress = progress;
+
+ // Generate the base argument list for dpkg
+ std::vector<std::string> const sArgs = debSystem::GetDpkgBaseCommand();
+ std::vector<const char *> Args(sArgs.size(), NULL);
+ std::transform(sArgs.begin(), sArgs.end(), Args.begin(),
+ [](std::string const &s) { return s.c_str(); });
+ unsigned long long const StartSize = std::accumulate(sArgs.begin(), sArgs.end(), 0,
+ [](unsigned long long const i, std::string const &s) { return i + s.length(); });
+ size_t const BaseArgs = Args.size();
+
+ fd_set rfds;
+ struct timespec tv;
+
+ // FIXME: do we really need this limit when we have MaxArgBytes?
+ unsigned int const MaxArgs = _config->FindI("Dpkg::MaxArgs",32*1024);
+
+ // try to figure out the max environment size
+ int OSArgMax = sysconf(_SC_ARG_MAX);
+ if(OSArgMax < 0)
+ OSArgMax = 32*1024;
+ OSArgMax -= EnvironmentSize() - 2*1024;
+ unsigned int const MaxArgBytes = _config->FindI("Dpkg::MaxArgBytes", OSArgMax);
+ bool const NoTriggers = _config->FindB("DPkg::NoTriggers", false);
+
+ if (RunScripts("DPkg::Pre-Invoke") == false)
+ return false;
+
+ if (RunScriptsWithPkgs("DPkg::Pre-Install-Pkgs") == false)
+ return false;
+
+ // support subpressing of triggers processing for special
+ // cases like d-i that runs the triggers handling manually
+ bool const TriggersPending = _config->FindB("DPkg::TriggersPending", false);
+ if (_config->FindB("DPkg::ConfigurePending", true) == true)
+ List.push_back(Item(Item::ConfigurePending, PkgIterator()));
+
+ // for the progress
+ BuildPackagesProgressMap();
+
+ d->stdin_is_dev_null = false;
+
+ // create log
+ OpenLog();
+
+ bool dpkgMultiArch = debSystem::SupportsMultiArch();
+
+ // start pty magic before the loop
+ StartPtyMagic();
+
+ // Tell the progress that its starting and fork dpkg
+ d->progress->Start(d->master);
+
+ // this loop is runs once per dpkg operation
+ vector<Item>::const_iterator I = List.begin();
+ while (I != List.end())