summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorKarel Klic <kklic@redhat.com>2009-11-19 10:14:27 +0100
committerKarel Klic <kklic@redhat.com>2009-11-19 10:14:27 +0100
commitbd60681c8227bc31ef0991e98a9a3e849032c924 (patch)
tree5d4f3cf03d54ecb30ab863c7cc349bfcd232346c /lib
parent0ecc573a8ba79bca8e37809c41f92f0b629149e8 (diff)
parent83aea71df4761ec10c0d947055e65102bcace489 (diff)
downloadabrt-bd60681c8227bc31ef0991e98a9a3e849032c924.tar.gz
abrt-bd60681c8227bc31ef0991e98a9a3e849032c924.tar.xz
abrt-bd60681c8227bc31ef0991e98a9a3e849032c924.zip
Merge branch 'master' of ssh://git.fedorahosted.org/git/abrt
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.am2
-rw-r--r--lib/Plugins/Bugzilla.cpp5
-rw-r--r--lib/Plugins/CCpp.conf5
-rw-r--r--lib/Plugins/CCpp.cpp197
-rw-r--r--lib/Plugins/CCpp.h1
-rw-r--r--lib/Plugins/Catcut.cpp4
-rw-r--r--lib/Plugins/Firefox.cpp1022
-rw-r--r--lib/Plugins/Firefox.h51
-rw-r--r--lib/Plugins/Kerneloops.cpp2
-rw-r--r--lib/Plugins/KerneloopsReporter.cpp2
-rw-r--r--lib/Plugins/KerneloopsScanner.cpp4
-rw-r--r--lib/Plugins/Logger.cpp2
-rw-r--r--lib/Plugins/Mailx.cpp183
-rw-r--r--lib/Plugins/Mailx.h10
-rw-r--r--lib/Plugins/Makefile.am12
-rw-r--r--lib/Plugins/Python.cpp2
-rw-r--r--lib/Plugins/RunApp.cpp39
-rw-r--r--lib/Plugins/SOSreport.cpp2
-rw-r--r--lib/Plugins/SQLite3.cpp4
-rw-r--r--lib/Plugins/TicketUploader.cpp49
-rw-r--r--lib/Python/Makefile.am5
-rw-r--r--lib/Python/PyABRTUtils.cpp248
-rw-r--r--lib/Python/PyBindingGenerator.py27
-rw-r--r--lib/Python/PyDebugDump.cpp248
-rw-r--r--lib/Utils/CommLayerInner.cpp2
-rw-r--r--lib/Utils/DebugDump.cpp8
-rw-r--r--lib/Utils/Makefile.am2
-rw-r--r--lib/Utils/make_descr.cpp2
-rw-r--r--lib/Utils/stringops.cpp25
29 files changed, 1382 insertions, 783 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 6be37e8..459e270 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -1 +1 @@
-SUBDIRS = Utils Plugins Python
+SUBDIRS = Utils Plugins \ No newline at end of file
diff --git a/lib/Plugins/Bugzilla.cpp b/lib/Plugins/Bugzilla.cpp
index 06f9334..7ddacf7 100644
--- a/lib/Plugins/Bugzilla.cpp
+++ b/lib/Plugins/Bugzilla.cpp
@@ -16,7 +16,7 @@
static void create_new_bug_description(const map_crash_report_t& pCrashReport, std::string& pDescription)
{
- pDescription = "abrt detected a crash.\n\n";
+ pDescription = "abrt "VERSION" detected a crash.\n\n";
pDescription += make_description_bz(pCrashReport);
}
@@ -527,8 +527,7 @@ PLUGIN_INFO(REPORTER,
CReporterBugzilla,
"Bugzilla",
"0.0.4",
- "Check if a bug isn't already reported in a bugzilla "
- "and if not, report it.",
+ "Reports bugs to bugzilla",
"npajkovs@redhat.com",
"https://fedorahosted.org/abrt/wiki",
PLUGINS_LIB_DIR"/Bugzilla.GTKBuilder");
diff --git a/lib/Plugins/CCpp.conf b/lib/Plugins/CCpp.conf
index 988ddf3..459dff8 100644
--- a/lib/Plugins/CCpp.conf
+++ b/lib/Plugins/CCpp.conf
@@ -12,6 +12,11 @@ DebugInfo = install
# debuginfos will be installed to @@LOCALSTATEDIR@@/cache/abrt-di
InstallDebugInfo = yes
+# Additional directories to search for debuginfos.
+# For example, you can list a network-mounted shared store
+# of all debuginfos here.
+# ReadonlyLocalDebugInfoDirs = /path1:/path2:...
+
# Keep @@LOCALSTATEDIR@@/cache/abrt-di
# from growing out-of-bounds.
DebugInfoCacheMB = 4000
diff --git a/lib/Plugins/CCpp.cpp b/lib/Plugins/CCpp.cpp
index 82c5677..83b0e9a 100644
--- a/lib/Plugins/CCpp.cpp
+++ b/lib/Plugins/CCpp.cpp
@@ -33,6 +33,8 @@
#include "CommLayerInner.h"
#include "Polkit.h"
+using namespace std;
+
#define CORE_PATTERN_IFACE "/proc/sys/kernel/core_pattern"
#define CORE_PATTERN "|"CCPP_HOOK_PATH" "DEBUG_DUMPS_DIR" %p %s %u"
@@ -48,9 +50,9 @@ CAnalyzerCCpp::CAnalyzerCCpp() :
m_nDebugInfoCacheMB(4000)
{}
-static std::string CreateHash(const std::string& pInput)
+static string CreateHash(const char *pInput)
{
- std::string ret = "";
+ string ret;
HASHContext* hc;
unsigned char hash[SHA1_LENGTH];
unsigned int len;
@@ -61,7 +63,7 @@ static std::string CreateHash(const std::string& pInput)
error_msg_and_die("HASH_Create(HASH_AlgSHA1) failed"); /* paranoia */
}
HASH_Begin(hc);
- HASH_Update(hc, reinterpret_cast<const unsigned char*>(pInput.c_str()), pInput.length());
+ HASH_Update(hc, (const unsigned char*)pInput, strlen(pInput));
HASH_End(hc, hash, &len, sizeof(hash));
HASH_Destroy(hc);
@@ -80,9 +82,9 @@ static std::string CreateHash(const std::string& pInput)
return hash_str;
}
-static std::string concat_str_vector(char **strings)
+static string concat_str_vector(char **strings)
{
- std::string result;
+ string result;
while (*strings)
{
result += *strings++;
@@ -92,7 +94,7 @@ static std::string concat_str_vector(char **strings)
return result;
}
-static pid_t ExecVP(char** pArgs, uid_t uid, std::string& pOutput)
+static pid_t ExecVP(char** pArgs, uid_t uid, string& pOutput)
{
int pipeout[2];
pid_t child;
@@ -100,7 +102,7 @@ static pid_t ExecVP(char** pArgs, uid_t uid, std::string& pOutput)
struct passwd* pw = getpwuid(uid);
if (!pw)
{
- throw CABRTException(EXCEP_PLUGIN, std::string(__func__) + ": cannot get GID for UID.");
+ throw CABRTException(EXCEP_PLUGIN, string(__func__) + ": cannot get GID for UID.");
}
xpipe(pipeout);
@@ -217,7 +219,7 @@ static int rate_backtrace(const char *backtrace)
{
if (backtrace[i] == '#') /* this separates frames from each other */
{
- std::string s(backtrace + i + 1, len);
+ string s(backtrace + i + 1, len);
for (j=0; j<len; j++) /* replace tabs with spaces */
if (s[j] == '\t')
s[j] = ' ';
@@ -249,12 +251,12 @@ static int rate_backtrace(const char *backtrace)
return 0;
}
-static void GetBacktrace(const char *pDebugDumpDir, std::string& pBacktrace)
+static void GetBacktrace(const char *pDebugDumpDir, const char *pDebugInfoDirs, string& pBacktrace)
{
update_client(_("Getting backtrace..."));
- std::string UID;
- std::string executable;
+ string UID;
+ string executable;
{
CDebugDump dd;
dd.Open(pDebugDumpDir);
@@ -270,10 +272,24 @@ static void GetBacktrace(const char *pDebugDumpDir, std::string& pBacktrace)
char* args[11];
args[0] = (char*)"gdb";
args[1] = (char*)"-batch";
+
// when/if gdb supports it:
// (https://bugzilla.redhat.com/show_bug.cgi?id=528668):
args[2] = (char*)"-ex";
- args[3] = (char*)"set debug-file-directory /usr/lib/debug:" DEBUGINFO_CACHE_DIR"/usr/lib/debug";
+ string dfd = "set debug-file-directory /usr/lib/debug";
+ const char *p = pDebugInfoDirs;
+ while (1)
+ {
+ const char *colon_or_nul = strchrnul(p, ':');
+ dfd += ':';
+ dfd.append(p, colon_or_nul - p);
+ dfd += "/usr/lib/debug";
+ if (*colon_or_nul != ':')
+ break;
+ p = colon_or_nul + 1;
+ }
+ args[3] = (char*)dfd.c_str();
+
/*
* Unfortunately, "file BINARY_FILE" doesn't work well if BINARY_FILE
* was deleted (as often happens during system updates):
@@ -282,22 +298,23 @@ static void GetBacktrace(const char *pDebugDumpDir, std::string& pBacktrace)
* See https://bugzilla.redhat.com/show_bug.cgi?id=525721
*/
args[4] = (char*)"-ex";
- args[5] = xasprintf("file %s", executable.c_str());
+ string file = ssprintf("file %s", executable.c_str());
+ args[5] = (char*)file.c_str();
+
args[6] = (char*)"-ex";
- args[7] = xasprintf("core-file %s/"FILENAME_COREDUMP, pDebugDumpDir);
+ string corefile = ssprintf("core-file %s/"FILENAME_COREDUMP, pDebugDumpDir);
+ args[7] = (char*)corefile.c_str();
+
args[8] = (char*)"-ex";
args[9] = (char*)"thread apply all backtrace full";
args[10] = NULL;
ExecVP(args, atoi(UID.c_str()), pBacktrace);
-
- free(args[5]);
- free(args[7]);
}
-static std::string GetIndependentBacktrace(const std::string& pBacktrace)
+static string GetIndependentBacktrace(const char *pBacktrace)
{
- std::string header;
+ string header;
bool in_bracket = false;
bool in_quote = false;
bool in_header = false;
@@ -305,7 +322,7 @@ static std::string GetIndependentBacktrace(const std::string& pBacktrace)
bool has_at = false;
bool has_filename = false;
bool has_bracket = false;
- std::set<std::string> set_headers;
+ set<string> set_headers;
/* Backtrace example:
#0 0x00007f047e21af70 in __nanosleep_nocancel () from /lib64/libc-2.10.1.so
@@ -328,7 +345,7 @@ static std::string GetIndependentBacktrace(const std::string& pBacktrace)
seconds = 1260
ok = true
*/
- const char *bk = pBacktrace.c_str();
+ const char *bk = pBacktrace;
while (*bk)
{
if (bk[0] == '#'
@@ -348,11 +365,11 @@ static std::string GetIndependentBacktrace(const std::string& pBacktrace)
{
in_digit = true;
}
- else if (bk[0] == '\\' && bk[1] == '\"')
+ else if (bk[0] == '\\' && bk[1] == '"')
{
bk++;
}
- else if (*bk == '\"')
+ else if (*bk == '"')
{
in_quote = in_quote == true ? false : true;
}
@@ -406,8 +423,8 @@ static std::string GetIndependentBacktrace(const std::string& pBacktrace)
bk++;
}
- std::string pIndependentBacktrace;
- std::set<std::string>::iterator it = set_headers.begin();
+ string pIndependentBacktrace;
+ set<string>::iterator it = set_headers.begin();
for (; it != set_headers.end(); it++)
{
pIndependentBacktrace += *it;
@@ -416,39 +433,35 @@ static std::string GetIndependentBacktrace(const std::string& pBacktrace)
return pIndependentBacktrace;
}
-static void GetIndependentBuildIdPC(const std::string& pBuildIdPC, std::string& pIndependentBuildIdPC)
+static void GetIndependentBuildIdPC(const char *unstrip_n_output, string& pIndependentBuildIdPC)
{
- int ii = 0;
- while (ii < pBuildIdPC.length())
+ // lines look like this:
+ // 0x400000+0x209000 23c77451cf6adff77fc1f5ee2a01d75de6511dda@0x40024c - - [exe]
+ // 0x400000+0x209000 ab3c8286aac6c043fd1bb1cc2a0b88ec29517d3e@0x40024c /bin/sleep /usr/lib/debug/bin/sleep.debug [exe]
+ // 0x7fff313ff000+0x1000 389c7475e3d5401c55953a425a2042ef62c4c7df@0x7fff313ff2f8 . - linux-vdso.so.1
+ const char *line = unstrip_n_output;
+ while (*line)
{
- std::string line;
- int jj = 0;
-
- while (pBuildIdPC[ii] != '\n' && ii < pBuildIdPC.length())
- {
- line += pBuildIdPC[ii];
- ii++;
- }
- while (line[jj] != '+' && jj < line.length())
+ const char *eol = strchrnul(line, '\n');
+ const char *plus = (char*)memchr(line, '+', eol - line);
+ if (plus)
{
- jj++;
- }
- jj++;
- while (line[jj] != '@' && jj < line.length())
- {
- if (!isspace(line[jj]))
+ while (++plus < eol && *plus != '@')
{
- pIndependentBuildIdPC += line[jj];
+ if (!isspace(*plus))
+ {
+ pIndependentBuildIdPC += *plus;
+ }
}
- jj++;
}
- ii++;
+ if (*eol != '\n') break;
+ line = eol + 1;
}
}
-static std::string run_unstrip_n(const char *pDebugDumpDir)
+static string run_unstrip_n(const char *pDebugDumpDir)
{
- std::string UID;
+ string UID;
{
CDebugDump dd;
dd.Open(pDebugDumpDir);
@@ -461,7 +474,7 @@ static std::string run_unstrip_n(const char *pDebugDumpDir)
args[2] = (char*)"-n";
args[3] = NULL;
- std::string output;
+ string output;
ExecVP(args, atoi(UID.c_str()), output);
free(args[1]);
@@ -481,10 +494,10 @@ static bool is_hexstr(const char* str)
}
return true;
}
-static void InstallDebugInfos(const char *pDebugDumpDir, std::string& build_ids)
+static void InstallDebugInfos(const char *pDebugDumpDir, const char *debuginfo_dirs, string& build_ids)
{
log("Getting module names, file names, build IDs from core file");
- std::string unstrip_list = run_unstrip_n(pDebugDumpDir);
+ string unstrip_list = run_unstrip_n(pDebugDumpDir);
log("Builting list of missing debuginfos");
// lines look like this:
@@ -542,7 +555,7 @@ static void InstallDebugInfos(const char *pDebugDumpDir, std::string& build_ids)
}
//missing vector is unused for now, but TODO: use it to install only needed debuginfos
- std::string package;
+ string package;
{
CDebugDump dd;
dd.Open(pDebugDumpDir);
@@ -629,7 +642,7 @@ Another application is holding the yum lock, cannot continue
bool already_installed = false;
#endif
char buff[1024];
- std::string packageName = package.substr(0, package.rfind("-", package.rfind("-")-1));
+ string packageName = package.substr(0, package.rfind("-", package.rfind("-")-1));
while (fgets(buff, sizeof(buff), pipeout_fp))
{
int last = strlen(buff) - 1;
@@ -662,7 +675,7 @@ Another application is holding the yum lock, cannot continue
fclose(pipeout_fp);
kill(child, SIGTERM);
wait(NULL);
- throw CABRTException(EXCEP_PLUGIN, std::string(__func__) + ": cannot install debuginfos for " + pPackage);
+ throw CABRTException(EXCEP_PLUGIN, string(__func__) + ": cannot install debuginfos for " + pPackage);
}
#endif
}
@@ -674,7 +687,7 @@ Another application is holding the yum lock, cannot continue
/* Needs gdb feature from here: https://bugzilla.redhat.com/show_bug.cgi?id=528668
* It is slated to be in F12/RHEL6.
*/
-static void InstallDebugInfos(const char *pDebugDumpDir, std::string& build_ids)
+static void InstallDebugInfos(const char *pDebugDumpDir, const char *debuginfo_dirs, string& build_ids)
{
update_client(_("Searching for debug-info packages..."));
@@ -703,8 +716,8 @@ static void InstallDebugInfos(const char *pDebugDumpDir, std::string& build_ids)
/* SELinux guys are not happy with /tmp, using /var/run/abrt */
char *tempdir = xasprintf(LOCALSTATEDIR"/run/abrt/tmp-%u-%lu", (int)getpid(), (long)time(NULL));
/* log() goes to stderr/syslog, it's ok to use it here */
- VERB1 log("Executing: %s %s %s %s", "abrt-debuginfo-install", coredump, tempdir, DEBUGINFO_CACHE_DIR);
- execlp("abrt-debuginfo-install", "abrt-debuginfo-install", coredump, tempdir, DEBUGINFO_CACHE_DIR, NULL);
+ VERB1 log("Executing: %s %s %s %s", "abrt-debuginfo-install", coredump, tempdir, debuginfo_dirs);
+ execlp("abrt-debuginfo-install", "abrt-debuginfo-install", coredump, tempdir, debuginfo_dirs, NULL);
exit(1);
}
@@ -750,7 +763,7 @@ static void InstallDebugInfos(const char *pDebugDumpDir, std::string& build_ids)
wait(NULL);
}
-static double get_dir_size(const char *dirname, std::string *worst_file, double *maxsz)
+static double get_dir_size(const char *dirname, string *worst_file, double *maxsz)
{
DIR *dp = opendir(dirname);
if (dp == NULL)
@@ -763,7 +776,7 @@ static double get_dir_size(const char *dirname, std::string *worst_file, double
{
if (dot_or_dotdot(ep->d_name))
continue;
- std::string dname = concat_path_file(dirname, ep->d_name);
+ string dname = concat_path_file(dirname, ep->d_name);
if (lstat(dname.c_str(), &stats) != 0)
continue;
if (S_ISDIR(stats.st_mode))
@@ -801,7 +814,7 @@ static void trim_debuginfo_cache(unsigned max_mb)
{
while (1)
{
- std::string worst_file;
+ string worst_file;
double maxsz = 0;
double cache_sz = get_dir_size(DEBUGINFO_CACHE_DIR, &worst_file, &maxsz);
if (cache_sz / (1024 * 1024) < max_mb)
@@ -813,12 +826,12 @@ static void trim_debuginfo_cache(unsigned max_mb)
}
}
-std::string CAnalyzerCCpp::GetLocalUUID(const char *pDebugDumpDir)
+string CAnalyzerCCpp::GetLocalUUID(const char *pDebugDumpDir)
{
log(_("Getting local universal unique identification..."));
- std::string executable;
- std::string package;
+ string executable;
+ string package;
{
CDebugDump dd;
dd.Open(pDebugDumpDir);
@@ -826,19 +839,19 @@ std::string CAnalyzerCCpp::GetLocalUUID(const char *pDebugDumpDir)
dd.LoadText(FILENAME_PACKAGE, package);
}
- std::string buildIdPC = run_unstrip_n(pDebugDumpDir);
- std::string independentBuildIdPC;
- GetIndependentBuildIdPC(buildIdPC, independentBuildIdPC);
- return CreateHash(package + executable + independentBuildIdPC);
+ string unstrip_n_output = run_unstrip_n(pDebugDumpDir);
+ string independentBuildIdPC;
+ GetIndependentBuildIdPC(unstrip_n_output.c_str(), independentBuildIdPC);
+ return CreateHash((package + executable + independentBuildIdPC).c_str());
}
-std::string CAnalyzerCCpp::GetGlobalUUID(const char *pDebugDumpDir)
+string CAnalyzerCCpp::GetGlobalUUID(const char *pDebugDumpDir)
{
log(_("Getting global universal unique identification..."));
- std::string backtrace;
- std::string executable;
- std::string package;
+ string backtrace;
+ string executable;
+ string package;
{
CDebugDump dd;
dd.Open(pDebugDumpDir);
@@ -846,8 +859,8 @@ std::string CAnalyzerCCpp::GetGlobalUUID(const char *pDebugDumpDir)
dd.LoadText(FILENAME_EXECUTABLE, executable);
dd.LoadText(FILENAME_PACKAGE, package);
}
- std::string independentBacktrace = GetIndependentBacktrace(backtrace);
- return CreateHash(package + executable + independentBacktrace);
+ string independentBacktrace = GetIndependentBacktrace(backtrace.c_str());
+ return CreateHash((package + executable + independentBacktrace).c_str());
}
static bool DebuginfoCheckPolkit(int uid)
@@ -881,9 +894,9 @@ void CAnalyzerCCpp::CreateReport(const char *pDebugDumpDir, int force)
{
update_client(_("Starting report creation..."));
- std::string package;
- std::string backtrace;
- std::string UID;
+ string package;
+ string backtrace;
+ string UID;
CDebugDump dd;
dd.Open(pDebugDumpDir);
@@ -901,18 +914,21 @@ void CAnalyzerCCpp::CreateReport(const char *pDebugDumpDir, int force)
dd.LoadText(FILENAME_UID, UID);
dd.Close(); /* do not keep dir locked longer than needed */
- std::string build_ids;
- if (m_bInstallDebugInfo && DebuginfoCheckPolkit(atoi(UID.c_str()))) {
- if (m_nDebugInfoCacheMB > 0)
+ string build_ids;
+ if (m_bInstallDebugInfo && DebuginfoCheckPolkit(atoi(UID.c_str())))
+ {
+ if (m_nDebugInfoCacheMB > 0)
+ {
trim_debuginfo_cache(m_nDebugInfoCacheMB);
- InstallDebugInfos(pDebugDumpDir, build_ids);
+ }
+ InstallDebugInfos(pDebugDumpDir, m_sDebugInfoDirs.c_str(), build_ids);
}
else
{
VERB1 log(_("Skipping debuginfo installation"));
}
- GetBacktrace(pDebugDumpDir, backtrace);
+ GetBacktrace(pDebugDumpDir, m_sDebugInfoDirs.c_str(), backtrace);
dd.Open(pDebugDumpDir);
dd.SaveText(FILENAME_BACKTRACE, (build_ids + backtrace).c_str());
@@ -926,7 +942,7 @@ void CAnalyzerCCpp::CreateReport(const char *pDebugDumpDir, int force)
void CAnalyzerCCpp::Init()
{
- std::ifstream fInCorePattern;
+ ifstream fInCorePattern;
fInCorePattern.open(CORE_PATTERN_IFACE);
if (fInCorePattern.is_open())
{
@@ -951,22 +967,22 @@ void CAnalyzerCCpp::Init()
}
}
- std::ofstream fOutCorePattern;
+ ofstream fOutCorePattern;
fOutCorePattern.open(CORE_PATTERN_IFACE);
if (fOutCorePattern.is_open())
{
- fOutCorePattern << CORE_PATTERN << std::endl;
+ fOutCorePattern << CORE_PATTERN << endl;
fOutCorePattern.close();
}
}
void CAnalyzerCCpp::DeInit()
{
- std::ofstream fOutCorePattern;
+ ofstream fOutCorePattern;
fOutCorePattern.open(CORE_PATTERN_IFACE);
if (fOutCorePattern.is_open())
{
- fOutCorePattern << m_sOldCorePattern << std::endl;
+ fOutCorePattern << m_sOldCorePattern << endl;
fOutCorePattern.close();
}
}
@@ -999,6 +1015,13 @@ void CAnalyzerCCpp::SetSettings(const map_plugin_settings_t& pSettings)
{
m_bInstallDebugInfo = string_to_bool(it->second.c_str());
}
+ m_sDebugInfoDirs = DEBUGINFO_CACHE_DIR;
+ it = pSettings.find("ReadonlyLocalDebugInfoDirs");
+ if (it != end)
+ {
+ m_sDebugInfoDirs += ':';
+ m_sDebugInfoDirs += it->second;
+ }
}
//ok to delete?
@@ -1016,7 +1039,7 @@ PLUGIN_INFO(ANALYZER,
CAnalyzerCCpp,
"CCpp",
"0.0.1",
- "Simple C/C++ analyzer plugin.",
+ "Analyzes crashes in C/C++ programs",
"zprikryl@redhat.com",
"https://fedorahosted.org/abrt/wiki",
"");
diff --git a/lib/Plugins/CCpp.h b/lib/Plugins/CCpp.h
index 3fa0d99..26dedea 100644
--- a/lib/Plugins/CCpp.h
+++ b/lib/Plugins/CCpp.h
@@ -35,6 +35,7 @@ class CAnalyzerCCpp : public CAnalyzer
unsigned m_nDebugInfoCacheMB;
std::string m_sOldCorePattern;
std::string m_sDebugInfo;
+ std::string m_sDebugInfoDirs;
public:
CAnalyzerCCpp();
diff --git a/lib/Plugins/Catcut.cpp b/lib/Plugins/Catcut.cpp
index e6d16b4..cf1d7d9 100644
--- a/lib/Plugins/Catcut.cpp
+++ b/lib/Plugins/Catcut.cpp
@@ -33,7 +33,7 @@ static void create_new_bug_description(const map_crash_report_t& pCrashReport, s
"-----\n" +
pCrashReport.find(CD_COMMENT)->second[CD_CONTENT];
}
- pDescription = "\nabrt detected a crash.\n" +
+ pDescription = "\nabrt "VERSION" detected a crash.\n" +
howToReproduce +
comment +
"\n\nAdditional information\n"
@@ -573,7 +573,7 @@ PLUGIN_INFO(REPORTER,
CReporterCatcut,
"Catcut",
"0.0.1",
- "Test plugin to report bugs to catcut and if not, report it.",
+ "Reports bugs to catcut",
"dvlasenk@redhat.com",
"https://fedorahosted.org/abrt/wiki",
PLUGINS_LIB_DIR"/Catcut.GTKBuilder");
diff --git a/lib/Plugins/Firefox.cpp b/lib/Plugins/Firefox.cpp
new file mode 100644
index 0000000..68dbd39
--- /dev/null
+++ b/lib/Plugins/Firefox.cpp
@@ -0,0 +1,1022 @@
+/*
+ Firefox.cpp
+
+ Copyright (C) 2009 Zdenek Prikryl (zprikryl@redhat.com)
+ Copyright (C) 2009 RedHat inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <sys/wait.h>
+#include <fstream>
+#include <sstream>
+#include <set>
+#include <iomanip>
+#include <nss.h>
+#include <sechash.h>
+#include "abrtlib.h"
+#include "Firefox.h"
+#include "ABRTException.h"
+#include "DebugDump.h"
+#include "CommLayerInner.h"
+#include "Polkit.h"
+
+#define CORE_PATTERN_IFACE "/proc/sys/kernel/core_pattern"
+#define CORE_PATTERN "|"CCPP_HOOK_PATH" "DEBUG_DUMPS_DIR" %p %s %u"
+
+#define FILENAME_COREDUMP "coredump"
+#define FILENAME_BACKTRACE "backtrace"
+#define FILENAME_MEMORYMAP "memorymap"
+
+#define DEBUGINFO_CACHE_DIR LOCALSTATEDIR"/cache/abrt-di"
+
+CAnalyzerFirefox::CAnalyzerFirefox() :
+ m_bMemoryMap(false),
+ m_bInstallDebugInfo(true),
+ m_nDebugInfoCacheMB(4000)
+{}
+
+static std::string CreateHash(const std::string& pInput)
+{
+ std::string ret = "";
+ HASHContext* hc;
+ unsigned char hash[SHA1_LENGTH];
+ unsigned int len;
+
+ hc = HASH_Create(HASH_AlgSHA1);
+ if (!hc)
+ {
+ error_msg_and_die("HASH_Create(HASH_AlgSHA1) failed"); /* paranoia */
+ }
+ HASH_Begin(hc);
+ HASH_Update(hc, reinterpret_cast<const unsigned char*>(pInput.c_str()), pInput.length());
+ HASH_End(hc, hash, &len, sizeof(hash));
+ HASH_Destroy(hc);
+
+ char hash_str[SHA1_LENGTH*2 + 1];
+ char *d = hash_str;
+ unsigned char *s = hash;
+ while (len)
+ {
+ *d++ = "0123456789abcdef"[*s >> 4];
+ *d++ = "0123456789abcdef"[*s & 0xf];
+ s++;
+ len--;
+ }
+ *d = '\0';
+
+ return hash_str;
+}
+
+static std::string concat_str_vector(char **strings)
+{
+ std::string result;
+ while (*strings)
+ {
+ result += *strings++;
+ if (*strings)
+ result += ' ';
+ }
+ return result;
+}
+
+static pid_t ExecVP(char** pArgs, uid_t uid, std::string& pOutput)
+{
+ int pipeout[2];
+ pid_t child;
+
+ struct passwd* pw = getpwuid(uid);
+ if (!pw)
+ {
+ throw CABRTException(EXCEP_PLUGIN, std::string(__func__) + ": cannot get GID for UID.");
+ }
+
+ xpipe(pipeout);
+ child = fork();
+ if (child == -1)
+ {
+ perror_msg_and_die("fork");
+ }
+ if (child == 0)
+ {
+ VERB1 log("Executing: %s", concat_str_vector(pArgs).c_str());
+ close(pipeout[0]); /* read side of the pipe */
+ xmove_fd(pipeout[1], STDOUT_FILENO);
+ /* Make sure stdin is safely open to nothing */
+ close(STDIN_FILENO);
+ if (open("/dev/null", O_RDONLY))
+ if (open("/", O_RDONLY))
+ abort(); /* never happens */
+ /* Not a good idea, we won't see any error messages */
+ /* close(STDERR_FILENO); */
+
+ setgroups(1, &pw->pw_gid);
+ setregid(pw->pw_gid, pw->pw_gid);
+ setreuid(uid, uid);
+ setsid();
+
+ /* Nuke everything which may make setlocale() switch to non-POSIX locale:
+ * we need to avoid having gdb output in some obscure language.
+ */
+ unsetenv("LANG");
+ unsetenv("LC_ALL");
+ unsetenv("LC_COLLATE");
+ unsetenv("LC_CTYPE");
+ unsetenv("LC_MESSAGES");
+ unsetenv("LC_MONETARY");
+ unsetenv("LC_NUMERIC");
+ unsetenv("LC_TIME");
+
+ execvp(pArgs[0], pArgs);
+ /* VERB1 since sometimes we expect errors here */
+ VERB1 perror_msg("Can't execute '%s'", pArgs[0]);
+ exit(1);
+ }
+
+ close(pipeout[1]); /* write side of the pipe */
+
+ int r;
+ char buff[1024];
+ while ((r = read(pipeout[0], buff, sizeof(buff) - 1)) > 0)
+ {
+ buff[r] = '\0';
+ pOutput += buff;
+ }
+
+ close(pipeout[0]);
+ wait(NULL); /* prevent having zombie child process */
+
+ return 0;
+}
+
+enum LineRating
+{
+ // RATING EXAMPLE
+ MissingEverything = 0, // #0 0x0000dead in ?? ()
+ MissingFunction = 1, // #0 0x0000dead in ?? () from /usr/lib/libfoobar.so.4
+ MissingLibrary = 2, // #0 0x0000dead in foobar()
+ MissingSourceFile = 3, // #0 0x0000dead in FooBar::FooBar () from /usr/lib/libfoobar.so.4
+ Good = 4, // #0 0x0000dead in FooBar::crash (this=0x0) at /home/user/foobar.cpp:204
+ BestRating = Good,
+};
+
+static LineRating rate_line(const char *line)
+{
+#define FOUND(x) (strstr(line, x) != NULL)
+ /* see the "enum LineRating" comments for possible combinations */
+ if (FOUND(" at "))
+ return Good;
+ const char *function = strstr(line, " in ");
+ if (function)
+ {
+ if (function[4] == '?') /* " in ??" does not count */
+ {
+ function = NULL;
+ }
+ }
+ bool library = FOUND(" from ");
+ if (function && library)
+ return MissingSourceFile;
+ if (function)
+ return MissingLibrary;
+ if (library)
+ return MissingFunction;
+
+ return MissingEverything;
+#undef FOUND
+}
+
+/* returns number of "stars" to show */
+static int rate_backtrace(const char *backtrace)
+{
+ int i, j, len;
+ int multiplier = 0;
+ int rating = 0;
+ int best_possible_rating = 0;
+
+ /* We look at the frames in reversed order, since:
+ * - rate_line() checks starting from the first line of the frame
+ * (note: it may need to look at more than one line!)
+ * - we increase weight (multiplier) for every frame,
+ * so that topmost frames end up most important
+ */
+ len = 0;
+ for (i = strlen(backtrace) - 1; i >= 0; i--)
+ {
+ if (backtrace[i] == '#') /* this separates frames from each other */
+ {
+ std::string s(backtrace + i + 1, len);
+ for (j=0; j<len; j++) /* replace tabs with spaces */
+ if (s[j] == '\t')
+ s[j] = ' ';
+ multiplier++;
+ rating += rate_line(s.c_str()) * multiplier;
+ best_possible_rating += BestRating * multiplier;
+ len = 0; /* starting new line */
+ }
+ else
+ {
+ len++;
+ }
+ }
+
+ /* Bogus "backtrace" with zero frames? */
+ if (best_possible_rating == 0)
+ return 0;
+
+ /* Returning number of "stars" to show */
+ if (rating*10 >= best_possible_rating*8) /* >= 0.8 */
+ return 4;
+ if (rating*10 >= best_possible_rating*6)
+ return 3;
+ if (rating*10 >= best_possible_rating*4)
+ return 2;
+ if (rating*10 >= best_possible_rating*2)
+ return 1;
+
+ return 0;
+}
+
+static void GetBacktrace(const char *pDebugDumpDir, std::string& pBacktrace)
+{
+ update_client(_("Getting backtrace..."));
+
+ std::string UID;
+ std::string executable;
+ {
+ CDebugDump dd;
+ dd.Open(pDebugDumpDir);
+ dd.LoadText(FILENAME_EXECUTABLE, executable);
+ dd.LoadText(FILENAME_UID, UID);
+ }
+
+ // Workaround for
+ // http://sourceware.org/bugzilla/show_bug.cgi?id=9622
+ unsetenv("TERM");
+ putenv((char*)"TERM=dumb");
+
+ char* args[11];
+ args[0] = (char*)"gdb";
+ args[1] = (char*)"-batch";
+ // when/if gdb supports it:
+ // (https://bugzilla.redhat.com/show_bug.cgi?id=528668):
+ args[2] = (char*)"-ex";
+ args[3] = (char*)"set debug-file-directory /usr/lib/debug:" DEBUGINFO_CACHE_DIR"/usr/lib/debug";
+ /*
+ * Unfortunately, "file BINARY_FILE" doesn't work well if BINARY_FILE
+ * was deleted (as often happens during system updates):
+ * gdb uses specified BINARY_FILE
+ * even if it is completely unrelated to the coredump
+ * See https://bugzilla.redhat.com/show_bug.cgi?id=525721
+ */
+ args[4] = (char*)"-ex";
+ args[5] = xasprintf("file %s", executable.c_str());
+ args[6] = (char*)"-ex";
+ args[7] = xasprintf("core-file %s/"FILENAME_COREDUMP, pDebugDumpDir);
+ args[8] = (char*)"-ex";
+ args[9] = (char*)"thread apply all backtrace full";
+ args[10] = NULL;
+
+ ExecVP(args, atoi(UID.c_str()), pBacktrace);
+
+ free(args[5]);
+ free(args[7]);
+}
+
+static std::string GetIndependentBacktrace(const std::string& pBacktrace)
+{
+ std::string header;
+ bool in_bracket = false;
+ bool in_quote = false;
+ bool in_header = false;
+ bool in_digit = false;
+ bool has_at = false;
+ bool has_filename = false;
+ bool has_bracket = false;
+ std::set<std::string> set_headers;
+
+ /* Backtrace example:
+ #0 0x00007f047e21af70 in __nanosleep_nocancel () from /lib64/libc-2.10.1.so
+
+ Thread 1 (Thread 30750):
+ #0 0x00007f047e21af70 in __nanosleep_nocancel () from /lib64/libc-2.10.1.so
+ No symbol table info available.
+ #1 0x00000000004037bb in rpl_nanosleep (requested_delay=0x7fff8999e400,
+ remaining_delay=0x0) at nanosleep.c:69
+ r = -516
+ delay = {tv_sec = 1260, tv_nsec = 0}
+ t0 = {tv_sec = 12407, tv_nsec = 291505364}
+ #2 0x000000000040322b in xnanosleep (seconds=<value optimized out>)
+ at xnanosleep.c:112
+ overflow = false
+ ts_sleep = {tv_sec = 1260, tv_nsec = 0}
+ __PRETTY_FUNCTION__ = "xnanosleep"
+ #3 0x0000000000401779 in main (argc=2, argv=0x7fff8999e598) at sleep.c:147
+ i = 2
+ seconds = 1260
+ ok = true
+ */
+ const char *bk = pBacktrace.c_str();
+ while (*bk)
+ {
+ if (bk[0] == '#'
+ && bk[1] >= '0' && bk[1] <= '7'
+ && bk[2] == ' ' /* take only #0...#7 (8 last stack frames) */
+ && !in_quote
+ ) {
+ if (in_header && !has_filename)
+ {
+ header = "";
+ }
+ in_header = true;
+ }
+ if (in_header)
+ {
+ if (isdigit(*bk) && !in_quote && !has_at)
+ {
+ in_digit = true;
+ }
+ else if (bk[0] == '\\' && bk[1] == '\"')
+ {
+ bk++;
+ }
+ else if (*bk == '\"')
+ {
+ in_quote = in_quote == true ? false : true;
+ }
+ else if (*bk == '(' && !in_quote)
+ {
+ in_bracket = true;
+ in_digit = false;
+ header += '(';
+ }
+ else if (*bk == ')' && !in_quote)
+ {
+ in_bracket = false;
+ has_bracket = true;
+ in_digit = false;
+ header += ')';
+ }
+ else if (*bk == '\n' && has_filename)
+ {
+ set_headers.insert(header);
+ in_bracket = false;
+ in_quote = false;
+ in_header = false;
+ in_digit = false;
+ has_at = false;
+ has_filename = false;
+ has_bracket = false;
+ header = "";
+ }
+ else if (*bk == ',' && !in_quote)
+ {
+ in_digit = false;
+ }
+ else if (isspace(*bk) && !in_quote)
+ {
+ in_digit = false;
+ }
+ else if (bk[0] == 'a' && bk[1] == 't' && has_bracket && !in_quote)
+ {
+ has_at = true;
+ header += 'a';
+ }
+ else if (bk[0] == ':' && has_at && isdigit(bk[1]) && !in_quote)
+ {
+ has_filename = true;
+ }
+ else if (in_header && !in_digit && !in_quote && !in_bracket)
+ {
+ header += *bk;
+ }
+ }
+ bk++;
+ }
+
+ std::string pIndependentBacktrace;
+ std::set<std::string>::iterator it = set_headers.begin();
+ for (; it != set_headers.end(); it++)
+ {
+ pIndependentBacktrace += *it;
+ }
+ VERB3 log("IndependentBacktrace:'%s'", pIndependentBacktrace.c_str());
+ return pIndependentBacktrace;
+}
+
+static void GetIndependentBuildIdPC(const std::string& pBuildIdPC, std::string& pIndependentBuildIdPC)
+{
+ int ii = 0;
+ while (ii < pBuildIdPC.length())
+ {
+ std::string line;
+ int jj = 0;
+
+ while (pBuildIdPC[ii] != '\n' && ii < pBuildIdPC.length())
+ {
+ line += pBuildIdPC[ii];
+ ii++;
+ }
+ while (line[jj] != '+' && jj < line.length())
+ {
+ jj++;
+ }
+ jj++;
+ while (line[jj] != '@' && jj < line.length())
+ {
+ if (!isspace(line[jj]))
+ {
+ pIndependentBuildIdPC += line[jj];
+ }
+ jj++;
+ }
+ ii++;
+ }
+}
+
+static std::string run_unstrip_n(const char *pDebugDumpDir)
+{
+ std::string UID;
+ {
+ CDebugDump dd;
+ dd.Open(pDebugDumpDir);
+ dd.LoadText(FILENAME_UID, UID);
+ }
+
+ char* args[4];
+ args[0] = (char*)"eu-unstrip";
+ args[1] = xasprintf("--core=%s/"FILENAME_COREDUMP, pDebugDumpDir);
+ args[2] = (char*)"-n";
+ args[3] = NULL;
+
+ std::string output;
+ ExecVP(args, atoi(UID.c_str()), output);
+
+ free(args[1]);
+
+ return output;
+}
+
+#if 0
+/* older code */
+static bool is_hexstr(const char* str)
+{
+ while (*str)
+ {
+ if (!isxdigit(*str))
+ return false;
+ str++;
+ }
+ return true;
+}
+static void InstallDebugInfos(const char *pDebugDumpDir, std::string& build_ids)
+{
+ log("Getting module names, file names, build IDs from core file");
+ std::string unstrip_list = run_unstrip_n(pDebugDumpDir);
+
+ log("Builting list of missing debuginfos");
+ // lines look like this:
+ // 0x400000+0x209000 23c77451cf6adff77fc1f5ee2a01d75de6511dda@0x40024c - - [exe]
+ // 0x400000+0x209000 ab3c8286aac6c043fd1bb1cc2a0b88ec29517d3e@0x40024c /bin/sleep /usr/lib/debug/bin/sleep.debug [exe]
+ // 0x7fff313ff000+0x1000 389c7475e3d5401c55953a425a2042ef62c4c7df@0x7fff313ff2f8 . - linux-vdso.so.1
+ vector_string_t missing;
+ char *dup = xstrdup(unstrip_list.c_str());
+ char *p = dup;
+ char c;
+ do {
+ char* end = strchrnul(p, '\n');
+ c = *end;
+ *end = '\0';
+ char* word2 = strchr(p, ' ');
+ if (!word2)
+ continue;
+ word2++;
+ char* endsp = strchr(word2, ' ');
+ if (!endsp)
+ continue;
+ /* endsp points to 2nd space in the line now*/
+
+ /* This filters out linux-vdso.so, among others */
+ if (strstr(endsp, "[exe]") == NULL && endsp[1] != '/')
+ continue;
+ *endsp = '\0';
+ char* at = strchrnul(word2, '@');
+ *at = '\0';
+
+ bool file_exists = 1;
+ if (word2[0] && word2[1] && is_hexstr(word2))
+ {
+ struct stat sb;
+ char *fn = xasprintf("/usr/lib/debug/.build-id/%.2s/%s.debug", word2, word2 + 2);
+ /* Not lstat: this is a symlink and we want link's TARGET to exist */
+ file_exists = stat(fn, &sb) == 0 && S_ISREG(sb.st_mode);
+ free(fn);
+ build_ids += "build-id ";
+ build_ids += word2;
+ build_ids += file_exists ? " (debuginfo present)\n" : " (debuginfo absent)\n";
+ }
+ log("build_id:%s exists:%d", word2, (int)file_exists);
+ if (!file_exists)
+ missing.push_back(word2);
+
+ p = end + 1;
+ } while (c);
+ free(dup);
+
+ if (missing.size() == 0)
+ {
+ log("All debuginfos are present, not installing debuginfo packages");
+ return;
+ }
+ //missing vector is unused for now, but TODO: use it to install only needed debuginfos
+
+ std::string package;
+ {
+ CDebugDump dd;
+ dd.Open(pDebugDumpDir);
+ dd.LoadText(FILENAME_PACKAGE, package);
+ }
+
+ update_client(_("Searching for debug-info packages..."));
+
+ int pipein[2], pipeout[2];
+ xpipe(pipein);
+ xpipe(pipeout);
+
+ pid_t child = fork();
+ if (child < 0)
+ {
+ /*close(pipein[0]); close(pipeout[0]); - why bother */
+ /*close(pipein[1]); close(pipeout[1]); */
+ perror_msg_and_die("fork");
+ }
+ if (child == 0)
+ {
+ close(pipein[1]);
+ close(pipeout[0]);
+ xmove_fd(pipein[0], STDIN_FILENO);
+ xmove_fd(pipeout[1], STDOUT_FILENO);
+ /* Not a good idea, we won't see any error messages */
+ /*close(STDERR_FILENO);*/
+
+ setsid();
+/* Honestly, I do not know what is worse, pk-debuginfo-install or debuginfo-install:
+
+# pk-debuginfo-install -y -- coreutils-7.2-4.fc11
+1. Getting sources list...OK. Found 16 enabled and 23 disabled sources.
+2. Finding debugging sources...OK. Found 0 disabled debuginfo repos.
+3. Enabling debugging sources...OK. Enabled 0 debugging sources.
+4. Finding debugging packages...Failed to find the package : more than one package found for
+Failed to find the package : more than one package found for
+FAILED. Found no packages to install.
+5. Disabling sources previously enabled...OK. Disabled 0 debugging sources.
+
+:( FAIL!
+
+# debuginfo-install -y -- coreutils-7.2-4.fc11
+Loaded plugins: refresh-packagekit
+Another application is holding the yum lock, cannot continue
+
+:( FAIL!
+
+# debuginfo-install -y -- coreutils-7.2-4.fc11
+(second time in a row - it worked)
+
+*/
+ /* log() goes to stderr/syslog, it's ok to use it here */
+ VERB1 log("Executing: %s %s %s %s", "pk-debuginfo-install", "-y", "--", package.c_str());
+ execlp("pk-debuginfo-install", "pk-debuginfo-install", "-y", "--", package.c_str(), NULL);
+ /* fall back */
+ VERB1 log("Executing: %s %s %s %s", "debuginfo-install", "-y", "--", package.c_str());
+ execlp("debuginfo-install", "debuginfo-install", "-y", "--", package.c_str(), NULL);
+ exit(1);
+ }
+
+ close(pipein[0]);
+ close(pipeout[1]);
+
+ /* Should not be needed (we use -y option), but just in case: */
+ safe_write(pipein[1], "y\n", sizeof("y\n")-1);
+ close(pipein[1]);
+
+ update_client(_("Downloading and installing debug-info packages..."));
+
+ FILE *pipeout_fp = fdopen(pipeout[0], "r");
+ if (pipeout_fp == NULL) /* never happens */
+ {
+ close(pipeout[0]);
+ wait(NULL);
+ return;
+ }
+
+/* glx-utils, for example, do not have glx-utils-debuginfo package.
+ * Disabled code was causing failures in backtrace decoding.
+ * This does not seem to be useful.
+ */
+#ifdef COMPLAIN_IF_NO_DEBUGINFO
+ bool already_installed = false;
+#endif
+ char buff[1024];
+ std::string packageName = package.substr(0, package.rfind("-", package.rfind("-")-1));
+ while (fgets(buff, sizeof(buff), pipeout_fp))
+ {
+ int last = strlen(buff) - 1;
+ if (last >= 0 && buff[last] == '\n')
+ buff[last] = '\0';
+
+ log("%s", buff);
+ update_client("%s", buff); /* maybe only if buff != ""? */
+
+#ifdef COMPLAIN_IF_NO_DEBUGINFO
+ if (already_installed == false)
+ {
+ /* "Package foo-debuginfo-1.2-5.ARCH already installed and latest version" */
+ char* pn = strstr(buff, packageName.c_str());
+ if (pn)
+ {
+ char* already_str = strstr(pn, "already installed and latest version");
+ if (already_str)
+ {
+ already_installed = true;
+ }
+ }
+ }
+
+ if (already_installed == false &&
+ (strstr(buff, "No debuginfo packages available to install") != NULL ||
+ strstr(buff, "Could not find debuginfo for main pkg") != NULL ||
+ strstr(buff, "Could not find debuginfo pkg for dependency package") != NULL))
+ {
+ fclose(pipeout_fp);
+ kill(child, SIGTERM);
+ wait(NULL);
+ throw CABRTException(EXCEP_PLUGIN, std::string(__func__) + ": cannot install debuginfos for " + pPackage);
+ }
+#endif
+ }
+
+ fclose(pipeout_fp);
+ wait(NULL);
+}
+#endif
+/* Needs gdb feature from here: https://bugzilla.redhat.com/show_bug.cgi?id=528668
+ * It is slated to be in F12/RHEL6.
+ */
+static void InstallDebugInfos(const char *pDebugDumpDir, std::string& build_ids)
+{
+ update_client(_("Searching for debug-info packages..."));
+
+ int pipeout[2]; //TODO: can we use ExecVP?
+ xpipe(pipeout);
+
+ pid_t child = fork();
+ if (child < 0)
+ {
+ /*close(pipeout[0]); - why bother */
+ /*close(pipeout[1]); */
+ perror_msg_and_die("fork");
+ }
+ if (child == 0)
+ {
+ close(pipeout[0]);
+ xmove_fd(pipeout[1], STDOUT_FILENO);
+ close(STDIN_FILENO);
+ xopen("/dev/null", O_RDONLY);
+ /* Not a good idea, we won't see any error messages */
+ /*close(STDERR_FILENO);*/
+
+ setsid();
+
+ char *coredump = xasprintf("%s/"FILENAME_COREDUMP, pDebugDumpDir);
+ /* SELinux guys are not happy with /tmp, using /var/run/abrt */
+ char *tempdir = xasprintf(LOCALSTATEDIR"/run/abrt/tmp-%u-%lu", (int)getpid(), (long)time(NULL));
+ /* log() goes to stderr/syslog, it's ok to use it here */
+ VERB1 log("Executing: %s %s %s %s", "abrt-debuginfo-install", coredump, tempdir, DEBUGINFO_CACHE_DIR);
+ execlp("abrt-debuginfo-install", "abrt-debuginfo-install", coredump, tempdir, DEBUGINFO_CACHE_DIR, NULL);
+ exit(1);
+ }
+
+ close(pipeout[1]);
+
+ update_client(_("Downloading and installing debug-info packages..."));
+
+ FILE *pipeout_fp = fdopen(pipeout[0], "r");
+ if (pipeout_fp == NULL) /* never happens */
+ {
+ close(pipeout[0]);
+ wait(NULL);
+ return;
+ }
+
+ char buff[1024];
+ while (fgets(buff, sizeof(buff), pipeout_fp))
+ {
+ int last = strlen(buff) - 1;
+ if (last >= 0 && buff[last] == '\n')
+ buff[last] = '\0';
+
+ if (strncmp(buff, "MISSING:", 8) == 0)
+ {
+ build_ids += "Debuginfo absent: ";
+ build_ids += buff + 8;
+ build_ids += "\n";
+ }
+
+ const char *p = buff;
+ while (*p == ' ' || *p == '\t')
+ {
+ p++;
+ }
+ if (*p)
+ {
+ log("%s", buff);
+ update_client("%s", buff);
+ }
+ }
+
+ fclose(pipeout_fp);
+ wait(NULL);
+}
+
+static double get_dir_size(const char *dirname, std::string *worst_file, double *maxsz)
+{
+ DIR *dp = opendir(dirname);
+ if (dp == NULL)
+ return 0;
+
+ struct dirent *ep;
+ struct stat stats;
+ double size = 0;
+ while ((ep = readdir(dp)) != NULL)
+ {
+ if (dot_or_dotdot(ep->d_name))
+ continue;
+ std::string dname = concat_path_file(dirname, ep->d_name);
+ if (lstat(dname.c_str(), &stats) != 0)
+ continue;
+ if (S_ISDIR(stats.st_mode))
+ {
+ double sz = get_dir_size(dname.c_str(), worst_file, maxsz);
+ size += sz;
+ }
+ else if (S_ISREG(stats.st_mode))
+ {
+ double sz = stats.st_size;
+ size += sz;
+
+ if (worst_file)
+ {
+ /* Calculate "weighted" size and age
+ * w = sz_kbytes * age_mins */
+ sz /= 1024;
+ long age = (time(NULL) - stats.st_mtime) / 60;
+ if (age > 0)
+ sz *= age;
+
+ if (sz > *maxsz)
+ {
+ *maxsz = sz;
+ *worst_file = dname;
+ }
+ }
+ }
+ }
+ closedir(dp);
+ return size;
+}
+
+static void trim_debuginfo_cache(unsigned max_mb)
+{
+ while (1)
+ {
+ std::string worst_file;
+ double maxsz = 0;
+ double cache_sz = get_dir_size(DEBUGINFO_CACHE_DIR, &worst_file, &maxsz);
+ if (cache_sz / (1024 * 1024) < max_mb)
+ break;
+ VERB1 log("%s is %.0f bytes (over %u MB), deleting '%s'",
+ DEBUGINFO_CACHE_DIR, cache_sz, max_mb, worst_file.c_str());
+ if (unlink(worst_file.c_str()) != 0)
+ perror_msg("Can't unlink '%s'", worst_file.c_str());
+ }
+}
+
+std::string CAnalyzerFirefox::GetLocalUUID(const char *pDebugDumpDir)
+{
+ log(_("Getting local universal unique identification..."));
+
+ std::string executable;
+ std::string package;
+ {
+ CDebugDump dd;
+ dd.Open(pDebugDumpDir);
+ dd.LoadText(FILENAME_EXECUTABLE, executable);
+ dd.LoadText(FILENAME_PACKAGE, package);
+ }
+
+ std::string buildIdPC = run_unstrip_n(pDebugDumpDir);
+ std::string independentBuildIdPC;
+ GetIndependentBuildIdPC(buildIdPC, independentBuildIdPC);
+ return CreateHash(package + executable + independentBuildIdPC);
+}
+
+std::string CAnalyzerFirefox::GetGlobalUUID(const char *pDebugDumpDir)
+{
+ log(_("Getting global universal unique identification..."));
+
+ std::string backtrace;
+ std::string executable;
+ std::string package;
+ {
+ CDebugDump dd;
+ dd.Open(pDebugDumpDir);
+ dd.LoadText(FILENAME_BACKTRACE, backtrace);
+ dd.LoadText(FILENAME_EXECUTABLE, executable);
+ dd.LoadText(FILENAME_PACKAGE, package);
+ }
+ std::string independentBacktrace = GetIndependentBacktrace(backtrace);
+ return CreateHash(package + executable + independentBacktrace);
+}
+
+static bool DebuginfoCheckPolkit(int uid)
+{
+ int child_pid = fork();
+ if (child_pid < 0)
+ {
+ perror_msg_and_die("fork");
+ }
+ if (child_pid == 0)
+ {
+ //child
+ if (setuid(uid))
+ exit(1); //paranoia
+ PolkitResult result = polkit_check_authorization(getpid(),
+ "org.fedoraproject.abrt.install-debuginfos");
+ exit(result != PolkitYes); //exit 1 (failure) if not allowed
+ }
+
+ //parent
+ int status;
+ if (waitpid(child_pid, &status, 0) > 0 && WEXITSTATUS(status) == 0)
+ {
+ return true; //authorization OK
+ }
+ log("UID %d is not authorized to install debuginfos", uid);
+ return false;
+}
+
+void CAnalyzerFirefox::CreateReport(const char *pDebugDumpDir, int force)
+{
+ update_client(_("Starting report creation..."));
+
+ std::string package;
+ std::string backtrace;
+ std::string UID;
+
+ CDebugDump dd;
+ dd.Open(pDebugDumpDir);
+
+ if (!force)
+ {
+ bool bt_exists = dd.Exist(FILENAME_BACKTRACE);
+ if (bt_exists)
+ {
+ return; /* backtrace already exists */
+ }
+ }
+
+ dd.LoadText(FILENAME_PACKAGE, package);
+ dd.LoadText(FILENAME_UID, UID);
+ dd.Close(); /* do not keep dir locked longer than needed */
+
+ std::string build_ids;
+ if (m_bInstallDebugInfo && DebuginfoCheckPolkit(atoi(UID.c_str()))) {
+ if (m_nDebugInfoCacheMB > 0)
+ trim_debuginfo_cache(m_nDebugInfoCacheMB);
+ InstallDebugInfos(pDebugDumpDir, build_ids);
+ }
+ else
+ {
+ VERB1 log(_("Skipping debuginfo installation"));
+ }
+
+ GetBacktrace(pDebugDumpDir, backtrace);
+
+ dd.Open(pDebugDumpDir);
+ dd.SaveText(FILENAME_BACKTRACE, (build_ids + backtrace).c_str());
+ if (m_bMemoryMap)
+ {
+ dd.SaveText(FILENAME_MEMORYMAP, "memory map of the crashed C/C++ application, not implemented yet");
+ }
+ dd.SaveText(FILENAME_RATING, to_string(rate_backtrace(backtrace.c_str())).c_str());
+ dd.Close();
+}
+
+void CAnalyzerFirefox::Init()
+{
+ std::ifstream fInCorePattern;
+ fInCorePattern.open(CORE_PATTERN_IFACE);
+ if (fInCorePattern.is_open())
+ {
+ getline(fInCorePattern, m_sOldCorePattern);
+ fInCorePattern.close();
+ }
+ if (m_sOldCorePattern[0] == '|')
+ {
+ if (m_sOldCorePattern == CORE_PATTERN)
+ {
+ log("warning: %s already contains %s, "
+ "did abrt daemon crash recently?",
+ CORE_PATTERN_IFACE, CORE_PATTERN);
+ /* There is no point in "restoring" CORE_PATTERN_IFACE
+ * to CORE_PATTERN on exit. Will restore to a default value:
+ */
+ m_sOldCorePattern = "core";
+ } else {
+ log("warning: %s was already set to run a crash analyser (%s), "
+ "abrt may interfere with it",
+ CORE_PATTERN_IFACE, CORE_PATTERN);
+ }
+ }
+
+ std::ofstream fOutCorePattern;
+ fOutCorePattern.open(CORE_PATTERN_IFACE);
+ if (fOutCorePattern.is_open())
+ {
+ fOutCorePattern << CORE_PATTERN << std::endl;
+ fOutCorePattern.close();
+ }
+}
+
+void CAnalyzerFirefox::DeInit()
+{
+ std::ofstream fOutCorePattern;
+ fOutCorePattern.open(CORE_PATTERN_IFACE);
+ if (fOutCorePattern.is_open())
+ {
+ fOutCorePattern << m_sOldCorePattern << std::endl;
+ fOutCorePattern.close();
+ }
+}
+
+void CAnalyzerFirefox::SetSettings(const map_plugin_settings_t& pSettings)
+{
+ m_pSettings = pSettings;
+
+ map_plugin_settings_t::const_iterator end = pSettings.end();
+ map_plugin_settings_t::const_iterator it;
+ it = pSettings.find("MemoryMap");
+ if (it != end)
+ {
+ m_bMemoryMap = string_to_bool(it->second.c_str());
+ }
+ it = pSettings.find("DebugInfo");
+ if (it != end)
+ {
+ m_sDebugInfo = it->second;
+ }
+ it = pSettings.find("DebugInfoCacheMB");
+ if (it != end)
+ {
+ m_nDebugInfoCacheMB = atoi(it->second.c_str());
+ }
+ it = pSettings.find("InstallDebugInfo");
+ if (it == end) //compat, remove after 0.0.11
+ it = pSettings.find("InstallDebuginfo");
+ if (it != end)
+ {
+ m_bInstallDebugInfo = string_to_bool(it->second.c_str());
+ }
+}
+
+//ok to delete?
+//const map_plugin_settings_t& CAnalyzerCCpp::GetSettings()
+//{
+// m_pSettings["MemoryMap"] = m_bMemoryMap ? "yes" : "no";
+// m_pSettings["DebugInfo"] = m_sDebugInfo;
+// m_pSettings["DebugInfoCacheMB"] = to_string(m_nDebugInfoCacheMB);
+// m_pSettings["InstallDebugInfo"] = m_bInstallDebugInfo ? "yes" : "no";
+//
+// return m_pSettings;
+//}
+
+PLUGIN_INFO(ANALYZER,
+ CAnalyzerFirefox,
+ "Firefox",
+ "0.0.1",
+ "Firefox analyzer plugin.",
+ "zprikryl@redhat.com",
+ "https://fedorahosted.org/abrt/wiki",
+ "");
diff --git a/lib/Plugins/Firefox.h b/lib/Plugins/Firefox.h
new file mode 100644
index 0000000..0669f4f
--- /dev/null
+++ b/lib/Plugins/Firefox.h
@@ -0,0 +1,51 @@
+/*
+ Firefox.h - header file for Firefox analyzer plugin
+ - it can get UUID and memory maps from core files
+
+ Copyright (C) 2009 Zdenek Prikryl (zprikryl@redhat.com)
+ Copyright (C) 2009 RedHat inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef CCPP_H_
+#define CCPP_H_
+
+#include <string>
+#include "Plugin.h"
+#include "Analyzer.h"
+
+class CAnalyzerFirefox : public CAnalyzer
+{
+ private:
+ bool m_bMemoryMap;
+ bool m_bInstallDebugInfo;
+ unsigned m_nDebugInfoCacheMB;
+ std::string m_sOldCorePattern;
+ std::string m_sDebugInfo;
+
+ public:
+ CAnalyzerFirefox();
+ virtual std::string GetLocalUUID(const char *pDebugDumpDir);
+ virtual std::string GetGlobalUUID(const char *pDebugDumpDir);
+ virtual void CreateReport(const char *pDebugDumpDir, int force);
+ virtual void Init();
+ virtual void DeInit();
+ virtual void SetSettings(const map_plugin_settings_t& pSettings);
+//ok to delete?
+// virtual const map_plugin_settings_t& GetSettings();
+};
+
+#endif /* CCPP */
diff --git a/lib/Plugins/Kerneloops.cpp b/lib/Plugins/Kerneloops.cpp
index b99183c..2e28cf4 100644
--- a/lib/Plugins/Kerneloops.cpp
+++ b/lib/Plugins/Kerneloops.cpp
@@ -67,7 +67,7 @@ PLUGIN_INFO(ANALYZER,
CAnalyzerKerneloops,
"Kerneloops",
"0.0.2",
- "Abrt's Kerneloops plugin.",
+ "Analyzes kernel oopses",
"anton@redhat.com",
"https://people.redhat.com/aarapov",
"");
diff --git a/lib/Plugins/KerneloopsReporter.cpp b/lib/Plugins/KerneloopsReporter.cpp
index f7a6cbb..f38f503 100644
--- a/lib/Plugins/KerneloopsReporter.cpp
+++ b/lib/Plugins/KerneloopsReporter.cpp
@@ -140,7 +140,7 @@ PLUGIN_INFO(REPORTER,
CKerneloopsReporter,
"KerneloopsReporter",
"0.0.1",
- "Sends the Kerneloops crash information to Kerneloops.org",
+ "Sends kernel oops information to kerneloops.org",
"anton@redhat.com",
"http://people.redhat.com/aarapov",
PLUGINS_LIB_DIR"/KerneloopsReporter.GTKBuilder");
diff --git a/lib/Plugins/KerneloopsScanner.cpp b/lib/Plugins/KerneloopsScanner.cpp
index 8c8cd4b..3831f9e 100644
--- a/lib/Plugins/KerneloopsScanner.cpp
+++ b/lib/Plugins/KerneloopsScanner.cpp
@@ -163,7 +163,7 @@ int CKerneloopsScanner::ScanSysLogFile(const char *filename)
*/
sz = statb.st_size + 1024;
if (statb.st_size > (32*1024*1024 - 1024)) {
- xlseek(fd, -(32*1024*1024 - 1024), SEEK_END);
+ xlseek(fd, statb.st_size - (32*1024*1024 - 1024), SEEK_SET);
sz = 32*1024*1024;
}
buffer = (char*)xzalloc(sz);
@@ -184,7 +184,7 @@ PLUGIN_INFO(ACTION,
CKerneloopsScanner,
"KerneloopsScanner",
"0.0.1",
- "Save new Kerneloops crashes into debug dump dir",
+ "Periodically scans for and saves kernel oopses",
"anton@redhat.com",
"http://people.redhat.com/aarapov",
"");
diff --git a/lib/Plugins/Logger.cpp b/lib/Plugins/Logger.cpp
index 6babc73..7267b64 100644
--- a/lib/Plugins/Logger.cpp
+++ b/lib/Plugins/Logger.cpp
@@ -91,7 +91,7 @@ PLUGIN_INFO(REPORTER,
CLogger,
"Logger",
"0.0.1",
- "Write a report to a specific file",
+ "Writes report to a file",
"zprikryl@redhat.com",
"https://fedorahosted.org/abrt/wiki",
PLUGINS_LIB_DIR"/Logger.GTKBuilder");
diff --git a/lib/Plugins/Mailx.cpp b/lib/Plugins/Mailx.cpp
index 1979f9e..32eeb25 100644
--- a/lib/Plugins/Mailx.cpp
+++ b/lib/Plugins/Mailx.cpp
@@ -33,168 +33,143 @@ CMailx::CMailx() :
m_sEmailFrom("user@localhost"),
m_sEmailTo("root@localhost"),
m_sSubject("[abrt] full crash report"),
- m_bSendBinaryData(false),
- m_nArgs(0),
- m_pArgs(NULL)
+ m_bSendBinaryData(false)
{}
-void CMailx::FreeMailxArgs()
-{
- int ii;
- for (ii = 0; ii < m_nArgs; ii++)
- {
- free(m_pArgs[ii]);
- }
- free((void*) m_pArgs);
- m_pArgs = NULL;
- m_nArgs = 0;
-}
-
-void CMailx::AddMailxArg(const std::string& pArg)
-{
- m_pArgs = (char**) realloc((void*)m_pArgs, (++m_nArgs) * (sizeof(char*)));
- if (pArg == "")
- {
- m_pArgs[m_nArgs - 1] = NULL;
- }
- else
- {
- m_pArgs[m_nArgs - 1] = strdup(pArg.c_str());
- }
-}
-
-void CMailx::ExecMailx(uid_t uid, const std::string& pText)
+static void exec_and_feed_input(uid_t uid, const char* pText, char **pArgs)
{
int pipein[2];
pid_t child;
- struct passwd* pw = getpwuid(uid);
- if (!pw)
- {
- throw CABRTException(EXCEP_PLUGIN, std::string(__func__) + ": cannot get GID for UID.");
- }
-
xpipe(pipein);
child = fork();
if (child == -1)
{
close(pipein[0]);
close(pipein[1]);
- throw CABRTException(EXCEP_PLUGIN, std::string(__func__) + ": fork failed.");
+ throw CABRTException(EXCEP_PLUGIN, "Can't fork");
}
if (child == 0)
{
-
close(pipein[1]);
xmove_fd(pipein[0], STDIN_FILENO);
- setgroups(1, &pw->pw_gid);
- setregid(pw->pw_gid, pw->pw_gid);
+ struct passwd* pw = getpwuid(uid);
+ gid_t gid = pw ? pw->pw_gid : uid;
+ setgroups(1, &gid);
+ setregid(gid, gid);
setreuid(uid, uid);
- setsid();
+ setsid(); /* why? I propose removing this */
- execvp(MAILX_COMMAND, m_pArgs);
- exit(0);
+ execvp(pArgs[0], pArgs);
+ exit(1); /* exec failed */
}
close(pipein[0]);
- safe_write(pipein[1], pText.c_str(), pText.length());
+ safe_write(pipein[1], pText, strlen(pText));
close(pipein[1]);
- wait(NULL); /* why? */
+ wait(NULL); /* wait for command completion */
}
-void CMailx::SendEmail(const std::string& pSubject, const std::string& pText, const std::string& pUID)
+static char** append_str_to_vector(char **vec, unsigned &size, const char *str)
{
- update_client(_("Sending an email..."));
-
- AddMailxArg("-s");
- AddMailxArg(pSubject);
- AddMailxArg("-r");
- AddMailxArg(m_sEmailFrom);
- AddMailxArg(m_sEmailTo);
- AddMailxArg("");
-
- ExecMailx(atoi(pUID.c_str()), pText);
+ //log("old vec: %p", vec);
+ vec = (char**) xrealloc(vec, (size+2) * sizeof(vec[0]));
+ vec[size] = xstrdup(str);
+ //log("new vec: %p, added [%d] %p", vec, size, vec[size]);
+ size++;
+ vec[size] = NULL;
+ return vec;
}
-std::string CMailx::Report(const map_crash_report_t& pCrashReport,
+std::string CMailx::Report(const map_crash_report_t& pCrashReport,
const map_plugin_settings_t& pSettings, const std::string& pArgs)
{
- update_client(_("Creating a report..."));
-
- std::stringstream emailBody;
- std::stringstream binaryFiles, commonFiles, bigTextFiles, additionalFiles, UUIDFile;
-
- AddMailxArg(MAILX_COMMAND);
+ char **args = NULL;
+ unsigned arg_size = 0;
+ args = append_str_to_vector(args, arg_size, MAILX_COMMAND);
+ std::string binaryFiles, commonFiles, bigTextFiles, additionalFiles, UUIDFile;
map_crash_report_t::const_iterator it;
for (it = pCrashReport.begin(); it != pCrashReport.end(); it++)
{
if (it->second[CD_TYPE] == CD_TXT)
{
- if (it->first != CD_UUID &&
- it->first != FILENAME_ARCHITECTURE &&
- it->first != FILENAME_KERNEL &&
- it->first != FILENAME_PACKAGE)
- {
- additionalFiles << it->first << std::endl;
- additionalFiles << "-----" << std::endl;
- additionalFiles << it->second[CD_CONTENT] << std::endl << std::endl;
+ if (it->first != CD_UUID
+ && it->first != FILENAME_ARCHITECTURE
+ && it->first != FILENAME_KERNEL
+ && it->first != FILENAME_PACKAGE
+ ) {
+ additionalFiles += it->first;
+ additionalFiles += "\n-----\n";
+ additionalFiles += it->second[CD_CONTENT];
+ additionalFiles += "\n\n";
}
else if (it->first == CD_UUID)
{
- UUIDFile << it->first << std::endl;
- UUIDFile << "-----" << std::endl;
- UUIDFile << it->second[CD_CONTENT] << std::endl << std::endl;
+ UUIDFile += it->first;
+ UUIDFile += "\n-----\n";
+ UUIDFile += it->second[CD_CONTENT];
+ UUIDFile += "\n\n";
}
else
{
- commonFiles << it->first << std::endl;
- commonFiles << "-----" << std::endl;
- commonFiles << it->second[CD_CONTENT] << std::endl << std::endl;
+ commonFiles += it->first;
+ commonFiles += "\n-----\n";
+ commonFiles += it->second[CD_CONTENT];
+ commonFiles += "\n\n";
}
}
if (it->second[CD_TYPE] == CD_ATT)
{
- bigTextFiles << it->first << std::endl;
- bigTextFiles << "-----" << std::endl;
- bigTextFiles << it->second[CD_CONTENT] << std::endl << std::endl;
+ bigTextFiles += it->first;
+ bigTextFiles += "\n-----\n";
+ bigTextFiles += it->second[CD_CONTENT];
+ bigTextFiles += "\n\n";
}
if (it->second[CD_TYPE] == CD_BIN)
{
- binaryFiles << " -a " << it->second[CD_CONTENT];
+ binaryFiles += " -a ";
+ binaryFiles += it->second[CD_CONTENT];
if (m_bSendBinaryData)
{
- AddMailxArg("-a");
- AddMailxArg(it->second[CD_CONTENT]);
+ args = append_str_to_vector(args, arg_size, "-a");
+ args = append_str_to_vector(args, arg_size, it->second[CD_CONTENT].c_str());
}
}
}
- emailBody << "Duplicity check" << std::endl;
- emailBody << "=====" << std::endl << std::endl;
- emailBody << UUIDFile.str() << std::endl;
- emailBody << "Common information" << std::endl;
- emailBody << "=====" << std::endl << std::endl;
- emailBody << commonFiles.str() << std::endl;
- emailBody << "Additional information" << std::endl;
- emailBody << "=====" << std::endl << std::endl;
- emailBody << additionalFiles.str() << std::endl;
- emailBody << "Other information" << std::endl;
- emailBody << "=====" << std::endl << std::endl;
- emailBody << bigTextFiles.str() << std::endl;
-
- if (pArgs != "")
- {
- SendEmail(pArgs, emailBody.str(), pCrashReport.find(CD_MWUID)->second[CD_CONTENT]);
- }
- else
+ std::string emailBody = "Duplicity check\n";
+ emailBody += "=====\n\n";
+ emailBody += UUIDFile;
+ emailBody += "\nCommon information\n";
+ emailBody += "=====\n\n";
+ emailBody += commonFiles;
+ emailBody += "\nAdditional information\n";
+ emailBody += "=====\n\n";
+ emailBody += additionalFiles;
+ emailBody += "\nOther information\n";
+ emailBody += "=====\n\n";
+ emailBody += bigTextFiles;
+ emailBody += '\n';
+
+ args = append_str_to_vector(args, arg_size, "-s");
+ args = append_str_to_vector(args, arg_size, (pArgs != "" ? pArgs.c_str() : m_sSubject.c_str()));
+ args = append_str_to_vector(args, arg_size, "-r");
+ args = append_str_to_vector(args, arg_size, m_sEmailFrom.c_str());
+ args = append_str_to_vector(args, arg_size, m_sEmailTo.c_str());
+
+ update_client(_("Sending an email..."));
+ const char *uid_str = pCrashReport.find(CD_MWUID)->second[CD_CONTENT].c_str();
+ exec_and_feed_input(atoi(uid_str), emailBody.c_str(), args);
+
+ while (*args)
{
- SendEmail(m_sSubject, emailBody.str(), pCrashReport.find(CD_MWUID)->second[CD_CONTENT]);
+ free(*args++);
}
-
- FreeMailxArgs();
+ args -= arg_size;
+ free(args);
return "Email was sent to: " + m_sEmailTo;
}
@@ -242,7 +217,7 @@ PLUGIN_INFO(REPORTER,
CMailx,
"Mailx",
"0.0.2",
- "Sends an email with a report via mailx command",
+ "Sends an email with a report (via mailx command)",
"zprikryl@redhat.com",
"https://fedorahosted.org/abrt/wiki",
PLUGINS_LIB_DIR"/Mailx.GTKBuilder");
diff --git a/lib/Plugins/Mailx.h b/lib/Plugins/Mailx.h
index 4aa861f..d6d66bd 100644
--- a/lib/Plugins/Mailx.h
+++ b/lib/Plugins/Mailx.h
@@ -35,14 +35,6 @@ class CMailx : public CReporter
std::string m_sSubject;
bool m_bSendBinaryData;
- int m_nArgs;
- char** m_pArgs;
-
- void FreeMailxArgs();
- void AddMailxArg(const std::string& pArg);
- void ExecMailx(uid_t uid, const std::string& pText);
- void SendEmail(const std::string& pSubject, const std::string& pText, const std::string& pUID);
-
public:
CMailx();
@@ -54,4 +46,4 @@ class CMailx : public CReporter
const std::string& pArgs);
};
-#endif /* MAILX_H_ */
+#endif
diff --git a/lib/Plugins/Makefile.am b/lib/Plugins/Makefile.am
index 0502f5e..9d80d91 100644
--- a/lib/Plugins/Makefile.am
+++ b/lib/Plugins/Makefile.am
@@ -15,6 +15,7 @@ pluginslib_LTLIBRARIES = \
libTicketUploader.la \
libPython.la \
libFileTransfer.la
+# libFirefox.la
dist_pluginslib_DATA = \
KerneloopsReporter.GTKBuilder Logger.GTKBuilder \
@@ -58,6 +59,17 @@ libCCpp_la_CPPFLAGS = -I$(srcdir)/../../inc -I$(srcdir)/../Utils \
-DLOCALSTATEDIR='"$(localstatedir)"' \
$(NSS_CFLAGS)
+
+# Firefox - disabled for now
+#libFirefox_la_SOURCES = Firefox.cpp Firefox.h
+#libFirefox_la_LDFLAGS = -avoid-version
+#libFirefox_la_LIBADD = $(NSS_LIBS)
+#libFirefox_la_CPPFLAGS = -I$(srcdir)/../../inc -I$(srcdir)/../Utils \
+# -DCCPP_HOOK_PATH=\"${libexecdir}/hookCCpp\" \
+# -DDEBUG_DUMPS_DIR=\"$(DEBUG_DUMPS_DIR)\" \
+# -DLOCALSTATEDIR='"$(localstatedir)"' \
+# $(NSS_CFLAGS)
+
# Kerneloops
libKerneloops_la_SOURCES = Kerneloops.cpp Kerneloops.h
libKerneloops_la_LDFLAGS = -avoid-version
diff --git a/lib/Plugins/Python.cpp b/lib/Plugins/Python.cpp
index 9fb7880..a5e9909 100644
--- a/lib/Plugins/Python.cpp
+++ b/lib/Plugins/Python.cpp
@@ -51,7 +51,7 @@ PLUGIN_INFO(ANALYZER,
CAnalyzerPython,
"Python",
"0.0.1",
- "Simple Python analyzer plugin.",
+ "Analyzes crashes in Python programs",
"zprikryl@redhat.com, jmoskovc@redhat.com",
"https://fedorahosted.org/abrt/wiki",
"");
diff --git a/lib/Plugins/RunApp.cpp b/lib/Plugins/RunApp.cpp
index e525d89..f7cbc01 100644
--- a/lib/Plugins/RunApp.cpp
+++ b/lib/Plugins/RunApp.cpp
@@ -21,7 +21,6 @@
#include "RunApp.h"
-#include <stdio.h>
#include "DebugDump.h"
#include "ABRTException.h"
#include "CommLayerInner.h"
@@ -30,28 +29,49 @@
#define COMMAND 0
#define FILENAME 1
+using namespace std;
+
void CActionRunApp::Run(const char *pActionDir, const char *pArgs)
{
- update_client(_("Executing RunApp plugin..."));
+ /* Don't update_client() - actions run at crash time */
+ log("RunApp('%s','%s')", pActionDir, pArgs);
- std::string output;
vector_string_t args;
-
parse_args(pArgs, args, '"');
- FILE *fp = popen(args[COMMAND].c_str(), "r");
+ const char *cmd = args[COMMAND].c_str();
+ if (!cmd[0])
+ {
+ return;
+ }
+
+//FIXME: need to be able to escape " in .conf
+ /* Chdir to the dump dir. Command can analyze component and such.
+ * Example:
+ * test x"`cat component`" = x"xorg-x11-apps" && cp /var/log/Xorg.0.log .
+ */
+//Can do it using chdir() in child if we'd open-code popen
+ string cd_and_cmd = ssprintf("cd '%s'; %s", pActionDir, cmd);
+ VERB1 log("RunApp: executing '%s'", cd_and_cmd.c_str());
+ FILE *fp = popen(cd_and_cmd.c_str(), "r");
if (fp == NULL)
{
- throw CABRTException(EXCEP_PLUGIN, "Can't execute " + args[COMMAND]);
+ /* Happens only on resource starvation (fork fails or out-of-mem) */
+ return;
}
+
+//FIXME: RunApp("gzip -9 </var/log/Xorg.0.log", "Xorg.0.log.gz") fails
+//since we mangle NULs.
+ string output;
char line[1024];
while (fgets(line, 1024, fp) != NULL)
{
- output += line;
+ if (args.size() > FILENAME)
+ output += line;
}
pclose(fp);
- if (args.size() > 1)
+ if (args.size() > FILENAME)
{
CDebugDump dd;
dd.Open(pActionDir);
@@ -63,8 +83,7 @@ PLUGIN_INFO(ACTION,
CActionRunApp,
"RunApp",
"0.0.1",
- "Simple action plugin which runs a command "
- "and it can save command's output",
+ "Runs a command, saves its output",
"zprikryl@redhat.com",
"https://fedorahosted.org/abrt/wiki",
"");
diff --git a/lib/Plugins/SOSreport.cpp b/lib/Plugins/SOSreport.cpp
index 287c01e..65d01a7 100644
--- a/lib/Plugins/SOSreport.cpp
+++ b/lib/Plugins/SOSreport.cpp
@@ -116,7 +116,7 @@ PLUGIN_INFO(ACTION,
CActionSOSreport,
"SOSreport",
"0.0.2",
- "Run sosreport, save the output in the crash dump",
+ "Runs sosreport, saves the output",
"gavin@redhat.com",
"https://fedorahosted.org/abrt/wiki",
"");
diff --git a/lib/Plugins/SQLite3.cpp b/lib/Plugins/SQLite3.cpp
index 3aad054..cc639da 100644
--- a/lib/Plugins/SQLite3.cpp
+++ b/lib/Plugins/SQLite3.cpp
@@ -34,7 +34,7 @@
// after a while, we can drop support for update, so a table can stay in
// normal limits
-static const char* upate_sql_commands[][ABRT_TABLE_VERSION + 1] = {
+static const char *const upate_sql_commands[][ABRT_TABLE_VERSION + 1] = {
// v0 -> *
{
// v0 -> v0
@@ -421,7 +421,7 @@ PLUGIN_INFO(DATABASE,
CSQLite3,
"SQLite3",
"0.0.2",
- "SQLite3 database plugin.",
+ "Keeps SQLite3 database about all crashes",
"zprikryl@redhat.com,jmoskovc@redhat.com",
"https://fedorahosted.org/abrt/wiki",
"");
diff --git a/lib/Plugins/TicketUploader.cpp b/lib/Plugins/TicketUploader.cpp
index 76bda40..847efdc 100644
--- a/lib/Plugins/TicketUploader.cpp
+++ b/lib/Plugins/TicketUploader.cpp
@@ -295,28 +295,47 @@ string CTicketUploader::Report(const map_crash_report_t& pCrashReport,
}
// generate a reciept telling md5sum and encryption key
- ostringstream msgbuf;
+ // note: do not internationalize these strings!
+ string msg;
if (have_ticket_name)
- msgbuf << _("Please copy this into ticket: ") << ticket_name << endl;
+ {
+ msg += "Please copy this into ticket: ";
+ msg += ticket_name;
+ msg += '\n';
+ }
else
- msgbuf << _("Please send this to your technical support: ") << endl;
+ {
+ msg += "Please send this to your technical support:\n";
+ }
if (do_upload)
- msgbuf << _("RHUPLOAD: This report was sent to ") + upload_url << endl;
+ {
+ msg += "RHUPLOAD: This report was sent to ";
+ msg += upload_url;
+ msg += '\n';
+ }
else
- msgbuf << _("RHUPLOAD: This report was copied into /tmp/: ") << endl;
+ {
+ msg += "RHUPLOAD: This report was copied into /tmp/:\n";
+ }
if (have_ticket_name)
- msgbuf << _("TICKET: ") << ticket_name << endl;
- msgbuf << _("FILE: ") << outfile_basename << endl;
- msgbuf << _("MD5SUM: ") << endl;
- msgbuf << md5sum;
+ {
+ msg += "TICKET: ";
+ msg += ticket_name;
+ msg += '\n';
+ }
+ msg += "FILE: ";
+ msg += outfile_basename;
+ msg += "\nMD5SUM:\n";
+ msg += md5sum;
if (do_encrypt)
{
- msgbuf << _("KEY: aes-128-cbc") << endl;
- msgbuf << key;
+ msg += "KEY: aes-128-cbc\n";
+ msg += key;
}
- msgbuf << _("END: ") << endl;
+ msg += "END:\n";
- error_msg("%s", msgbuf.str().c_str());
+ /* warn the client: */
+ error_msg("%s", msg.c_str());
string ret;
if (do_upload)
@@ -400,7 +419,7 @@ PLUGIN_INFO(REPORTER,
CTicketUploader,
"TicketUploader",
"0.0.1",
- "input ticket# and customer name from user, send report to FTP",
+ "Asks ticket# and customer name from user, sends report to FTP",
"gavin@redhat.com",
- "https://fedorahosted.org/abtr/wiki",
+ "https://fedorahosted.org/abrt/wiki",
PLUGINS_LIB_DIR"/TicketUploader.GTKBuilder");
diff --git a/lib/Python/Makefile.am b/lib/Python/Makefile.am
deleted file mode 100644
index dd9eeca..0000000
--- a/lib/Python/Makefile.am
+++ /dev/null
@@ -1,5 +0,0 @@
-pyexec_LTLIBRARIES = ABRTUtils.la
-ABRTUtils_la_SOURCES = PyDebugDump.cpp
-ABRTUtils_la_LDFLAGS = -module -avoid-version
-ABRTUtils_la_LIBADD = ../Utils/libABRTUtils.la
-ABRTUtils_la_CPPFLAGS = -fPIC -shared `python-config --cflags` -I../Utils
diff --git a/lib/Python/PyABRTUtils.cpp b/lib/Python/PyABRTUtils.cpp
deleted file mode 100644
index e56ba07..0000000
--- a/lib/Python/PyABRTUtils.cpp
+++ /dev/null
@@ -1,248 +0,0 @@
-/* This file was generated by PyBindGen 0.10.0 */
-#define PY_SSIZE_T_CLEAN
-#include <Python.h>
-#include <stddef.h>
-
-
-#if PY_VERSION_HEX < 0x020400F0
-
-#define PyEval_ThreadsInitialized() 1
-
-#define Py_CLEAR(op) \
- do { \
- if (op) { \
- PyObject *tmp = (PyObject *)(op); \
- (op) = NULL; \
- Py_DECREF(tmp); \
- } \
- } while (0)
-
-
-#define Py_VISIT(op) \
- do { \
- if (op) { \
- int vret = visit((PyObject *)(op), arg); \
- if (vret) \
- return vret; \
- } \
- } while (0)
-
-#endif
-
-
-
-#if PY_VERSION_HEX < 0x020500F0
-
-typedef int Py_ssize_t;
-# define PY_SSIZE_T_MAX INT_MAX
-# define PY_SSIZE_T_MIN INT_MIN
-typedef inquiry lenfunc;
-typedef intargfunc ssizeargfunc;
-typedef intobjargproc ssizeobjargproc;
-
-#endif
-
-
-#if __GNUC__ > 2
-# define PYBINDGEN_UNUSED(param) param __attribute__((__unused__))
-#elif __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
-# define PYBINDGEN_UNUSED(param) __attribute__((__unused__)) param
-#else
-# define PYBINDGEN_UNUSED(param)
-#endif /* !__GNUC__ */
-
-#include "../Utils/DebugDump.h"
-/* --- forward declarations --- */
-
-
-typedef struct {
- PyObject_HEAD
- CDebugDump *obj;
-} PyCDebugDump;
-
-
-extern PyTypeObject PyCDebugDump_Type;
-
-static PyMethodDef ABRTUtils_functions[] = {
- {NULL, NULL, 0, NULL}
-};
-/* --- classes --- */
-
-
-
-static int
-_wrap_PyCDebugDump__tp_init(PyCDebugDump *self, PyObject *args, PyObject *kwargs)
-{
- const char *keywords[] = {NULL};
-
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "", (char **) keywords)) {
- return -1;
- }
- self->obj = new CDebugDump();
- return 0;
-}
-
-
-PyObject *
-_wrap_PyCDebugDump_Close(PyCDebugDump *self)
-{
- PyObject *py_retval;
-
- self->obj->Close();
- Py_INCREF(Py_None);
- py_retval = Py_None;
- return py_retval;
-}
-
-
-PyObject *
-_wrap_PyCDebugDump_Create(PyCDebugDump *self, PyObject *args, PyObject *kwargs)
-{
- PyObject *py_retval;
- char *pFilename2;
- char *pUID2;
- const char *keywords[] = {"pFilename", "pUID", NULL};
-
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "ss", (char **) keywords, &pFilename2, &pUID2)) {
- return NULL;
- }
- self->obj->Create(pFilename2);
- Py_INCREF(Py_None);
- py_retval = Py_None;
- return py_retval;
-}
-
-
-PyObject *
-_wrap_PyCDebugDump_SaveText(PyCDebugDump *self, PyObject *args, PyObject *kwargs)
-{
- PyObject *py_retval;
- char *pName2;
- char *pData2;
- const char *keywords[] = {"pName", "pData", NULL};
-
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "ss", (char **) keywords, &pName2, &pData2)) {
- return NULL;
- }
- self->obj->SaveText(pName2, pData2);
- Py_INCREF(Py_None);
- py_retval = Py_None;
- return py_retval;
-}
-
-static PyMethodDef PyCDebugDump_methods[] = {
- {(char *) "Close", (PyCFunction) _wrap_PyCDebugDump_Close, METH_NOARGS, NULL },
- {(char *) "Create", (PyCFunction) _wrap_PyCDebugDump_Create, METH_KEYWORDS|METH_VARARGS, NULL },
- {(char *) "SaveText", (PyCFunction) _wrap_PyCDebugDump_SaveText, METH_KEYWORDS|METH_VARARGS, NULL },
- {NULL, NULL, 0, NULL}
-};
-
-static void
-_wrap_PyCDebugDump__tp_dealloc(PyCDebugDump *self)
-{
- CDebugDump *tmp = self->obj;
- self->obj = NULL;
- delete tmp;
- self->ob_type->tp_free((PyObject*)self);
-}
-
-static PyObject*
-_wrap_PyCDebugDump__tp_richcompare (PyCDebugDump *self, PyCDebugDump *other, int opid)
-{
-
- if (!PyObject_IsInstance((PyObject*) other, (PyObject*) &PyCDebugDump_Type)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- switch (opid)
- {
- case Py_LT:
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- case Py_LE:
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- case Py_EQ:
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- case Py_NE:
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- case Py_GE:
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- case Py_GT:
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- } /* closes switch (opid) */
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
-}
-
-PyTypeObject PyCDebugDump_Type = {
- PyObject_HEAD_INIT(NULL)
- 0, /* ob_size */
- (char *) "ABRTUtils.CDebugDump", /* tp_name */
- sizeof(PyCDebugDump), /* tp_basicsize */
- 0, /* tp_itemsize */
- /* methods */
- (destructor)_wrap_PyCDebugDump__tp_dealloc, /* tp_dealloc */
- (printfunc)0, /* tp_print */
- (getattrfunc)NULL, /* tp_getattr */
- (setattrfunc)NULL, /* tp_setattr */
- (cmpfunc)NULL, /* tp_compare */
- (reprfunc)NULL, /* tp_repr */
- (PyNumberMethods*)NULL, /* tp_as_number */
- (PySequenceMethods*)NULL, /* tp_as_sequence */
- (PyMappingMethods*)NULL, /* tp_as_mapping */
- (hashfunc)NULL, /* tp_hash */
- (ternaryfunc)NULL, /* tp_call */
- (reprfunc)NULL, /* tp_str */
- (getattrofunc)NULL, /* tp_getattro */
- (setattrofunc)NULL, /* tp_setattro */
- (PyBufferProcs*)NULL, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
- NULL, /* Documentation string */
- (traverseproc)NULL, /* tp_traverse */
- (inquiry)NULL, /* tp_clear */
- (richcmpfunc)_wrap_PyCDebugDump__tp_richcompare, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- (getiterfunc)NULL, /* tp_iter */
- (iternextfunc)NULL, /* tp_iternext */
- (struct PyMethodDef*)PyCDebugDump_methods, /* tp_methods */
- (struct PyMemberDef*)0, /* tp_members */
- 0, /* tp_getset */
- NULL, /* tp_base */
- NULL, /* tp_dict */
- (descrgetfunc)NULL, /* tp_descr_get */
- (descrsetfunc)NULL, /* tp_descr_set */
- 0, /* tp_dictoffset */
- (initproc)_wrap_PyCDebugDump__tp_init, /* tp_init */
- (allocfunc)PyType_GenericAlloc, /* tp_alloc */
- (newfunc)PyType_GenericNew, /* tp_new */
- (freefunc)0, /* tp_free */
- (inquiry)NULL, /* tp_is_gc */
- NULL, /* tp_bases */
- NULL, /* tp_mro */
- NULL, /* tp_cache */
- NULL, /* tp_subclasses */
- NULL, /* tp_weaklist */
- (destructor) NULL /* tp_del */
-};
-
-
-
-PyMODINIT_FUNC
-initABRTUtils(void)
-{
- PyObject *m;
- m = Py_InitModule3((char *) "ABRTUtils", ABRTUtils_functions, NULL);
- if (m == NULL) {
- return;
- }
- /* Register the 'CDebugDump' class */
- if (PyType_Ready(&PyCDebugDump_Type)) {
- return;
- }
- PyModule_AddObject(m, (char *) "CDebugDump", (PyObject *) &PyCDebugDump_Type);
-}
diff --git a/lib/Python/PyBindingGenerator.py b/lib/Python/PyBindingGenerator.py
deleted file mode 100644
index a2d62d5..0000000
--- a/lib/Python/PyBindingGenerator.py
+++ /dev/null
@@ -1,27 +0,0 @@
-from pybindgen import *
-import sys
-"""
- void Open(const std::string& pDir);
- void Create(const std::string& pDir);
- void Delete();
- void Close();
-
- bool Exist(const std::string& pFileName);
-
- void LoadText(const std::string& pName, std::string& pData);
- void LoadBinary(const std::string& pName, char** pData, unsigned int* pSize);
-
- void SaveText(const std::string& pName, const std::string& pData);
- void SaveBinary(const std::string& pName, const char* pData, const unsigned int pSize);
-
- void InitGetNextFile();
- bool GetNextFile(std::string& pFileName, std::string& pContent, bool& pIsTextFile);
-"""
-mod = Module('ABRTUtils')
-mod.add_include('"../Utils/DebugDump.h"')
-klass = mod.add_class('CDebugDump')
-klass.add_constructor([])
-klass.add_method('Create', None, [param('char*', 'pFilename')])
-klass.add_method('Close', None, [])
-klass.add_method('SaveText', None, [param('char*', 'pName'), param('char*', 'pData')])
-mod.generate(sys.stdout)
diff --git a/lib/Python/PyDebugDump.cpp b/lib/Python/PyDebugDump.cpp
deleted file mode 100644
index 0f6de47..0000000
--- a/lib/Python/PyDebugDump.cpp
+++ /dev/null
@@ -1,248 +0,0 @@
-/* This file was generated by PyBindGen 0.10.0 */
-#define PY_SSIZE_T_CLEAN
-#include <Python.h>
-#include <stddef.h>
-
-
-#if PY_VERSION_HEX < 0x020400F0
-
-#define PyEval_ThreadsInitialized() 1
-
-#define Py_CLEAR(op) \
- do { \
- if (op) { \
- PyObject *tmp = (PyObject *)(op); \
- (op) = NULL; \
- Py_DECREF(tmp); \
- } \
- } while (0)
-
-
-#define Py_VISIT(op) \
- do { \
- if (op) { \
- int vret = visit((PyObject *)(op), arg); \
- if (vret) \
- return vret; \
- } \
- } while (0)
-
-#endif
-
-
-
-#if PY_VERSION_HEX < 0x020500F0
-
-typedef int Py_ssize_t;
-# define PY_SSIZE_T_MAX INT_MAX
-# define PY_SSIZE_T_MIN INT_MIN
-typedef inquiry lenfunc;
-typedef intargfunc ssizeargfunc;
-typedef intobjargproc ssizeobjargproc;
-
-#endif
-
-
-#if __GNUC__ > 2
-# define PYBINDGEN_UNUSED(param) param __attribute__((__unused__))
-#elif __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
-# define PYBINDGEN_UNUSED(param) __attribute__((__unused__)) param
-#else
-# define PYBINDGEN_UNUSED(param)
-#endif /* !__GNUC__ */
-
-#include "../Utils/DebugDump.h"
-/* --- forward declarations --- */
-
-
-typedef struct {
- PyObject_HEAD
- CDebugDump *obj;
-} PyCDebugDump;
-
-
-extern PyTypeObject PyCDebugDump_Type;
-
-static PyMethodDef ABRTUtils_functions[] = {
- {NULL, NULL, 0, NULL}
-};
-/* --- classes --- */
-
-
-
-static int
-_wrap_PyCDebugDump__tp_init(PyCDebugDump *self, PyObject *args, PyObject *kwargs)
-{
- static const char *const keywords[] = {NULL};
-
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "", (char **) keywords)) {
- return -1;
- }
- self->obj = new CDebugDump();
- return 0;
-}
-
-
-PyObject *
-_wrap_PyCDebugDump_Close(PyCDebugDump *self)
-{
- PyObject *py_retval;
-
- self->obj->Close();
- Py_INCREF(Py_None);
- py_retval = Py_None;
- return py_retval;
-}
-
-
-PyObject *
-_wrap_PyCDebugDump_Create(PyCDebugDump *self, PyObject *args, PyObject *kwargs)
-{
- PyObject *py_retval;
- char *pFilename2;
- int pUID2;
- static const char *const keywords[] = {"pFilename", "pUID", NULL};
-
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "si", (char **) keywords, &pFilename2, &pUID2)) {
- return NULL;
- }
- self->obj->Create(pFilename2, pUID2);
- Py_INCREF(Py_None);
- py_retval = Py_None;
- return py_retval;
-}
-
-
-PyObject *
-_wrap_PyCDebugDump_SaveText(PyCDebugDump *self, PyObject *args, PyObject *kwargs)
-{
- PyObject *py_retval;
- char *pName2;
- char *pData2;
- static const char *const keywords[] = {"pName", "pData", NULL};
-
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "ss", (char **) keywords, &pName2, &pData2)) {
- return NULL;
- }
- self->obj->SaveText(pName2, pData2);
- Py_INCREF(Py_None);
- py_retval = Py_None;
- return py_retval;
-}
-
-static PyMethodDef PyCDebugDump_methods[] = {
- {(char *) "Close", (PyCFunction) _wrap_PyCDebugDump_Close, METH_NOARGS, NULL },
- {(char *) "Create", (PyCFunction) _wrap_PyCDebugDump_Create, METH_KEYWORDS|METH_VARARGS, NULL },
- {(char *) "SaveText", (PyCFunction) _wrap_PyCDebugDump_SaveText, METH_KEYWORDS|METH_VARARGS, NULL },
- {NULL, NULL, 0, NULL}
-};
-
-static void
-_wrap_PyCDebugDump__tp_dealloc(PyCDebugDump *self)
-{
- CDebugDump *tmp = self->obj;
- self->obj = NULL;
- delete tmp;
- self->ob_type->tp_free((PyObject*)self);
-}
-
-static PyObject*
-_wrap_PyCDebugDump__tp_richcompare (PyCDebugDump *self, PyCDebugDump *other, int opid)
-{
-
- if (!PyObject_IsInstance((PyObject*) other, (PyObject*) &PyCDebugDump_Type)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- switch (opid)
- {
- case Py_LT:
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- case Py_LE:
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- case Py_EQ:
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- case Py_NE:
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- case Py_GE:
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- case Py_GT:
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- } /* closes switch (opid) */
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
-}
-
-PyTypeObject PyCDebugDump_Type = {
- PyObject_HEAD_INIT(NULL)
- 0, /* ob_size */
- (char *) "ABRTUtils.CDebugDump", /* tp_name */
- sizeof(PyCDebugDump), /* tp_basicsize */
- 0, /* tp_itemsize */
- /* methods */
- (destructor)_wrap_PyCDebugDump__tp_dealloc, /* tp_dealloc */
- (printfunc)0, /* tp_print */
- (getattrfunc)NULL, /* tp_getattr */
- (setattrfunc)NULL, /* tp_setattr */
- (cmpfunc)NULL, /* tp_compare */
- (reprfunc)NULL, /* tp_repr */
- (PyNumberMethods*)NULL, /* tp_as_number */
- (PySequenceMethods*)NULL, /* tp_as_sequence */
- (PyMappingMethods*)NULL, /* tp_as_mapping */
- (hashfunc)NULL, /* tp_hash */
- (ternaryfunc)NULL, /* tp_call */
- (reprfunc)NULL, /* tp_str */
- (getattrofunc)NULL, /* tp_getattro */
- (setattrofunc)NULL, /* tp_setattro */
- (PyBufferProcs*)NULL, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
- NULL, /* Documentation string */
- (traverseproc)NULL, /* tp_traverse */
- (inquiry)NULL, /* tp_clear */
- (richcmpfunc)_wrap_PyCDebugDump__tp_richcompare, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- (getiterfunc)NULL, /* tp_iter */
- (iternextfunc)NULL, /* tp_iternext */
- (struct PyMethodDef*)PyCDebugDump_methods, /* tp_methods */
- (struct PyMemberDef*)0, /* tp_members */
- 0, /* tp_getset */
- NULL, /* tp_base */
- NULL, /* tp_dict */
- (descrgetfunc)NULL, /* tp_descr_get */
- (descrsetfunc)NULL, /* tp_descr_set */
- 0, /* tp_dictoffset */
- (initproc)_wrap_PyCDebugDump__tp_init, /* tp_init */
- (allocfunc)PyType_GenericAlloc, /* tp_alloc */
- (newfunc)PyType_GenericNew, /* tp_new */
- (freefunc)0, /* tp_free */
- (inquiry)NULL, /* tp_is_gc */
- NULL, /* tp_bases */
- NULL, /* tp_mro */
- NULL, /* tp_cache */
- NULL, /* tp_subclasses */
- NULL, /* tp_weaklist */
- (destructor) NULL /* tp_del */
-};
-
-
-
-PyMODINIT_FUNC
-initABRTUtils(void)
-{
- PyObject *m;
- m = Py_InitModule3((char *) "ABRTUtils", ABRTUtils_functions, NULL);
- if (m == NULL) {
- return;
- }
- /* Register the 'CDebugDump' class */
- if (PyType_Ready(&PyCDebugDump_Type)) {
- return;
- }
- PyModule_AddObject(m, (char *) "CDebugDump", (PyObject *) &PyCDebugDump_Type);
-}
diff --git a/lib/Utils/CommLayerInner.cpp b/lib/Utils/CommLayerInner.cpp
index 307fe66..133e97d 100644
--- a/lib/Utils/CommLayerInner.cpp
+++ b/lib/Utils/CommLayerInner.cpp
@@ -72,7 +72,7 @@ void update_client(const char *fmt, ...)
int used = vasprintf(&msg, fmt, p);
va_end(p);
if (used < 0)
- return;
+ return;
s_pObs->Status(msg, peer, key);
}
diff --git a/lib/Utils/DebugDump.cpp b/lib/Utils/DebugDump.cpp
index ba11d96..2883d01 100644
--- a/lib/Utils/DebugDump.cpp
+++ b/lib/Utils/DebugDump.cpp
@@ -74,7 +74,7 @@ void CDebugDump::Open(const char *pDir)
bool CDebugDump::Exist(const char* pPath)
{
- std::string fullPath = m_sDebugDumpDir + "/" + pPath;
+ std::string fullPath = concat_path_file(m_sDebugDumpDir.c_str(), pPath);
return ExistFileDir(fullPath.c_str());
}
@@ -433,7 +433,7 @@ void CDebugDump::LoadText(const char* pName, std::string& pData)
{
throw CABRTException(EXCEP_DD_OPEN, "CDebugDump::LoadText(): DebugDump is not opened.");
}
- std::string fullPath = m_sDebugDumpDir + '/' + pName;
+ std::string fullPath = concat_path_file(m_sDebugDumpDir.c_str(), pName);
LoadTextFile(fullPath.c_str(), pData);
}
@@ -443,7 +443,7 @@ void CDebugDump::SaveText(const char* pName, const char* pData)
{
throw CABRTException(EXCEP_DD_OPEN, "CDebugDump::SaveText(): DebugDump is not opened.");
}
- std::string fullPath = m_sDebugDumpDir + "/" + pName;
+ std::string fullPath = concat_path_file(m_sDebugDumpDir.c_str(), pName);
SaveBinaryFile(fullPath.c_str(), pData, strlen(pData));
}
void CDebugDump::SaveBinary(const char* pName, const char* pData, unsigned pSize)
@@ -452,7 +452,7 @@ void CDebugDump::SaveBinary(const char* pName, const char* pData, unsigned pSize
{
throw CABRTException(EXCEP_DD_OPEN, "CDebugDump::SaveBinary(): DebugDump is not opened.");
}
- std::string fullPath = m_sDebugDumpDir + "/" + pName;
+ std::string fullPath = concat_path_file(m_sDebugDumpDir.c_str(), pName);
SaveBinaryFile(fullPath.c_str(), pData, pSize);
}
diff --git a/lib/Utils/Makefile.am b/lib/Utils/Makefile.am
index f752992..eae4148 100644
--- a/lib/Utils/Makefile.am
+++ b/lib/Utils/Makefile.am
@@ -4,6 +4,7 @@ lib_LTLIBRARIES = libABRTUtils.la
# time.cpp
# xconnect.cpp
+# removed: CrashTypesSocket.cpp
libABRTUtils_la_SOURCES = \
stringops.cpp \
xfuncs.cpp \
@@ -14,7 +15,6 @@ libABRTUtils_la_SOURCES = \
skip_whitespace.cpp \
popen_and_save_output.cpp \
parse_release.cpp \
- CrashTypesSocket.cpp \
DebugDump.h DebugDump.cpp \
CommLayerInner.h CommLayerInner.cpp \
abrt_dbus.h abrt_dbus.cpp \
diff --git a/lib/Utils/make_descr.cpp b/lib/Utils/make_descr.cpp
index 1352149..0c09614 100644
--- a/lib/Utils/make_descr.cpp
+++ b/lib/Utils/make_descr.cpp
@@ -75,7 +75,7 @@ string make_description_bz(const map_crash_report_t& pCrashReport)
&& filename != FILENAME_RELEASE
&& filename != CD_REPRODUCE
&& filename != CD_COMMENT
- ) {
+ ) {
add_content(was_multiline, description, filename.c_str(), content.c_str());
}
}
diff --git a/lib/Utils/stringops.cpp b/lib/Utils/stringops.cpp
index 1b3793f..dc71b5b 100644
--- a/lib/Utils/stringops.cpp
+++ b/lib/Utils/stringops.cpp
@@ -3,24 +3,33 @@
void parse_args(const char *psArgs, vector_string_t& pArgs, int quote)
{
unsigned ii;
- bool is_quote = false;
+ bool inside_quotes = false;
std::string item;
for (ii = 0; psArgs[ii]; ii++)
{
- if (quote != -1 && psArgs[ii] == quote)
+ if (quote != -1)
{
- is_quote = !is_quote;
+ if (psArgs[ii] == quote)
+ {
+ inside_quotes = !inside_quotes;
+ continue;
+ }
+ /* inside quotes we support escaping with \x */
+ if (inside_quotes && psArgs[ii] == '\\' && psArgs[ii+1])
+ {
+ ii++;
+ item += psArgs[ii];
+ continue;
+ }
}
- else if (psArgs[ii] == ',' && !is_quote)
+ if (psArgs[ii] == ',' && !inside_quotes)
{
pArgs.push_back(item);
item.clear();
+ continue;
}
- else
- {
- item += psArgs[ii];
- }
+ item += psArgs[ii];
}
if (item.size() != 0)