#include <sys/wait.h>
#include <signal.h>
#include <errno.h>
+#include <string.h>
#include <stdio.h>
+#include <string.h>
+#include <algorithm>
#include <sstream>
#include <map>
using namespace std;
-
+namespace
+{
+ // Maps the dpkg "processing" info to human readable names. Entry 0
+ // of each array is the key, entry 1 is the value.
+ const std::pair<const char *, const char *> PackageProcessingOps[] = {
+ std::make_pair("install", N_("Installing %s")),
+ std::make_pair("configure", N_("Configuring %s")),
+ std::make_pair("remove", N_("Removing %s")),
+ std::make_pair("trigproc", N_("Running post-installation trigger %s"))
+ };
+
+ const std::pair<const char *, const char *> * const PackageProcessingOpsBegin = PackageProcessingOps;
+ const std::pair<const char *, const char *> * const PackageProcessingOpsEnd = PackageProcessingOps + sizeof(PackageProcessingOps) / sizeof(PackageProcessingOps[0]);
+
+ // Predicate to test whether an entry in the PackageProcessingOps
+ // array matches a string.
+ class MatchProcessingOp
+ {
+ const char *target;
+
+ public:
+ MatchProcessingOp(const char *the_target)
+ : target(the_target)
+ {
+ }
+
+ bool operator()(const std::pair<const char *, const char *> &pair) const
+ {
+ return strcmp(pair.first, target) == 0;
+ }
+ };
+}
// DPkgPM::pkgDPkgPM - Constructor /*{{{*/
// ---------------------------------------------------------------------
'processing: trigproc: trigger'
*/
- char* list[5];
+ char* list[6];
// dpkg sends multiline error messages sometimes (see
// #374195 for a example. we should support this by
// either patching dpkg to not send multiline over the
if(strncmp(list[0], "processing", strlen("processing")) == 0)
{
char s[200];
- map<string,string>::iterator iter;
char *pkg_or_trigger = _strstrip(list[2]);
action =_strstrip( list[1]);
- iter = PackageProcessingOps.find(action);
- if(iter == PackageProcessingOps.end())
+ const std::pair<const char *, const char *> * const iter =
+ std::find_if(PackageProcessingOpsBegin,
+ PackageProcessingOpsEnd,
+ MatchProcessingOp(action));
+ if(iter == PackageProcessingOpsEnd)
{
if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
std::clog << "ignoring unknwon action: " << action << std::endl;
return;
}
- snprintf(s, sizeof(s), _(iter->second.c_str()), pkg_or_trigger);
+ snprintf(s, sizeof(s), _(iter->second), pkg_or_trigger);
status << "pmstatus:" << pkg_or_trigger
<< ":" << (PackagesDone/float(PackagesTotal)*100.0)
// urgs, sometime has ":" in its error string so that we
// end up with the error message split between list[3]
// and list[4], e.g. the message:
- // failed in buffer_write(fd) (10, ret=-1): backend dpkg-deb ...
+ // "failed in buffer_write(fd) (10, ret=-1): backend dpkg-deb ..."
// concat them again
- if( list[4] != NULL)
- list[4][-1] = ':';
+ if( list[4] != NULL )
+ list[3][strlen(list[3])] = ':';
status << "pmerror:" << list[1]
<< ":" << (PackagesDone/float(PackagesTotal)*100.0)
*/
bool pkgDPkgPM::Go(int OutStatusFd)
{
+ fd_set rfds;
+ struct timespec tv;
+ sigset_t sigmask;
+ sigset_t original_sigmask;
+
unsigned int MaxArgs = _config->FindI("Dpkg::MaxArgs",8*1024);
unsigned int MaxArgBytes = _config->FindI("Dpkg::MaxArgBytes",32*1024);
bool NoTriggers = _config->FindB("DPkg::NoTriggers",false);
},
};
- // populate the "processing" map
- PackageProcessingOps.insert( make_pair("install",N_("Installing %s")) );
- PackageProcessingOps.insert( make_pair("configure",N_("Configuring %s")) );
- PackageProcessingOps.insert( make_pair("remove",N_("Removing %s")) );
- PackageProcessingOps.insert( make_pair("trigproc",N_("Running post-installation trigger %s")) );
-
// init the PackageOps map, go over the list of packages that
// that will be [installed|configured|removed|purged] and add
// them to the PackageOps map (the dpkg states it goes through)
sighandler_t old_SIGQUIT = signal(SIGQUIT,SIG_IGN);
sighandler_t old_SIGINT = signal(SIGINT,SIG_IGN);
+ // ignore SIGHUP as well (debian #463030)
+ sighandler_t old_SIGHUP = signal(SIGHUP,SIG_IGN);
+
struct termios tt;
- struct termios tt_out;
struct winsize win;
int master;
int slave;
// FIXME: setup sensible signal handling (*ick*)
tcgetattr(0, &tt);
- tcgetattr(1, &tt_out);
ioctl(0, TIOCGWINSZ, (char *)&win);
- if (openpty(&master, &slave, NULL, &tt_out, &win) < 0)
+ if (openpty(&master, &slave, NULL, &tt, &win) < 0)
{
const char *s = _("Can not write log, openpty() "
"failed (/dev/pts not mounted?)\n");
rtt = tt;
cfmakeraw(&rtt);
rtt.c_lflag &= ~ECHO;
+ // block SIGTTOU during tcsetattr to prevent a hang if
+ // the process is a member of the background process group
+ // http://www.opengroup.org/onlinepubs/000095399/functions/tcsetattr.html
+ sigemptyset(&sigmask);
+ sigaddset(&sigmask, SIGTTOU);
+ sigprocmask(SIG_BLOCK,&sigmask, &original_sigmask);
tcsetattr(0, TCSAFLUSH, &rtt);
+ sigprocmask(SIG_SETMASK, &original_sigmask, 0);
}
// Fork dpkg
close(slave);
// setups fds
- fd_set rfds;
- struct timespec tv;
- sigset_t sigmask;
- sigset_t original_sigmask;
sigemptyset(&sigmask);
sigprocmask(SIG_BLOCK,&sigmask,&original_sigmask);
// Restore sig int/quit
signal(SIGQUIT,old_SIGQUIT);
signal(SIGINT,old_SIGINT);
+ signal(SIGHUP,old_SIGHUP);
return _error->Errno("waitpid","Couldn't wait for subprocess");
}
// wait for input or output here
// Restore sig int/quit
signal(SIGQUIT,old_SIGQUIT);
signal(SIGINT,old_SIGINT);
+ signal(SIGHUP,old_SIGHUP);
if(master >= 0)
{
if (RunScripts("DPkg::Post-Invoke") == false)
return false;
+
+ Cache.writeStateFile(NULL);
return true;
}
/*}}}*/
return;
}
+ // do not report disk-full failures
+ if(strstr(errormsg, strerror(ENOSPC)) != NULL) {
+ std::clog << _("No apport report written because the error message indicates a disk full error") << std::endl;
+ return;
+ }
+
+ // do not report out-of-memory failures
+ if(strstr(errormsg, strerror(ENOMEM)) != NULL) {
+ std::clog << _("No apport report written because the error message indicates a out of memory error") << std::endl;
+ return;
+ }
+
// get the pkgname and reportfile
pkgname = flNotDir(pkgpath);
pos = pkgname.find('_');
fclose(log);
}
}
+
+ // log the ordering
+ const char *ops_str[] = {"Install", "Configure","Remove","Purge"};
+ fprintf(report, "AptOrdering:\n");
+ for (vector<Item>::iterator I = List.begin(); I != List.end(); I++)
+ fprintf(report, " %s: %s\n", (*I).Pkg.Name(), ops_str[(*I).Op]);
+
+ // attach dmesg log (to learn about segfaults)
+ if (FileExists("/bin/dmesg"))
+ {
+ FILE *log = NULL;
+ char buf[1024];
+
+ fprintf(report, "Dmesg:\n");
+ log = popen("/bin/dmesg","r");
+ if(log != NULL)
+ {
+ while( fgets(buf, sizeof(buf), log) != NULL)
+ fprintf(report, " %s", buf);
+ fclose(log);
+ }
+ }
fclose(report);
+
}
/*}}}*/