diff options
Diffstat (limited to 'lib')
47 files changed, 1371 insertions, 1242 deletions
diff --git a/lib/Plugins/Bugzilla.cpp b/lib/Plugins/Bugzilla.cpp index ca83d369..06f93342 100644 --- a/lib/Plugins/Bugzilla.cpp +++ b/lib/Plugins/Bugzilla.cpp @@ -1,69 +1,25 @@ #include <xmlrpc-c/base.h> #include <xmlrpc-c/client.h> #include "abrtlib.h" +#include "abrt_xmlrpc.h" #include "Bugzilla.h" #include "CrashTypes.h" #include "DebugDump.h" #include "ABRTException.h" #include "CommLayerInner.h" #ifdef HAVE_CONFIG_H - #include <config.h> +# include <config.h> #endif #define XML_RPC_SUFFIX "/xmlrpc.cgi" -static void get_product_and_version(const std::string& pRelease, - std::string& pProduct, - std::string& pVersion) -{ - if (pRelease.find("Rawhide") != std::string::npos) - { - pProduct = "Fedora"; - pVersion = "rawhide"; - return; - } - if (pRelease.find("Fedora") != std::string::npos) - { - pProduct = "Fedora"; - } - else if (pRelease.find("Red Hat Enterprise Linux") != std::string::npos) - { - pProduct = "Red Hat Enterprise Linux "; - } - std::string::size_type pos = pRelease.find("release"); - pos = pRelease.find(" ", pos) + 1; - while (pRelease[pos] != ' ') - { - pVersion += pRelease[pos]; - if (pProduct == "Red Hat Enterprise Linux ") - { - pProduct += pRelease[pos]; - } - pos++; - } -} - static void create_new_bug_description(const map_crash_report_t& pCrashReport, std::string& pDescription) { pDescription = "abrt detected a crash.\n\n"; pDescription += make_description_bz(pCrashReport); } -// FIXME: we still leak memory if this function detects a fault: -// many instances when we leave non-freed or non-xmlrpc_DECREF'ed data behind. -static void throw_if_xml_fault_occurred(xmlrpc_env *env) -{ - if (env->fault_occurred) - { - std::string errmsg = ssprintf("XML-RPC Fault: %s(%d)", env->fault_string, env->fault_code); - xmlrpc_env_clean(env); // this is needed ONLY if fault_occurred - xmlrpc_env_init(env); // just in case user catches ex and _continues_ to use env - error_msg("%s", errmsg.c_str()); // show error in daemon log - throw CABRTException(EXCEP_PLUGIN, errmsg); - } -} - /* * Static namespace for xmlrpc stuff. @@ -72,81 +28,18 @@ static void throw_if_xml_fault_occurred(xmlrpc_env *env) namespace { -struct ctx { - xmlrpc_client* client; - xmlrpc_server_info* server_info; +struct ctx: public abrt_xmlrpc_conn { + ctx(const char* url, bool no_ssl_verify): abrt_xmlrpc_conn(url, no_ssl_verify) {} - ctx(const char* url, bool no_ssl_verify) { new_xmlrpc_client(url, no_ssl_verify); } - ~ctx() { destroy_xmlrpc_client(); } - - void new_xmlrpc_client(const char* url, bool no_ssl_verify); - void destroy_xmlrpc_client(); - - void login(const char* login, const char* passwd); - void logout(); - int32_t check_uuid_in_bugzilla(const char* component, const char* UUID); - bool check_cc_and_reporter(uint32_t bug_id, const char* login); - void add_plus_one_cc(uint32_t bug_id, const char* login); - uint32_t new_bug(const map_crash_report_t& pCrashReport); - void add_attachments(const char* bug_id_str, const map_crash_report_t& pCrashReport); + void login(const char* login, const char* passwd); + void logout(); + int32_t check_uuid_in_bugzilla(const char* component, const char* UUID); + bool check_cc_and_reporter(uint32_t bug_id, const char* login); + void add_plus_one_cc(uint32_t bug_id, const char* login); + uint32_t new_bug(const map_crash_report_t& pCrashReport); + void add_attachments(const char* bug_id_str, const map_crash_report_t& pCrashReport); }; -void ctx::new_xmlrpc_client(const char* url, bool no_ssl_verify) -{ - xmlrpc_env env; - xmlrpc_env_init(&env); - - /* This should be done at program startup, once. - * We do it in abrtd's main */ - /* xmlrpc_client_setup_global_const(&env); */ - - struct xmlrpc_curl_xportparms curlParms; - memset(&curlParms, 0, sizeof(curlParms)); - /* curlParms.network_interface = NULL; - done by memset */ - curlParms.no_ssl_verifypeer = no_ssl_verify; - curlParms.no_ssl_verifyhost = no_ssl_verify; -#ifdef VERSION - curlParms.user_agent = PACKAGE_NAME"/"VERSION; -#else - curlParms.user_agent = "abrt"; -#endif - - struct xmlrpc_clientparms clientParms; - memset(&clientParms, 0, sizeof(clientParms)); - clientParms.transport = "curl"; - clientParms.transportparmsP = &curlParms; - clientParms.transportparm_size = XMLRPC_CXPSIZE(user_agent); - - client = NULL; - xmlrpc_client_create(&env, XMLRPC_CLIENT_NO_FLAGS, - PACKAGE_NAME, VERSION, - &clientParms, XMLRPC_CPSIZE(transportparm_size), - &client); - throw_if_xml_fault_occurred(&env); - - server_info = xmlrpc_server_info_new(&env, url); - if (env.fault_occurred) - { - xmlrpc_client_destroy(client); - client = NULL; - } - throw_if_xml_fault_occurred(&env); -} - -void ctx::destroy_xmlrpc_client() -{ - if (server_info) - { - xmlrpc_server_info_free(server_info); - server_info = NULL; - } - if (client) - { - xmlrpc_client_destroy(client); - client = NULL; - } -} - void ctx::login(const char* login, const char* passwd) { xmlrpc_env env; @@ -156,7 +49,7 @@ void ctx::login(const char* login, const char* passwd) throw_if_xml_fault_occurred(&env); xmlrpc_value* result = NULL; - xmlrpc_client_call2(&env, client, server_info, "User.login", param, &result); + xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "User.login", param, &result); xmlrpc_DECREF(param); if (result) xmlrpc_DECREF(result); @@ -179,7 +72,7 @@ void ctx::logout() throw_if_xml_fault_occurred(&env); xmlrpc_value* result = NULL; - xmlrpc_client_call2(&env, client, server_info, "User.logout", param, &result); + xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "User.logout", param, &result); xmlrpc_DECREF(param); if (result) xmlrpc_DECREF(result); @@ -195,7 +88,7 @@ bool ctx::check_cc_and_reporter(uint32_t bug_id, const char* login) throw_if_xml_fault_occurred(&env); xmlrpc_value* result = NULL; - xmlrpc_client_call2(&env, client, server_info, "bugzilla.getBug", param, &result); + xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "bugzilla.getBug", param, &result); throw_if_xml_fault_occurred(&env); xmlrpc_DECREF(param); @@ -263,7 +156,7 @@ void ctx::add_plus_one_cc(uint32_t bug_id, const char* login) throw_if_xml_fault_occurred(&env); xmlrpc_value* result = NULL; - xmlrpc_client_call2(&env, client, server_info, "Bug.update", param, &result); + xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "Bug.update", param, &result); throw_if_xml_fault_occurred(&env); xmlrpc_DECREF(result); @@ -281,7 +174,7 @@ int32_t ctx::check_uuid_in_bugzilla(const char* component, const char* UUID) throw_if_xml_fault_occurred(&env); xmlrpc_value* result = NULL; - xmlrpc_client_call2(&env, client, server_info, "Bug.search", param, &result); + xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "Bug.search", param, &result); throw_if_xml_fault_occurred(&env); xmlrpc_DECREF(param); @@ -313,7 +206,7 @@ int32_t ctx::check_uuid_in_bugzilla(const char* component, const char* UUID) xmlrpc_int bug_id; xmlrpc_read_int(&env, bug, &bug_id); log("Bug is already reported: %i", (int)bug_id); - update_client(_("Bug is already reported: ") + to_string(bug_id)); + update_client(_("Bug is already reported: %i"), (int)bug_id); xmlrpc_DECREF(bug); xmlrpc_DECREF(item); @@ -348,7 +241,7 @@ uint32_t ctx::new_bug(const map_crash_report_t& pCrashReport) std::string product; std::string version; - get_product_and_version(release, product, version); + parse_release(release.c_str(), product, version); xmlrpc_value* param = xmlrpc_build_value(&env, "({s:s,s:s,s:s,s:s,s:s,s:s,s:s})", "product", product.c_str(), @@ -362,7 +255,7 @@ uint32_t ctx::new_bug(const map_crash_report_t& pCrashReport) throw_if_xml_fault_occurred(&env); xmlrpc_value* result; - xmlrpc_client_call2(&env, client, server_info, "Bug.create", param, &result); + xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "Bug.create", param, &result); throw_if_xml_fault_occurred(&env); xmlrpc_value* id; @@ -375,7 +268,7 @@ uint32_t ctx::new_bug(const map_crash_report_t& pCrashReport) xmlrpc_read_int(&env, id, &bug_id); throw_if_xml_fault_occurred(&env); log("New bug id: %i", bug_id); - update_client(_("New bug id: ") + to_string(bug_id)); + update_client(_("New bug id: %i"), bug_id); } xmlrpc_DECREF(result); @@ -409,7 +302,7 @@ void ctx::add_attachments(const char* bug_id_str, const map_crash_report_t& pCra free(encoded64); throw_if_xml_fault_occurred(&env); - xmlrpc_client_call2(&env, client, server_info, "bugzilla.addAttachment", param, &result); + xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "bugzilla.addAttachment", param, &result); throw_if_xml_fault_occurred(&env); xmlrpc_DECREF(result); xmlrpc_DECREF(param); @@ -444,14 +337,14 @@ std::string CReporterBugzilla::Report(const map_crash_report_t& pCrashReport, std::string BugzillaURL; bool NoSSLVerify; map_plugin_settings_t settings = parse_settings(pSettings); - /* if parse_settings fails it returns an empty map so we need to use defaults*/ - if(!settings.empty()) + /* if parse_settings fails it returns an empty map so we need to use defaults */ + if (!settings.empty()) { Login = settings["Login"]; Password = settings["Password"]; BugzillaXMLRPC = settings["BugzillaXMLRPC"]; BugzillaURL = settings["BugzillaURL"]; - NoSSLVerify = settings["NoSSLVerify"] == "yes"; + NoSSLVerify = string_to_bool(settings["NoSSLVerify"].c_str()); } else { @@ -513,9 +406,9 @@ std::string CReporterBugzilla::Report(const map_crash_report_t& pCrashReport, map_plugin_settings_t CReporterBugzilla::parse_settings(const map_plugin_settings_t& pSettings) { map_plugin_settings_t plugin_settings; - map_plugin_settings_t::const_iterator it; - map_plugin_settings_t::const_iterator end = pSettings.end(); + map_plugin_settings_t::const_iterator end = pSettings.end(); + map_plugin_settings_t::const_iterator it; it = pSettings.find("BugzillaURL"); if (it != end) { @@ -567,6 +460,8 @@ map_plugin_settings_t CReporterBugzilla::parse_settings(const map_plugin_setting void CReporterBugzilla::SetSettings(const map_plugin_settings_t& pSettings) { + m_pSettings = pSettings; + //BUG! This gets called when user's keyring contains login data, //then it takes precedence over /etc/abrt/plugins/Bugzilla.conf. //I got a case when keyring had a STALE password, and there was no way @@ -574,9 +469,8 @@ void CReporterBugzilla::SetSettings(const map_plugin_settings_t& pSettings) //(by hacking abrt source!), I don't know how to purge it from the keyring. //At the very least, log("SOMETHING") here. - map_plugin_settings_t::const_iterator it; map_plugin_settings_t::const_iterator end = pSettings.end(); - + map_plugin_settings_t::const_iterator it; it = pSettings.find("BugzillaURL"); if (it != end) { @@ -614,20 +508,19 @@ void CReporterBugzilla::SetSettings(const map_plugin_settings_t& pSettings) it = pSettings.find("NoSSLVerify"); if (it != end) { - m_bNoSSLVerify = (it->second == "yes"); + m_bNoSSLVerify = string_to_bool(it->second.c_str()); } } -map_plugin_settings_t CReporterBugzilla::GetSettings() +/* Should not be deleted (why?) */ +const map_plugin_settings_t& CReporterBugzilla::GetSettings() { - map_plugin_settings_t ret; - - ret["BugzillaURL"] = m_sBugzillaURL; - ret["Login"] = m_sLogin; - ret["Password"] = m_sPassword; - ret["NoSSLVerify"] = m_bNoSSLVerify ? "yes" : "no"; + m_pSettings["BugzillaURL"] = m_sBugzillaURL; + m_pSettings["Login"] = m_sLogin; + m_pSettings["Password"] = m_sPassword; + m_pSettings["NoSSLVerify"] = m_bNoSSLVerify ? "yes" : "no"; - return ret; + return m_pSettings; } PLUGIN_INFO(REPORTER, diff --git a/lib/Plugins/Bugzilla.h b/lib/Plugins/Bugzilla.h index 702eead2..9130a698 100644 --- a/lib/Plugins/Bugzilla.h +++ b/lib/Plugins/Bugzilla.h @@ -8,23 +8,24 @@ class CReporterBugzilla : public CReporter { private: bool m_bNoSSLVerify; - std::string m_sBugzillaURL; std::string m_sBugzillaXMLRPC; std::string m_sLogin; std::string m_sPassword; std::string m_sAttchmentInBase64; - + map_plugin_settings_t parse_settings(const map_plugin_settings_t& pSettings); public: CReporterBugzilla(); virtual ~CReporterBugzilla(); - virtual void SetSettings(const map_plugin_settings_t& pSettings); - virtual map_plugin_settings_t GetSettings(); + virtual std::string Report(const map_crash_report_t& pCrashReport, const map_plugin_settings_t& pSettings, const std::string& pArgs); + + virtual void SetSettings(const map_plugin_settings_t& pSettings); + virtual const map_plugin_settings_t& GetSettings(); }; #endif /* BUGZILLA_H_ */ diff --git a/lib/Plugins/CCpp.cpp b/lib/Plugins/CCpp.cpp index 83622169..82c5677d 100644 --- a/lib/Plugins/CCpp.cpp +++ b/lib/Plugins/CCpp.cpp @@ -95,7 +95,6 @@ static std::string concat_str_vector(char **strings) static pid_t ExecVP(char** pArgs, uid_t uid, std::string& pOutput) { int pipeout[2]; - char buff[1024]; pid_t child; struct passwd* pw = getpwuid(uid); @@ -128,6 +127,18 @@ static pid_t ExecVP(char** pArgs, uid_t uid, std::string& pOutput) 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]); @@ -137,6 +148,7 @@ static pid_t ExecVP(char** pArgs, uid_t uid, std::string& pOutput) 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'; @@ -160,17 +172,21 @@ enum LineRating BestRating = Good, }; -static LineRating rate_line(const std::string & line) +static LineRating rate_line(const char *line) { -#define FOUND(x) (line.find(x) != std::string::npos) - bool function = FOUND(" in ") && !FOUND(" in ??"); - bool library = FOUND(" from "); - bool source_file = FOUND(" at "); -#undef FOUND - +#define FOUND(x) (strstr(line, x) != NULL) /* see the "enum LineRating" comments for possible combinations */ - if (function && source_file) + 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) @@ -179,38 +195,48 @@ static LineRating rate_line(const std::string & line) return MissingFunction; return MissingEverything; +#undef FOUND } /* returns number of "stars" to show */ -int rate_backtrace(const std::string & backtrace) +static int rate_backtrace(const char *backtrace) { - int l = backtrace.length(); - int i; - std::string s; + 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() looks at the first line of the frame + /* 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. + * so that topmost frames end up most important */ - for (i = l-1; i >= 0; i--) + 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) * multiplier; + rating += rate_line(s.c_str()) * multiplier; best_possible_rating += BestRating * multiplier; - s = ""; /* starting new line */ - } else + len = 0; /* starting new line */ + } + else { - s = backtrace[i] + s; + len++; } } - /* returning number of "stars" to show */ + /* 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) @@ -223,7 +249,7 @@ int rate_backtrace(const std::string & backtrace) return 0; } -static void GetBacktrace(const std::string& pDebugDumpDir, std::string& pBacktrace) +static void GetBacktrace(const char *pDebugDumpDir, std::string& pBacktrace) { update_client(_("Getting backtrace...")); @@ -258,7 +284,7 @@ static void GetBacktrace(const std::string& pDebugDumpDir, std::string& pBacktra 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.c_str()); + args[7] = xasprintf("core-file %s/"FILENAME_COREDUMP, pDebugDumpDir); args[8] = (char*)"-ex"; args[9] = (char*)"thread apply all backtrace full"; args[10] = NULL; @@ -420,7 +446,7 @@ static void GetIndependentBuildIdPC(const std::string& pBuildIdPC, std::string& } } -static std::string run_unstrip_n(const std::string& pDebugDumpDir) +static std::string run_unstrip_n(const char *pDebugDumpDir) { std::string UID; { @@ -431,7 +457,7 @@ static std::string run_unstrip_n(const std::string& pDebugDumpDir) char* args[4]; args[0] = (char*)"eu-unstrip"; - args[1] = xasprintf("--core=%s/"FILENAME_COREDUMP, pDebugDumpDir.c_str()); + args[1] = xasprintf("--core=%s/"FILENAME_COREDUMP, pDebugDumpDir); args[2] = (char*)"-n"; args[3] = NULL; @@ -455,7 +481,7 @@ static bool is_hexstr(const char* str) } return true; } -static void InstallDebugInfos(const std::string& pDebugDumpDir, std::string& build_ids) +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); @@ -610,8 +636,8 @@ Another application is holding the yum lock, cannot continue if (last >= 0 && buff[last] == '\n') buff[last] = '\0'; - /* log(buff); - update_client logs it too */ - update_client(buff); /* maybe only if buff != ""? */ + log("%s", buff); + update_client("%s", buff); /* maybe only if buff != ""? */ #ifdef COMPLAIN_IF_NO_DEBUGINFO if (already_installed == false) @@ -648,7 +674,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 std::string& pDebugDumpDir, std::string& build_ids) +static void InstallDebugInfos(const char *pDebugDumpDir, std::string& build_ids) { update_client(_("Searching for debug-info packages...")); @@ -673,7 +699,7 @@ static void InstallDebugInfos(const std::string& pDebugDumpDir, std::string& bui setsid(); - char *coredump = xasprintf("%s/"FILENAME_COREDUMP, pDebugDumpDir.c_str()); + 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 */ @@ -715,8 +741,8 @@ static void InstallDebugInfos(const std::string& pDebugDumpDir, std::string& bui } if (*p) { - /* log(buff); - update_client logs it too */ - update_client(buff); + log("%s", buff); + update_client("%s", buff); } } @@ -787,7 +813,7 @@ static void trim_debuginfo_cache(unsigned max_mb) } } -std::string CAnalyzerCCpp::GetLocalUUID(const std::string& pDebugDumpDir) +std::string CAnalyzerCCpp::GetLocalUUID(const char *pDebugDumpDir) { log(_("Getting local universal unique identification...")); @@ -806,7 +832,7 @@ std::string CAnalyzerCCpp::GetLocalUUID(const std::string& pDebugDumpDir) return CreateHash(package + executable + independentBuildIdPC); } -std::string CAnalyzerCCpp::GetGlobalUUID(const std::string& pDebugDumpDir) +std::string CAnalyzerCCpp::GetGlobalUUID(const char *pDebugDumpDir) { log(_("Getting global universal unique identification...")); @@ -851,7 +877,7 @@ static bool DebuginfoCheckPolkit(int uid) return false; } -void CAnalyzerCCpp::CreateReport(const std::string& pDebugDumpDir, int force) +void CAnalyzerCCpp::CreateReport(const char *pDebugDumpDir, int force) { update_client(_("Starting report creation...")); @@ -889,13 +915,12 @@ void CAnalyzerCCpp::CreateReport(const std::string& pDebugDumpDir, int force) GetBacktrace(pDebugDumpDir, backtrace); dd.Open(pDebugDumpDir); - dd.SaveText(FILENAME_BACKTRACE, build_ids + backtrace); + 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"); } - std::string rating = ssprintf("%d", rate_backtrace(backtrace)); - dd.SaveText(FILENAME_RATING, rating); + dd.SaveText(FILENAME_RATING, to_string(rate_backtrace(backtrace.c_str())).c_str()); dd.Close(); } @@ -948,12 +973,14 @@ void CAnalyzerCCpp::DeInit() void CAnalyzerCCpp::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 = it->second == "yes"; + m_bMemoryMap = string_to_bool(it->second.c_str()); } it = pSettings.find("DebugInfo"); if (it != end) @@ -970,21 +997,20 @@ void CAnalyzerCCpp::SetSettings(const map_plugin_settings_t& pSettings) it = pSettings.find("InstallDebuginfo"); if (it != end) { - m_bInstallDebugInfo = it->second == "yes"; + m_bInstallDebugInfo = string_to_bool(it->second.c_str()); } } -map_plugin_settings_t CAnalyzerCCpp::GetSettings() -{ - map_plugin_settings_t ret; - - ret["MemoryMap"] = m_bMemoryMap ? "yes" : "no"; - ret["DebugInfo"] = m_sDebugInfo; - ret["DebugInfoCacheMB"] = to_string(m_nDebugInfoCacheMB); - ret["InstallDebugInfo"] = m_bInstallDebugInfo ? "yes" : "no"; - - return ret; -} +//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, CAnalyzerCCpp, diff --git a/lib/Plugins/CCpp.h b/lib/Plugins/CCpp.h index f3f911ef..3fa0d99a 100644 --- a/lib/Plugins/CCpp.h +++ b/lib/Plugins/CCpp.h @@ -35,15 +35,17 @@ class CAnalyzerCCpp : public CAnalyzer unsigned m_nDebugInfoCacheMB; std::string m_sOldCorePattern; std::string m_sDebugInfo; + public: CAnalyzerCCpp(); - virtual std::string GetLocalUUID(const std::string& pDebugDumpDir); - virtual std::string GetGlobalUUID(const std::string& pDebugDumpDir); - virtual void CreateReport(const std::string& pDebugDumpDir, int force); + 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); - virtual map_plugin_settings_t GetSettings(); +//ok to delete? +// virtual const map_plugin_settings_t& GetSettings(); }; #endif /* CCPP */ diff --git a/lib/Plugins/Catcut.cpp b/lib/Plugins/Catcut.cpp index 6bb44a9d..e6d16b4f 100644 --- a/lib/Plugins/Catcut.cpp +++ b/lib/Plugins/Catcut.cpp @@ -1,7 +1,8 @@ #include <xmlrpc-c/base.h> #include <xmlrpc-c/client.h> - +#include <curl/curl.h> #include "abrtlib.h" +#include "abrt_xmlrpc.h" #include "Catcut.h" #include "CrashTypes.h" #include "DebugDump.h" @@ -13,108 +14,8 @@ using namespace std; -static xmlrpc_env env; -static xmlrpc_client* client = NULL; -static struct xmlrpc_clientparms clientParms; -static struct xmlrpc_curl_xportparms curlParms; -static xmlrpc_server_info* server_info = NULL; - - -static string login(const char* login, const char* passwd); -//static void logout(); -static void new_xmlrpc_client(const char* url, bool no_ssl_verify); -static void destroy_xmlrpc_client(); -static void create_new_bug_description(const map_crash_report_t& pCrashReport, string& pDescription); -static void get_product_and_version(const string& pRelease, - string& pProduct, - string& pVersion); - - -static void throw_if_xml_fault_occurred() -{ - if (env.fault_occurred) - { - string errmsg = ssprintf("XML-RPC Fault: %s(%d)", env.fault_string, env.fault_code); - error_msg("%s", errmsg.c_str()); // show error in daemon log - throw CABRTException(EXCEP_PLUGIN, errmsg); - } -} - -static void new_xmlrpc_client(const char* url, bool no_ssl_verify) -{ - xmlrpc_env_init(&env); - - /* This should be done at program startup, once. - * We do it in abrtd's main */ - /* xmlrpc_client_setup_global_const(&env); */ - - curlParms.network_interface = NULL; - curlParms.no_ssl_verifypeer = no_ssl_verify; - curlParms.no_ssl_verifyhost = no_ssl_verify; -#ifdef VERSION - curlParms.user_agent = PACKAGE_NAME"/"VERSION; -#else - curlParms.user_agent = "abrt"; -#endif - - clientParms.transport = "curl"; - clientParms.transportparmsP = &curlParms; - clientParms.transportparm_size = XMLRPC_CXPSIZE(user_agent); - - xmlrpc_client_create(&env, XMLRPC_CLIENT_NO_FLAGS, PACKAGE_NAME, VERSION, &clientParms, XMLRPC_CPSIZE(transportparm_size), - &client); - throw_if_xml_fault_occurred(); - - server_info = xmlrpc_server_info_new(&env, url); - throw_if_xml_fault_occurred(); -} - -static void destroy_xmlrpc_client() -{ - xmlrpc_server_info_free(server_info); - xmlrpc_env_clean(&env); - xmlrpc_client_destroy(client); -} - -static string login(const char* login, const char* passwd) -{ - xmlrpc_value* param = xmlrpc_build_value(&env, "(ss)", login, passwd); - throw_if_xml_fault_occurred(); - - xmlrpc_value* result; - xmlrpc_client_call2(&env, client, server_info, "Catcut.auth", param, &result); - throw_if_xml_fault_occurred(); - xmlrpc_DECREF(param); - - xmlrpc_value *cookie_xml; - const char *cookie; - string cookie_str; - xmlrpc_struct_find_value(&env, result, "cookie", &cookie_xml); - throw_if_xml_fault_occurred(); - xmlrpc_read_string(&env, cookie_xml, &cookie); - throw_if_xml_fault_occurred(); - cookie_str = cookie; - /* xmlrpc_read_string returns *malloc'ed ptr*. - * doc is not very clear on it, but I looked in xmlrpc sources. */ - free((void*)cookie); - xmlrpc_DECREF(cookie_xml); - - xmlrpc_DECREF(result); - - return cookie_str; -} - -// catcut does not have it (yet?) -//static void logout() -//{ -// xmlrpc_value* param = xmlrpc_build_value(&env, "(s)", ""); -// throw_if_xml_fault_occurred(); -// -// xmlrpc_value* result = NULL; /* paranoia */ -// xmlrpc_client_call2(&env, client, server_info, "User.logout", param, &result); -// throw_if_xml_fault_occurred(); -//} +//TODO: move to make_descr.cpp static void create_new_bug_description(const map_crash_report_t& pCrashReport, string& pDescription) { string howToReproduce; @@ -162,46 +63,258 @@ static void create_new_bug_description(const map_crash_report_t& pCrashReport, s } else if (it->second[CD_TYPE] == CD_BIN) { - string msg = ssprintf(_("Binary file %s will not be reported."), it->first.c_str()); - warn_client(msg); - //update_client(_("Binary file ")+it->first+_(" will not be reported.")); + error_msg(_("Binary file %s will not be reported"), it->first.c_str()); } } } -static void get_product_and_version(const string& pRelease, - string& pProduct, - string& pVersion) +static int +put_stream(const char *pURL, FILE* f, size_t content_length) { - if (pRelease.find("Rawhide") != string::npos) + CURL* curl = curl_easy_init(); + if (!curl) { - pProduct = "Fedora"; - pVersion = "rawhide"; + throw CABRTException(EXCEP_PLUGIN, "put_stream: Curl library error."); + } + /* enable uploading */ + curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); + /* specify target */ + curl_easy_setopt(curl, CURLOPT_URL, pURL); + /* file handle: passed to the default callback, it will fread() it */ + curl_easy_setopt(curl, CURLOPT_READDATA, f); + /* get file size */ + curl_easy_setopt(curl, CURLOPT_INFILESIZE, content_length); + /*everything is done here; result 0 means success*/ + int result = curl_easy_perform(curl); + /* goodbye */ + curl_easy_cleanup(curl); + return result; +} + +static void +send_string(const char *pURL, + const char *pContent, + int retryCount, + int retryDelaySeconds) +{ + if (pURL[0] == '\0') + { + error_msg(_("send_string: URL not specified")); return; } - if (pRelease.find("Fedora") != string::npos) + + do { - pProduct = "Fedora"; + int content_length = strlen(pContent); + FILE* f = fmemopen((void*)pContent, content_length, "r"); + if (!f) + { + throw CABRTException(EXCEP_PLUGIN, "send_string: could not open string stream"); + } + int result = put_stream(pURL, f, content_length); + fclose(f); + if (!result) + return; + update_client(_("Sending failed, try it again: %s"), curl_easy_strerror((CURLcode)result)); } - else if (pRelease.find("Red Hat Enterprise Linux") != string::npos) + /*retry the upload if not succesful, wait a bit before next try*/ + while (--retryCount != 0 && (sleep(retryDelaySeconds), 1)); + + throw CABRTException(EXCEP_PLUGIN, "send_string: could not send string"); +} + +static void +send_file(const char *pURL, + const char *pFilename, + int retryCount, + int retryDelaySeconds) +{ + if (pURL[0] == '\0') { - pProduct = "Red Hat Enterprise Linux "; + error_msg(_("send_file: URL not specified")); + return; } - string::size_type pos = pRelease.find("release"); - pos = pRelease.find(" ", pos) + 1; - while (pRelease[pos] != ' ') + + update_client(_("Sending file %s to %s"), pFilename, pURL); + + do { - pVersion += pRelease[pos]; - if (pProduct == "Red Hat Enterprise Linux ") + FILE* f = fopen(pFilename, "r"); + if (!f) { - pProduct += pRelease[pos]; + throw CABRTException(EXCEP_PLUGIN, "send_file: could not open string stream"); } - pos++; + struct stat buf; + fstat(fileno(f), &buf); /* can't fail */ + int content_length = buf.st_size; + int result = put_stream(pURL, f, content_length); + fclose(f); + if (!result) + return; + update_client(_("Sending failed, try it again: %s"), curl_easy_strerror((CURLcode)result)); } + /*retry the upload if not succesful, wait a bit before next try*/ + while (--retryCount != 0 && (sleep(retryDelaySeconds), 1)); + + throw CABRTException(EXCEP_PLUGIN, "send_file: could not send file"); +} + +static string +resolve_relative_url(const char *url, const char *base) +{ + // if 'url' is relative (not absolute) combine it with 'base' + // (which must be absolute) + // Only works in limited cases: + // 0) url is already absolute + // 1) url starts with two slashes + // 2) url starts with one slash + + const char *colon = strchr(url, ':'); + const char *slash = strchr(url, '/'); + + if (colon && (!slash || colon < slash)) + { + return url; + } + + const char *end_of_protocol = strchr(base, ':'); + string protocol(base, end_of_protocol - base); + + end_of_protocol += 3; /* skip "://" */ + const char *end_of_host = strchr(end_of_protocol, '/'); + string host(end_of_protocol, end_of_host - end_of_protocol); + + if (url[0] == '/') + { + if (url[1] == '/') + { + protocol += ':'; + protocol += url; + return protocol; + } + protocol += "://"; + protocol += host; + protocol += url; + return protocol; + } + throw CABRTException(EXCEP_PLUGIN, "resolve_relative_url: unhandled relative url"); +} + +// +// struct_find_XXXX +// abstract all the busy work of getting a field's value from +// a struct. XXXX is a type. +// Return true/false = the field is in the struct +// If true, return the field's value in 'value'. +// +// This function currently just assumes that the value in the +// field can be read into the type of 'value'. This should probably +// be fixed to either convert the fields value to the type of 'value' +// or error specifically/usefully. +// +// This function probably should be converted to an overloaded function +// (overloaded on the type of 'value'). It could also be a function +// template. +// + +static bool +struct_find_int(xmlrpc_env* env, xmlrpc_value* result, + const char* fieldName, int& value) +{ + xmlrpc_value* an_xmlrpc_value; + xmlrpc_struct_find_value(env, result, fieldName, &an_xmlrpc_value); + throw_if_xml_fault_occurred(env); + if (an_xmlrpc_value) + { + xmlrpc_read_int(env, an_xmlrpc_value, &value); + throw_if_xml_fault_occurred(env); + xmlrpc_DECREF(an_xmlrpc_value); + return true; + } + return false; +} + +static bool +struct_find_string(xmlrpc_env* env, xmlrpc_value* result, + const char* fieldName, string& value) +{ + xmlrpc_value* an_xmlrpc_value; + xmlrpc_struct_find_value(env, result, fieldName, &an_xmlrpc_value); + throw_if_xml_fault_occurred(env); + if (an_xmlrpc_value) + { + const char* value_s; + xmlrpc_read_string(env, an_xmlrpc_value, &value_s); + throw_if_xml_fault_occurred(env); + value = value_s; + xmlrpc_DECREF(an_xmlrpc_value); + free((void*)value_s); + return true; + } + return false; +} + + +/* + * Static namespace for xmlrpc stuff. + * Used mainly to ensure we always destroy xmlrpc client and server_info. + */ + +namespace { + +struct ctx: public abrt_xmlrpc_conn { + ctx(const char* url, bool no_ssl_verify): abrt_xmlrpc_conn(url, no_ssl_verify) {} + + string login(const char* login, const char* passwd); + string new_bug(const char *auth_cookie, const map_crash_report_t& pCrashReport); + string request_upload(const char* auth_cookie, const char* pTicketName, + const char* fileName, const char* description); + void add_attachments(const char* xmlrpc_URL, + const char* auth_cookie, + const char* pTicketName, + const map_crash_report_t& pCrashReport, + int retryCount, + int retryDelaySeconds); +}; + +string +ctx::login(const char* login, const char* passwd) +{ + xmlrpc_env env; + xmlrpc_env_init(&env); + + xmlrpc_value* param = xmlrpc_build_value(&env, "(ss)", login, passwd); + throw_if_xml_fault_occurred(&env); + + xmlrpc_value* result; + xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "Catcut.auth", param, &result); + xmlrpc_DECREF(param); + throw_if_xml_fault_occurred(&env); + + xmlrpc_value *cookie_xml; + const char *cookie; + string cookie_str; + xmlrpc_struct_find_value(&env, result, "cookie", &cookie_xml); + throw_if_xml_fault_occurred(&env); + xmlrpc_read_string(&env, cookie_xml, &cookie); + throw_if_xml_fault_occurred(&env); + cookie_str = cookie; + /* xmlrpc_read_string returns *malloc'ed ptr*. + * doc is not very clear on it, but I looked in xmlrpc sources. */ + free((void*)cookie); + xmlrpc_DECREF(cookie_xml); + + xmlrpc_DECREF(result); + + return cookie_str; } -static string new_bug(const char *auth_cookie, const map_crash_report_t& pCrashReport) +string +ctx::new_bug(const char *auth_cookie, const map_crash_report_t& pCrashReport) { + xmlrpc_env env; + xmlrpc_env_init(&env); + string package = pCrashReport.find(FILENAME_PACKAGE)->second[CD_CONTENT]; string component = pCrashReport.find(FILENAME_COMPONENT)->second[CD_CONTENT]; string release = pCrashReport.find(FILENAME_RELEASE)->second[CD_CONTENT]; @@ -216,7 +329,7 @@ static string new_bug(const char *auth_cookie, const map_crash_report_t& pCrashR string product; string version; - get_product_and_version(release, product, version); + parse_release(release.c_str(), product, version); xmlrpc_value *param = xmlrpc_build_value(&env, "(s{s:s,s:s,s:s,s:s,s:s,s:s,s:s})", auth_cookie, @@ -228,23 +341,23 @@ static string new_bug(const char *auth_cookie, const map_crash_report_t& pCrashR "status_whiteboard", status_whiteboard.c_str(), "platform", arch.c_str() ); - throw_if_xml_fault_occurred(); + throw_if_xml_fault_occurred(&env); xmlrpc_value *result; - xmlrpc_client_call2(&env, client, server_info, "Catcut.createTicket", param, &result); - throw_if_xml_fault_occurred(); + xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "Catcut.createTicket", param, &result); xmlrpc_DECREF(param); + throw_if_xml_fault_occurred(&env); xmlrpc_value *bug_id_xml; const char *bug_id; string bug_id_str; xmlrpc_struct_find_value(&env, result, "ticket", &bug_id_xml); - throw_if_xml_fault_occurred(); + throw_if_xml_fault_occurred(&env); xmlrpc_read_string(&env, bug_id_xml, &bug_id); - throw_if_xml_fault_occurred(); + throw_if_xml_fault_occurred(&env); bug_id_str = bug_id; log("New bug id: %s", bug_id); - update_client(_("New bug id: ") + bug_id_str); + update_client(_("New bug id: %s"), bug_id); free((void*)bug_id); xmlrpc_DECREF(bug_id_xml); @@ -253,81 +366,177 @@ static string new_bug(const char *auth_cookie, const map_crash_report_t& pCrashR return bug_id_str; } -//static -//void add_attachments(const string& pBugId, const map_crash_report_t& pCrashReport) -//{ -// xmlrpc_value* result = NULL; -// -// map_crash_report_t::const_iterator it = pCrashReport.begin(); -// for (; it != pCrashReport.end(); it++) -// { -// if (it->second[CD_TYPE] == CD_ATT) -// { -// string description = "File: " + it->first; -// const string& to_encode = it->second[CD_CONTENT]; -// char *encoded64 = encode_base64(to_encode.c_str(), to_encode.length()); -// xmlrpc_value* param = xmlrpc_build_value(&env,"(s{s:s,s:s,s:s,s:s})", -// pBugId.c_str(), -// "description", description.c_str(), -// "filename", it->first.c_str(), -// "contenttype", "text/plain", -// "data", encoded64 -// ); -// free(encoded64); -// throw_if_xml_fault_occurred(); -// -//// catcut has this API: -//// struct response requestUpload(string cookie, string ticket, string filename, string description) -////response MUST include "errno", "errmsg" members; if an upload is approved, -////a "URL" MUST be returned in the response. The description string -////should include a brief description of the file. -//// -////The client should upload the file via HTTP PUT to the provided -////URL. The provided URL may be absolute or relative, if relative it must -////be combined with the base URL of the XML-RPC server using the usual -////rules for relative URL's (RFC 3986). -// xmlrpc_client_call2(&env, client, server_info, "catcut.addAttachment", param, &result); -// throw_if_xml_fault_occurred(); -// } -// } -//} +string +ctx::request_upload(const char* auth_cookie, const char* pTicketName, + const char* fileName, const char* description) +{ + xmlrpc_env env; + xmlrpc_env_init(&env); + + xmlrpc_value* param = xmlrpc_build_value(&env, "(ssss)", + auth_cookie, + pTicketName, + fileName, + description); + throw_if_xml_fault_occurred(&env); + + xmlrpc_value* result = NULL; + xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "Catcut.requestUpload", param, &result); + xmlrpc_DECREF(param); + throw_if_xml_fault_occurred(&env); + + string URL; + bool has_URL = struct_find_string(&env, result, "uri", URL); + if (!has_URL || URL == "") + { + int err; + bool has_errno = struct_find_int(&env, result, "errno", err); + if (has_errno && err) + { + string errmsg; + bool has_errmsg = struct_find_string(&env, result, "errmsg", errmsg); + if (has_errmsg) + { + log("error returned by requestUpload: %s", errmsg.c_str()); + update_client(_("error returned by requestUpload: %s"), errmsg.c_str()); + } + else + { + log("error returned by requestUpload: %d", err); + update_client(_("error returned by requestUpload: %d"), err); + } + } + else + { + log("no URL returned by requestUpload, and no err"); + update_client(_("no URL returned by requestUpload, and no errno")); + } + } + + log("requestUpload returned URL: %s", URL.c_str()); + update_client(_("requestUpload returned URL: %s"), URL.c_str()); + + xmlrpc_DECREF(result); + return URL; +} + +void +ctx::add_attachments(const char* xmlrpc_URL, + const char* auth_cookie, + const char* pTicketName, + const map_crash_report_t& pCrashReport, + int retryCount, + int retryDelaySeconds) +{ + + map_crash_report_t::const_iterator it = pCrashReport.begin(); + for (; it != pCrashReport.end(); it++) + { + if (it->second[CD_TYPE] == CD_ATT) + { + update_client(_("Attaching (CD_ATT): %s"), it->first.c_str()); + + string description = "File: " + it->first; + string URL = request_upload(auth_cookie, + pTicketName, + it->first.c_str(), + description.c_str()); + + URL = resolve_relative_url(URL.c_str(), xmlrpc_URL); + + log("rebased URL: %s", URL.c_str()); + update_client(_("rebased URL: %s"), URL.c_str()); + + send_string(URL.c_str(), it->second[CD_CONTENT].c_str(), + retryCount, retryDelaySeconds); + } + else if (it->second[CD_TYPE] == CD_BIN) + { + update_client(_("Attaching (CD_ATT): %s"), it->first.c_str()); + + string description = "File: " + it->first; + string URL = request_upload(auth_cookie, + pTicketName, + it->first.c_str(), + description.c_str()); + + URL = resolve_relative_url(URL.c_str(), xmlrpc_URL); + + log("rebased URL: %s", URL.c_str()); + update_client(_("rebased URL: %s"), URL.c_str()); + + send_file(URL.c_str(), it->second[CD_CONTENT].c_str(), + retryCount, retryDelaySeconds); + } + } +} + +} /* namespace */ + + +/* + * CReporterCatcut + */ CReporterCatcut::CReporterCatcut() : m_sCatcutURL("http://127.0.0.1:8080/catcut/xmlrpc"), - m_bNoSSLVerify(false) + m_bNoSSLVerify(false), + m_nRetryCount(3), + m_nRetryDelay(20) {} CReporterCatcut::~CReporterCatcut() {} string CReporterCatcut::Report(const map_crash_report_t& pCrashReport, - const map_plugin_settings_t& pSettings, const string& pArgs) + const map_plugin_settings_t& pSettings, + const string& pArgs) { update_client(_("Creating new bug...")); try { - new_xmlrpc_client(m_sCatcutURL.c_str(), m_bNoSSLVerify); - string auth_cookie = login(m_sLogin.c_str(), m_sPassword.c_str()); - string bug_id = (auth_cookie != "") ? new_bug(auth_cookie.c_str(), pCrashReport) : ""; -// add_attachments(to_string(bug_id), pCrashReport); -// update_client(_("Logging out...")); -// logout(); - destroy_xmlrpc_client(); - return "New catcut bug ID: " + bug_id; + ctx catcut_server(m_sCatcutURL.c_str(), m_bNoSSLVerify); + string auth_cookie = catcut_server.login(m_sLogin.c_str(), m_sPassword.c_str()); + string message; + if (auth_cookie != "") + { + string ticket_name = catcut_server.new_bug(auth_cookie.c_str(), pCrashReport); + if (ticket_name != "") + { + catcut_server.add_attachments( + m_sCatcutURL.c_str(), + auth_cookie.c_str(), + ticket_name.c_str(), + pCrashReport, + m_nRetryCount, + m_nRetryDelay + ); + message = "New catcut bug ID: " + ticket_name; + } + else + { + message = "Error could not create ticket"; + } + } + else + { + message = "Error could not create ticket"; + } + return message; } catch (CABRTException& e) { - destroy_xmlrpc_client(); - throw CABRTException(EXCEP_PLUGIN, string("CReporterCatcut::Report(): ") + e.what()); + throw CABRTException(EXCEP_PLUGIN, e.what()); } } void CReporterCatcut::SetSettings(const map_plugin_settings_t& pSettings) { - map_plugin_settings_t::const_iterator it; - map_plugin_settings_t::const_iterator end = pSettings.end(); + m_pSettings = pSettings; + map_plugin_settings_t::const_iterator end = pSettings.end(); + map_plugin_settings_t::const_iterator it; it = pSettings.find("CatcutURL"); if (it != end) { @@ -346,20 +555,18 @@ void CReporterCatcut::SetSettings(const map_plugin_settings_t& pSettings) it = pSettings.find("NoSSLVerify"); if (it != end) { - m_bNoSSLVerify = it->second == "yes"; + m_bNoSSLVerify = string_to_bool(it->second.c_str()); + } + it = pSettings.find("RetryCount"); + if (it != end) + { + m_nRetryCount = atoi(it->second.c_str()); + } + it = pSettings.find("RetryDelay"); + if (it != end) + { + m_nRetryDelay = atoi(it->second.c_str()); } -} - -map_plugin_settings_t CReporterCatcut::GetSettings() -{ - map_plugin_settings_t ret; - - ret["CatcutURL"] = m_sCatcutURL; - ret["Login"] = m_sLogin; - ret["Password"] = m_sPassword; - ret["NoSSLVerify"] = m_bNoSSLVerify ? "yes" : "no"; - - return ret; } PLUGIN_INFO(REPORTER, diff --git a/lib/Plugins/Catcut.h b/lib/Plugins/Catcut.h index 40ef399d..4fb89e22 100644 --- a/lib/Plugins/Catcut.h +++ b/lib/Plugins/Catcut.h @@ -11,13 +11,14 @@ class CReporterCatcut : public CReporter std::string m_sLogin; std::string m_sPassword; bool m_bNoSSLVerify; + int m_nRetryCount; + int m_nRetryDelay; public: CReporterCatcut(); virtual ~CReporterCatcut(); virtual void SetSettings(const map_plugin_settings_t& pSettings); - virtual map_plugin_settings_t GetSettings(); virtual std::string Report(const map_crash_report_t& pCrashReport, const map_plugin_settings_t& pSettings, diff --git a/lib/Plugins/FileTransfer.cpp b/lib/Plugins/FileTransfer.cpp index 66427585..868f54dd 100644 --- a/lib/Plugins/FileTransfer.cpp +++ b/lib/Plugins/FileTransfer.cpp @@ -42,8 +42,8 @@ #include "ABRTException.h" #include "CommLayerInner.h" - using namespace std; + #define HBLEN 255 #define FILETRANSFER_DIRLIST DEBUG_DUMPS_DIR "/FileTransferDirlist.txt" @@ -55,74 +55,51 @@ CFileTransfer::CFileTransfer() { } -void CFileTransfer::SendFile(const std::string& pURL, - const std::string& pFilename) +void CFileTransfer::SendFile(const char *pURL, const char *pFilename) { - if (pURL == "") + int len = strlen(pURL); + if (len == 0) { - warn_client(_("FileTransfer: URL not specified")); + error_msg(_("FileTransfer: URL not specified")); return; } - int len = pURL.length(); - int i = 0; - std::string protocol; - while (pURL[i] != ':') - { - protocol += pURL[i]; - i++; - if (i == len) - { - throw CABRTException(EXCEP_PLUGIN, "CFileTransfer::SendFile(): malformed URL, does not contain protocol"); - } - } + update_client(_("Sending archive %s to %s"), pFilename, pURL); - std::string msg = ssprintf(_("Sending archive %s via %s"), pFilename.c_str(), protocol.c_str()); - update_client(msg.c_str()); - - std::string wholeURL; - if (pURL[len-1] == '/') - { - wholeURL = pURL + pFilename; - } - else - { - wholeURL = pURL + "/" + pFilename; - } + string wholeURL = concat_path_file(pURL, pFilename); int result; int count = m_nRetryCount; do { - FILE * f; + FILE *f; struct stat buf; - CURL * curl; + CURL *curl; - f = fopen(pFilename.c_str(), "r"); + f = fopen(pFilename, "r"); if (!f) { - throw CABRTException(EXCEP_PLUGIN, "CFileTransfer::SendFile(): cannot open archive file "+pFilename); + throw CABRTException(EXCEP_PLUGIN, ssprintf("Can't open archive file '%s'", pFilename)); } if (fstat(fileno(f), &buf) == -1) { - throw CABRTException(EXCEP_PLUGIN, "CFileTransfer::SendFile(): cannot stat archive file "+pFilename); + fclose(f); + throw CABRTException(EXCEP_PLUGIN, ssprintf("Can't stat archive file '%s'", pFilename)); } curl = curl_easy_init(); if (!curl) { - throw CABRTException(EXCEP_PLUGIN, "CFileTransfer::SendFile(): Curl library error."); + throw CABRTException(EXCEP_PLUGIN, "Curl library init error"); } /* enable uploading */ curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); /* specify target */ curl_easy_setopt(curl, CURLOPT_URL, wholeURL.c_str()); - /*file handle: passed to the default callback, it will fread() it*/ + /* FILE handle: passed to the default callback, it will fread() it */ curl_easy_setopt(curl, CURLOPT_READDATA, f); - /*get file size*/ curl_easy_setopt(curl, CURLOPT_INFILESIZE, buf.st_size); - /*everything is done here; result 0 means success*/ + /* everything is done here; result 0 means success */ result = curl_easy_perform(curl); - /*goodbye*/ curl_easy_cleanup(curl); fclose(f); } @@ -285,84 +262,81 @@ static void create_tarbz2(const char * archive_name, const char * directory) free(name_without_bz2); } -void CFileTransfer::CreateArchive(const std::string& pArchiveName, - const std::string& pDir) +void CFileTransfer::CreateArchive(const char *pArchiveName, const char *pDir) { if (m_sArchiveType == ".tar") { - create_tar(pArchiveName.c_str(), pDir.c_str()); + create_tar(pArchiveName, pDir); } else if (m_sArchiveType == ".tar.gz") { - create_targz(pArchiveName.c_str(), pDir.c_str()); + create_targz(pArchiveName, pDir); } else if (m_sArchiveType == ".tar.bz2") { - create_tarbz2(pArchiveName.c_str(), pDir.c_str()); + create_tarbz2(pArchiveName, pDir); } else if (m_sArchiveType == ".zip") { - create_zip(pArchiveName.c_str(), pDir.c_str()); + create_zip(pArchiveName, pDir); } else { - throw CABRTException(EXCEP_PLUGIN, "CFileTransfer::CreateArchive(): unknown/unsupported archive type "+m_sArchiveType); + throw CABRTException(EXCEP_PLUGIN, "Unknown/unsupported archive type " + m_sArchiveType); } } -/*returns the last component of the directory path*/ -static std::string DirBase(const std::string& pStr) +/* Returns the last component of the directory path. + * Careful to not return "" on "/path/path2/", but "path2". + */ +static string DirBase(const char *pStr) { - int i = pStr.length() - 1; - if (i > 0 && pStr[i] == '/') + int end = strlen(pStr); + if (end > 1 && pStr[end-1] == '/') { - i--; + end--; } - std::string result; - for (; i >= 0 && pStr[i] != '/'; i--) + int beg = end; + while (beg > 0 && pStr[beg-1] != '/') { - result = pStr[i] + result; + beg--; } - return result; + return string(pStr + beg, end - beg); } -void CFileTransfer::Run(const std::string& pActiveDir, const std::string& pArgs) +void CFileTransfer::Run(const char *pActionDir, const char *pArgs) { - fstream dirlist; - std::string dirname, archivename; - char hostname[HBLEN]; - update_client(_("File Transfer: Creating a report...")); - if (pArgs == "store") + char hostname[HBLEN]; + gethostname(hostname, HBLEN-1); + hostname[HBLEN-1] = '\0'; + + fstream dirlist; + if (strcmp(pArgs, "store") == 0) { /* store pActiveDir for later sending */ - dirlist.open(FILETRANSFER_DIRLIST, fstream::out | fstream::app ); - dirlist << pActiveDir << endl; + dirlist.open(FILETRANSFER_DIRLIST, fstream::out | fstream::app); + dirlist << pActionDir << endl; dirlist.close(); } - else if (pArgs == "one") + else if (strcmp(pArgs, "one") == 0) { /* just send one archive */ - gethostname(hostname, HBLEN); - archivename = std::string(hostname) + "-" - + DirBase(pActiveDir) + m_sArchiveType; + string archivename = ssprintf("%s-%s%s", hostname, DirBase(pActionDir).c_str(), m_sArchiveType.c_str()); try { - CreateArchive(archivename, pActiveDir); - SendFile(m_sURL, archivename); + CreateArchive(archivename.c_str(), pActionDir); + SendFile(m_sURL.c_str(), archivename.c_str()); } catch (CABRTException& e) { - warn_client(_("CFileTransfer::Run(): Cannot create and send an archive: ") + e.what()); - //update_client("CFileTransfer::Run(): Cannot create and send an archive: " + e.what()); + error_msg(_("Can't create and send an archive: %s"), e.what()); } unlink(archivename.c_str()); } else { - gethostname(hostname, HBLEN); - dirlist.open(FILETRANSFER_DIRLIST, fstream::in); if (dirlist.fail()) { @@ -371,19 +345,18 @@ void CFileTransfer::Run(const std::string& pActiveDir, const std::string& pArgs) return; } + string dirname; while (getline(dirlist, dirname), dirlist.good()) { - archivename = std::string(hostname) + "-" - + DirBase(dirname) + m_sArchiveType; + string archivename = ssprintf("%s-%s%s", hostname, DirBase(dirname.c_str()).c_str(), m_sArchiveType.c_str()); try { - CreateArchive(archivename, dirname); - SendFile(m_sURL, archivename); + CreateArchive(archivename.c_str(), dirname.c_str()); + SendFile(m_sURL.c_str(), archivename.c_str()); } catch (CABRTException& e) { - warn_client(_("CFileTransfer::Run(): Cannot create and send an archive: ") + e.what()); -// update_client("CFileTransfer::Run(): Cannot create and send an archive: " + e.what()); + error_msg(_("Can't create and send an archive %s"), e.what()); } unlink(archivename.c_str()); } @@ -397,15 +370,18 @@ void CFileTransfer::Run(const std::string& pActiveDir, const std::string& pArgs) void CFileTransfer::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 = pSettings.find("URL"); + map_plugin_settings_t::const_iterator it; + it = pSettings.find("URL"); if (it != end) { m_sURL = it->second; } else { - warn_client(_("FileTransfer: URL not specified")); + error_msg(_("FileTransfer: URL not specified")); } it = pSettings.find("RetryCount"); @@ -427,25 +403,21 @@ void CFileTransfer::SetSettings(const map_plugin_settings_t& pSettings) m_sArchiveType = it->second; if (m_sArchiveType[0] != '.') { - m_sArchiveType = "." + m_sArchiveType; + m_sArchiveType = "." + m_sArchiveType; } } } -map_plugin_settings_t CFileTransfer::GetSettings() -{ - map_plugin_settings_t ret; - std::stringstream ss; - ret["URL"] = m_sURL; - ss << m_nRetryCount; - ret["RetryCount"] = ss.str(); - ss.str(""); - ss << m_nRetryDelay; - ret["RetryDelay"] = ss.str(); - ret["ArchiveType"] = m_sArchiveType; - - return ret; -} +//ok to delete? +//const map_plugin_settings_t& CFileTransfer::GetSettings() +//{ +// m_pSettings["URL"] = m_sURL; +// m_pSettings["RetryCount"] = to_string(m_nRetryCount); +// m_pSettings["RetryDelay"] = to_string(m_nRetryDelay); +// m_pSettings["ArchiveType"] = m_sArchiveType; +// +// return m_pSettings; +//} PLUGIN_INFO(ACTION, CFileTransfer, diff --git a/lib/Plugins/FileTransfer.h b/lib/Plugins/FileTransfer.h index 2f230c65..91207f49 100644 --- a/lib/Plugins/FileTransfer.h +++ b/lib/Plugins/FileTransfer.h @@ -35,18 +35,15 @@ class CFileTransfer : public CAction int m_nRetryCount; int m_nRetryDelay; - void CreateArchive(const std::string& pArchiveName, - const std::string& pDir); - - void SendFile(const std::string& pURL, - const std::string& pFilename); + void CreateArchive(const char *pArchiveName, const char *pDir); + void SendFile(const char *pURL, const char *pFilename); public: CFileTransfer(); virtual void SetSettings(const map_plugin_settings_t& pSettings); - virtual map_plugin_settings_t GetSettings(); - virtual void Run(const std::string& pActiveDir, - const std::string& pArgs); +//ok to delete? +// virtual const map_plugin_settings_t& GetSettings(); + virtual void Run(const char *pActionDir, const char *pArgs); }; #endif /* FILETRANSFER_H_ */ diff --git a/lib/Plugins/Kerneloops.conf b/lib/Plugins/Kerneloops.conf new file mode 100644 index 00000000..47b242ff --- /dev/null +++ b/lib/Plugins/Kerneloops.conf @@ -0,0 +1,2 @@ +# compatibility with kerneloops.org tool +InformAllUsers = yes diff --git a/lib/Plugins/Kerneloops.cpp b/lib/Plugins/Kerneloops.cpp index e01bb426..b99183c3 100644 --- a/lib/Plugins/Kerneloops.cpp +++ b/lib/Plugins/Kerneloops.cpp @@ -32,7 +32,7 @@ #define FILENAME_KERNELOOPS "kerneloops" -std::string CAnalyzerKerneloops::GetLocalUUID(const std::string& pDebugDumpDir) +std::string CAnalyzerKerneloops::GetLocalUUID(const char *pDebugDumpDir) { log(_("Getting local universal unique identification")); @@ -58,7 +58,7 @@ std::string CAnalyzerKerneloops::GetLocalUUID(const std::string& pDebugDumpDir) return to_string(hash); } -std::string CAnalyzerKerneloops::GetGlobalUUID(const std::string& pDebugDumpDir) +std::string CAnalyzerKerneloops::GetGlobalUUID(const char *pDebugDumpDir) { return GetLocalUUID(pDebugDumpDir); } diff --git a/lib/Plugins/Kerneloops.h b/lib/Plugins/Kerneloops.h index edd00d8b..9e2010c7 100644 --- a/lib/Plugins/Kerneloops.h +++ b/lib/Plugins/Kerneloops.h @@ -34,9 +34,9 @@ class CAnalyzerKerneloops : public CAnalyzer { public: - virtual std::string GetLocalUUID(const std::string& pDebugDumpDir); - virtual std::string GetGlobalUUID(const std::string& pDebugDumpDir); - virtual void CreateReport(const std::string& pDebugDumpDir, int force) {} + virtual std::string GetLocalUUID(const char *pDebugDumpDir); + virtual std::string GetGlobalUUID(const char *pDebugDumpDir); + virtual void CreateReport(const char *pDebugDumpDir, int force) {} }; #endif diff --git a/lib/Plugins/KerneloopsReporter.cpp b/lib/Plugins/KerneloopsReporter.cpp index c57a1ef8..f7a6cbb8 100644 --- a/lib/Plugins/KerneloopsReporter.cpp +++ b/lib/Plugins/KerneloopsReporter.cpp @@ -98,12 +98,10 @@ std::string CKerneloopsReporter::Report(const map_crash_report_t& pCrashReport, const std::string& pArgs) { int ret = -1; - map_crash_report_t::const_iterator it; update_client(_("Creating and submitting a report...")); - it = pCrashReport.begin(); - it = pCrashReport.find(FILENAME_KERNELOOPS); + map_crash_report_t::const_iterator it = pCrashReport.find(FILENAME_KERNELOOPS); if (it != pCrashReport.end()) { ret = http_post_to_kerneloops_site( m_sSubmitURL.c_str(), @@ -111,30 +109,32 @@ std::string CKerneloopsReporter::Report(const map_crash_report_t& pCrashReport, ); } - if (ret) - { + if (ret) { /* FIXME: be more informative */ - throw CABRTException(EXCEP_PLUGIN, std::string("CKerneloopsReporter::Report(): Report has not been sent...")); + throw CABRTException(EXCEP_PLUGIN, std::string("CKerneloopsReporter::Report(): Report has not been sent...")); } return "Kernel oops report was uploaded to: " + m_sSubmitURL; } void CKerneloopsReporter::SetSettings(const map_plugin_settings_t& pSettings) { - if (pSettings.find("SubmitURL") != pSettings.end()) - { - m_sSubmitURL = pSettings.find("SubmitURL")->second; + m_pSettings = pSettings; + + map_plugin_settings_t::const_iterator end = pSettings.end(); + map_plugin_settings_t::const_iterator it; + it = pSettings.find("SubmitURL"); + if (it != end) { + m_sSubmitURL = it->second; } } -map_plugin_settings_t CKerneloopsReporter::GetSettings() -{ - map_plugin_settings_t ret; - - ret["SubmitURL"] = m_sSubmitURL; - - return ret; -} +//ok to delete? +//const map_plugin_settings_t& CKerneloopsReporter::GetSettings() +//{ +// m_pSettings["SubmitURL"] = m_sSubmitURL; +// +// return m_pSettings; +//} PLUGIN_INFO(REPORTER, CKerneloopsReporter, diff --git a/lib/Plugins/KerneloopsReporter.h b/lib/Plugins/KerneloopsReporter.h index 3c165920..af82afbe 100644 --- a/lib/Plugins/KerneloopsReporter.h +++ b/lib/Plugins/KerneloopsReporter.h @@ -41,7 +41,8 @@ class CKerneloopsReporter : public CReporter CKerneloopsReporter(); virtual void SetSettings(const map_plugin_settings_t& pSettings); - virtual map_plugin_settings_t GetSettings(); +//ok to delete? +// virtual const map_plugin_settings_t& GetSettings(); virtual std::string Report(const map_crash_report_t& pCrashReport, const map_plugin_settings_t& pSettings, const std::string& pArgs); diff --git a/lib/Plugins/KerneloopsScanner.cpp b/lib/Plugins/KerneloopsScanner.cpp index 9e1bd535..8c8cd4b9 100644 --- a/lib/Plugins/KerneloopsScanner.cpp +++ b/lib/Plugins/KerneloopsScanner.cpp @@ -43,7 +43,6 @@ CKerneloopsScanner::CKerneloopsScanner() { int cnt_FoundOopses; - m_sSysLogFile = "/var/log/messages"; /* Scan dmesg, on first call only */ cnt_FoundOopses = ScanDmesg(); @@ -51,19 +50,23 @@ CKerneloopsScanner::CKerneloopsScanner() SaveOopsToDebugDump(); } -void CKerneloopsScanner::Run(const std::string& pActionDir, - const std::string& pArgs) +void CKerneloopsScanner::Run(const char *pActionDir, const char *pArgs) { - int cnt_FoundOopses; + const char *syslog_file = "/var/log/messages"; + map_plugin_settings_t::const_iterator it = m_pSettings.find("SysLogFile"); + if (it != m_pSettings.end()) + { + syslog_file = it->second.c_str(); + } - cnt_FoundOopses = ScanSysLogFile(m_sSysLogFile.c_str()); + int cnt_FoundOopses = ScanSysLogFile(syslog_file); if (cnt_FoundOopses > 0) { SaveOopsToDebugDump(); /* * This marker in syslog file prevents us from * re-parsing old oopses (any oops before it is * ignored by ScanSysLogFile()). The only problem - * is that we can't be sure here that m_sSysLogFile + * is that we can't be sure here that syslog_file * is the file where syslog(xxx) stuff ends up. */ openlog("abrt", 0, LOG_KERN); @@ -97,8 +100,7 @@ void CKerneloopsScanner::SaveOopsToDebugDump() try { CDebugDump debugDump; - // UID of kerneloops is -1 - debugDump.Create(path, -1); + debugDump.Create(path, 0); debugDump.SaveText(FILENAME_ANALYZER, "Kerneloops"); debugDump.SaveText(FILENAME_EXECUTABLE, "kernel"); debugDump.SaveText(FILENAME_KERNEL, first_line); @@ -178,24 +180,6 @@ int CKerneloopsScanner::ScanSysLogFile(const char *filename) return cnt_FoundOopses; } -void CKerneloopsScanner::SetSettings(const map_plugin_settings_t& pSettings) -{ - map_plugin_settings_t::const_iterator it = pSettings.find("SysLogFile"); - if (it != pSettings.end()) - { - m_sSysLogFile = it->second; - } -} - -map_plugin_settings_t CKerneloopsScanner::GetSettings() -{ - map_plugin_settings_t ret; - - ret["SysLogFile"] = m_sSysLogFile; - - return ret; -} - PLUGIN_INFO(ACTION, CKerneloopsScanner, "KerneloopsScanner", diff --git a/lib/Plugins/KerneloopsScanner.h b/lib/Plugins/KerneloopsScanner.h index 6ac0461f..9f00df21 100644 --- a/lib/Plugins/KerneloopsScanner.h +++ b/lib/Plugins/KerneloopsScanner.h @@ -33,9 +33,6 @@ class CKerneloopsScanner : public CAction { - private: - std::string m_sSysLogFile; - /* For "dumpoops" tool */ public: vector_string_t m_pOopsList; @@ -49,10 +46,7 @@ class CKerneloopsScanner : public CAction /* Plugin interface */ public: CKerneloopsScanner(); - virtual void Run(const std::string& pActionDir, - const std::string& pArgs); - virtual void SetSettings(const map_plugin_settings_t& pSettings); - virtual map_plugin_settings_t GetSettings(); + virtual void Run(const char *pActionDir, const char *pArgs); }; #endif diff --git a/lib/Plugins/KerneloopsSysLog.cpp b/lib/Plugins/KerneloopsSysLog.cpp index d28ce399..cb15fccb 100644 --- a/lib/Plugins/KerneloopsSysLog.cpp +++ b/lib/Plugins/KerneloopsSysLog.cpp @@ -75,7 +75,6 @@ struct line_info { int extract_oopses(vector_string_t &oopses, char *buffer, size_t buflen) { char *c; - enum { maybe, no, yes } syslog_format = maybe; int linecount = 0; int lines_info_alloc = 0; struct line_info *lines_info = NULL; @@ -86,86 +85,73 @@ int extract_oopses(vector_string_t &oopses, char *buffer, size_t buflen) buffer[buflen - 1] = '\n'; /* the buffer usually ends with \n, but let's make sure */ c = buffer; while (c < buffer + buflen) { - char v, linelevel; - int len = 0; + char linelevel; char *c9; char *linepointer; c9 = (char*)memchr(c, '\n', buffer + buflen - c); /* a \n will always be found */ assert(c9); - len = c9 - c; + *c9 = '\0'; /* turn the \n into a string termination */ + if (c9 == c) + goto next_line; /* in /var/log/messages, we need to strip the first part off, upto the 3rd ':' */ - if (syslog_format == yes - || (syslog_format == maybe - && len > sizeof("Jul 4 11:11:41") - && c[3] == ' ' && c[6] == ' ' && c[9] == ':' && c[12] == ':' - && (v = (c[5] | c[7]|c[8] | c[10]|c[11] | c[13]|c[14])) <= '9' - && v >= '0' - && (v = (c[5] & c[7]&c[8] & c[10]&c[11] & c[13]&c[14])) <= '9' - && v >= '0' - ) + /* 01234567890123456 */ + if ((c9 - c) > sizeof("Jul 4 11:11:11 ") + && c[3] == ' ' + && (c[4] == ' ' || isdigit(c[4])) + && isdigit(c[5]) + && c[6] == ' ' + && isdigit(c[7]) + && isdigit(c[8]) + && c[9] == ':' + && isdigit(c[10]) + && isdigit(c[11]) + && c[12] == ':' + && isdigit(c[13]) + && isdigit(c[14]) + && c[15] == ' ' ) { /* It's syslog file, not a bare dmesg */ - syslog_format = yes; - - char *c2; - int i; - /* skip non-kernel lines */ - c2 = (char*)memmem(c, len, "kernel:", 7); - if (!c2) - c2 = (char*)memmem(c, len, "abrt:", 5); - if (!c2) + /* Skip over timestamp */ + c += 16; + + /* Skip non-kernel lines */ + char *kernel_str = strstr(c, "kernel: "); + if (kernel_str == NULL) { + /* if we see our own marker: + * "hostname abrt: Kerneloops: Reported 1 kernel oopses to Abrt" + * we know we submitted everything upto here already */ + if (strstr(c, "abrt:") && strstr(c, "Abrt")) { + linecount = 0; + lines_info_alloc = 0; + free(lines_info); + lines_info = NULL; + } goto next_line; - - /* skip to message in "Jan 01 01:23:45 hostname kernel: message" */ - for (i = 0; i < 3; i++) { - c = (char*)memchr(c, ':', len); - if (!c) - goto next_line; - c++; - len = c9 - c; } - c++; - len--; - } else if (len) { - syslog_format = no; + c = kernel_str + sizeof("kernel: ")-1; } - linepointer = c; linelevel = 0; /* store and remove kernel log level */ - if (len >= 3 && *c == '<' && *(c+2) == '>') { - linelevel = *(c+1); + if (*c == '<' && c[1] && c[2] == '>') { + linelevel = c[1]; c += 3; - len -= 3; - linepointer = c; } /* remove jiffies time stamp counter if present */ if (*c == '[') { char *c2, *c3; - c2 = (char*)memchr(c, '.', len); - c3 = (char*)memchr(c, ']', len); + c2 = strchr(c, '.'); + c3 = strchr(c, ']'); if (c2 && c3 && (c2 < c3) && (c3-c) < 14 && (c2-c) < 8) { c = c3 + 1; if (*c == ' ') c++; - len = c9 - c; - linepointer = c; } } - - assert(c + len == c9); - *c9 = '\0'; /* turn the \n into a string termination */ - - /* if we see our own marker, we know we submitted everything upto here already */ - if (len >= 4 && memmem(linepointer, len, "Abrt", 4)) { - linecount = 0; - lines_info_alloc = 0; - free(lines_info); - lines_info = NULL; - } + linepointer = c; if (linecount >= lines_info_alloc) { lines_info_alloc += REALLOC_CHUNK; diff --git a/lib/Plugins/Logger.cpp b/lib/Plugins/Logger.cpp index 716d3a92..6babc732 100644 --- a/lib/Plugins/Logger.cpp +++ b/lib/Plugins/Logger.cpp @@ -19,9 +19,10 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "Logger.h" #include <fstream> #include <sstream> +#include "abrtlib.h" +#include "Logger.h" #include "DebugDump.h" #include "CommLayerInner.h" #include "ABRTException.h" @@ -33,25 +34,30 @@ CLogger::CLogger() : void CLogger::SetSettings(const map_plugin_settings_t& pSettings) { - if (pSettings.find("LogPath") != pSettings.end()) + m_pSettings = pSettings; + + map_plugin_settings_t::const_iterator end = pSettings.end(); + map_plugin_settings_t::const_iterator it; + it = pSettings.find("LogPath"); + if (it != end) { - m_sLogPath = pSettings.find("LogPath")->second; + m_sLogPath = it->second; } - if (pSettings.find("AppendLogs") != pSettings.end()) + it = pSettings.find("AppendLogs"); + if (it != end) { - m_bAppendLogs = pSettings.find("AppendLogs")->second == "yes"; + m_bAppendLogs = string_to_bool(it->second.c_str()); } } -map_plugin_settings_t CLogger::GetSettings() -{ - map_plugin_settings_t ret; - - ret["LogPath"] = m_sLogPath; - ret["AppendLogs"] = m_bAppendLogs ? "yes" : "no"; - - return ret; -} +//ok to delete? +//const map_plugin_settings_t& CLogger::GetSettings() +//{ +// m_pSettings["LogPath"] = m_sLogPath; +// m_pSettings["AppendLogs"] = m_bAppendLogs ? "yes" : "no"; +// +// return m_pSettings; +//} std::string CLogger::Report(const map_crash_report_t& pCrashReport, const map_plugin_settings_t& pSettings, const std::string& pArgs) diff --git a/lib/Plugins/Logger.h b/lib/Plugins/Logger.h index 33f957db..285e25ba 100644 --- a/lib/Plugins/Logger.h +++ b/lib/Plugins/Logger.h @@ -35,7 +35,8 @@ class CLogger : public CReporter CLogger(); virtual void SetSettings(const map_plugin_settings_t& pSettings); - virtual map_plugin_settings_t GetSettings(); +//ok to delete? +// virtual const map_plugin_settings_t& GetSettings(); virtual std::string Report(const map_crash_report_t& pCrashReport, const map_plugin_settings_t& pSettings, const std::string& pArgs); diff --git a/lib/Plugins/Mailx.cpp b/lib/Plugins/Mailx.cpp index ef3a8d2a..1979f9e8 100644 --- a/lib/Plugins/Mailx.cpp +++ b/lib/Plugins/Mailx.cpp @@ -201,35 +201,42 @@ std::string CMailx::Report(const map_crash_report_t& pCrashReport, void CMailx::SetSettings(const map_plugin_settings_t& pSettings) { - if (pSettings.find("Subject") != pSettings.end()) + m_pSettings = pSettings; + + map_plugin_settings_t::const_iterator end = pSettings.end(); + map_plugin_settings_t::const_iterator it; + it = pSettings.find("Subject"); + if (it != end) { - m_sSubject = pSettings.find("Subject")->second; + m_sSubject = it->second; } - if (pSettings.find("EmailFrom") != pSettings.end()) + it = pSettings.find("EmailFrom"); + if (it != end) { - m_sEmailFrom = pSettings.find("EmailFrom")->second; + m_sEmailFrom = it->second; } - if (pSettings.find("EmailTo") != pSettings.end()) + it = pSettings.find("EmailTo"); + if (it != end) { - m_sEmailTo = pSettings.find("EmailTo")->second; + m_sEmailTo = it->second; } - if (pSettings.find("SendBinaryData") != pSettings.end()) + it = pSettings.find("SendBinaryData"); + if (it != end) { - m_bSendBinaryData = pSettings.find("SendBinaryData")->second == "yes"; + m_bSendBinaryData = string_to_bool(it->second.c_str()); } } -map_plugin_settings_t CMailx::GetSettings() -{ - map_plugin_settings_t ret; - - ret["Subject"] = m_sSubject; - ret["EmailFrom"] = m_sEmailFrom; - ret["EmailTo"] = m_sEmailTo; - ret["SendBinaryData"] = m_bSendBinaryData ? "yes" : "no"; - - return ret; -} +//ok to delete? +//const map_plugin_settings_t& CMailx::GetSettings() +//{ +// m_pSettings["Subject"] = m_sSubject; +// m_pSettings["EmailFrom"] = m_sEmailFrom; +// m_pSettings["EmailTo"] = m_sEmailTo; +// m_pSettings["SendBinaryData"] = m_bSendBinaryData ? "yes" : "no"; +// +// return m_pSettings; +//} PLUGIN_INFO(REPORTER, CMailx, diff --git a/lib/Plugins/Mailx.h b/lib/Plugins/Mailx.h index e3c86e73..4aa861f1 100644 --- a/lib/Plugins/Mailx.h +++ b/lib/Plugins/Mailx.h @@ -47,7 +47,8 @@ class CMailx : public CReporter CMailx(); virtual void SetSettings(const map_plugin_settings_t& pSettings); - virtual map_plugin_settings_t GetSettings(); +//ok to delete? +// virtual const map_plugin_settings_t& GetSettings(); virtual std::string Report(const map_crash_report_t& pCrashReport, const map_plugin_settings_t& pSettings, const std::string& pArgs); diff --git a/lib/Plugins/Makefile.am b/lib/Plugins/Makefile.am index 428c2d67..0502f5e1 100644 --- a/lib/Plugins/Makefile.am +++ b/lib/Plugins/Makefile.am @@ -1,30 +1,42 @@ AM_CPPFLAGS = -I$(srcdir)/../../inc -I$(srcdir)/../Utils pluginslibdir=$(PLUGINS_LIB_DIR) -pluginslib_LTLIBRARIES = libCCpp.la \ - libMailx.la \ - libSQLite3.la \ - libLogger.la \ - libKerneloopsScanner.la\ - libKerneloopsReporter.la\ - libKerneloops.la \ - libRunApp.la \ - libSOSreport.la \ - libBugzilla.la \ - libCatcut.la \ - libTicketUploader.la \ - libPython.la \ - libFileTransfer.la - -dist_pluginslib_DATA = KerneloopsReporter.GTKBuilder Logger.GTKBuilder\ - Mailx.GTKBuilder Bugzilla.GTKBuilder\ - TicketUploader.GTKBuilder Catcut.GTKBuilder - -pluginsconfdir=$(PLUGINS_CONF_DIR) -dist_pluginsconf_DATA = CCpp.conf Mailx.conf SQLite3.conf Logger.conf KerneloopsScanner.conf KerneloopsReporter.conf Bugzilla.conf Catcut.conf TicketUploader.conf FileTransfer.conf - - -man_MANS = abrt-FileTransfer.7 abrt-Bugzilla.7 abrt-KerneloopsReporter.7\ - abrt-KerneloopsScanner.7 abrt-Logger.7 abrt-Mailx.7 abrt-plugins.7\ +pluginslib_LTLIBRARIES = \ + libCCpp.la \ + libMailx.la \ + libSQLite3.la \ + libLogger.la \ + libKerneloopsScanner.la\ + libKerneloopsReporter.la\ + libKerneloops.la \ + libRunApp.la \ + libSOSreport.la \ + libBugzilla.la \ + libCatcut.la \ + libTicketUploader.la \ + libPython.la \ + libFileTransfer.la + +dist_pluginslib_DATA = \ + KerneloopsReporter.GTKBuilder Logger.GTKBuilder \ + Mailx.GTKBuilder Bugzilla.GTKBuilder \ + TicketUploader.GTKBuilder Catcut.GTKBuilder + +pluginsconfdir = $(PLUGINS_CONF_DIR) +dist_pluginsconf_DATA = \ + CCpp.conf \ + Mailx.conf \ + SQLite3.conf \ + Logger.conf \ + Kerneloops.conf \ + KerneloopsScanner.conf \ + KerneloopsReporter.conf \ + Bugzilla.conf \ + Catcut.conf \ + TicketUploader.conf \ + FileTransfer.conf + +man_MANS = abrt-FileTransfer.7 abrt-Bugzilla.7 abrt-KerneloopsReporter.7 \ + abrt-KerneloopsScanner.7 abrt-Logger.7 abrt-Mailx.7 abrt-plugins.7 \ abrt-SQLite3.7 abrt-RunApp.7 abrt-TicketUploader.7 # + abrt-Catcut.7 diff --git a/lib/Plugins/Python.cpp b/lib/Plugins/Python.cpp index 9be76b3b..9fb78808 100644 --- a/lib/Plugins/Python.cpp +++ b/lib/Plugins/Python.cpp @@ -6,7 +6,7 @@ #define FILENAME_BACKTRACE "backtrace" #define PYHOOK_CONFIG "/etc/abrt/pyhook.conf" -std::string CAnalyzerPython::CreateHash(const std::string& pDebugDumpDir) +static std::string CreateHash(const char *pDebugDumpDir) { std::string uuid; CDebugDump dd; @@ -15,11 +15,11 @@ std::string CAnalyzerPython::CreateHash(const std::string& pDebugDumpDir) return uuid; } -std::string CAnalyzerPython::GetLocalUUID(const std::string& pDebugDumpDir) +std::string CAnalyzerPython::GetLocalUUID(const char *pDebugDumpDir) { return CreateHash(pDebugDumpDir); } -std::string CAnalyzerPython::GetGlobalUUID(const std::string& pDebugDumpDir) +std::string CAnalyzerPython::GetGlobalUUID(const char *pDebugDumpDir) { return GetLocalUUID(pDebugDumpDir); } diff --git a/lib/Plugins/Python.h b/lib/Plugins/Python.h index b54de8dc..82f52c05 100644 --- a/lib/Plugins/Python.h +++ b/lib/Plugins/Python.h @@ -8,12 +8,11 @@ class CAnalyzerPython : public CAnalyzer { public: - virtual std::string GetLocalUUID(const std::string& pDebugDumpDir); - virtual std::string GetGlobalUUID(const std::string& pDebugDumpDir); - virtual void CreateReport(const std::string& pDebugDumpDir, int force) {} + 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 std::string CreateHash(const std::string& pInput); }; #endif /* PYTHON_H_ */ diff --git a/lib/Plugins/RunApp.cpp b/lib/Plugins/RunApp.cpp index 5a5c1d44..f816dc23 100644 --- a/lib/Plugins/RunApp.cpp +++ b/lib/Plugins/RunApp.cpp @@ -29,41 +29,41 @@ #define COMMAND 0 #define FILENAME 1 -void CActionRunApp::ParseArgs(const std::string& psArgs, vector_string_t& pArgs) +/* TODO: do not duplicate: SOSreport.cpp has same function too */ +static void ParseArgs(const char *psArgs, vector_string_t& pArgs) { - unsigned int ii; + unsigned ii; bool is_quote = false; - std::string item = ""; - for (ii = 0; ii < psArgs.length(); ii++) + std::string item; + + for (ii = 0; psArgs[ii]; ii++) { - if (psArgs[ii] == '\"') + if (psArgs[ii] == '"') { - is_quote = is_quote == true ? false : true; + is_quote = !is_quote; } else if (psArgs[ii] == ',' && !is_quote) { pArgs.push_back(item); - item = ""; + item.clear(); } else { item += psArgs[ii]; } } - if (item != "") + + if (item.size() != 0) { pArgs.push_back(item); } } -void CActionRunApp::Run(const std::string& pActionDir, - const std::string& pArgs) +void CActionRunApp::Run(const char *pActionDir, const char *pArgs) { update_client(_("Executing RunApp plugin...")); - char line[1024]; - std::string output = ""; - + std::string output; vector_string_t args; ParseArgs(pArgs, args); @@ -71,8 +71,9 @@ void CActionRunApp::Run(const std::string& pActionDir, FILE *fp = popen(args[COMMAND].c_str(), "r"); if (fp == NULL) { - throw CABRTException(EXCEP_PLUGIN, "CActionRunApp::Run(): cannot execute " + args[COMMAND]); + throw CABRTException(EXCEP_PLUGIN, "Can't execute " + args[COMMAND]); } + char line[1024]; while (fgets(line, 1024, fp) != NULL) { output += line; @@ -83,7 +84,7 @@ void CActionRunApp::Run(const std::string& pActionDir, { CDebugDump dd; dd.Open(pActionDir); - dd.SaveText(args[FILENAME].c_str(), output); + dd.SaveText(args[FILENAME].c_str(), output.c_str()); } } diff --git a/lib/Plugins/RunApp.h b/lib/Plugins/RunApp.h index 23315f1d..939feaa5 100644 --- a/lib/Plugins/RunApp.h +++ b/lib/Plugins/RunApp.h @@ -28,12 +28,8 @@ class CActionRunApp : public CAction { - private: - void ParseArgs(const std::string& psArgs, vector_string_t& pArgs); - public: - virtual void Run(const std::string& pActionDir, - const std::string& pArgs); + virtual void Run(const char *pActionDir, const char *pArgs); }; #endif diff --git a/lib/Plugins/SOSreport.cpp b/lib/Plugins/SOSreport.cpp index ab6125c4..fedc51ab 100644 --- a/lib/Plugins/SOSreport.cpp +++ b/lib/Plugins/SOSreport.cpp @@ -18,41 +18,26 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include <stdio.h> -#include <string.h> #include <ext/stdio_filebuf.h> #include <fstream> #include <sstream> +#include "abrtlib.h" +#include "abrt_types.h" +#include "ABRTException.h" #include "SOSreport.h" #include "DebugDump.h" #include "ABRTException.h" #include "CommLayerInner.h" -void CActionSOSreport::CopyFile(const std::string& pSourceName, const std::string& pDestName) -{ - std::ifstream source(pSourceName.c_str(), std::fstream::binary); - - if (!source) - { - throw CABRTException(EXCEP_PLUGIN, "CActionSOSreport::CopyFile(): could not open input sosreport filename:" + pSourceName); - } - std::ofstream dest(pDestName.c_str(),std::fstream::trunc|std::fstream::binary); - if (!dest) - { - throw CABRTException(EXCEP_PLUGIN, "CActionSOSreport::CopyFile(): could not open output sosreport filename:" + pDestName); - } - dest << source.rdbuf(); -} - -void CActionSOSreport::ErrorCheck(const index_type pI) +static void ErrorCheck(int pos) { - if (pI == std::string::npos) + if (pos < 0) { - throw CABRTException(EXCEP_PLUGIN, std::string("CActionSOSreport::ErrorCheck(): could not find filename in sosreport output")); + throw CABRTException(EXCEP_PLUGIN, "Can't find filename in sosreport output"); } } -std::string CActionSOSreport::ParseFilename(const std::string& pOutput) +static std::string ParseFilename(const std::string& pOutput) { /* the sosreport's filename is embedded in sosreport's output. @@ -63,83 +48,85 @@ std::string CActionSOSreport::ParseFilename(const std::string& pOutput) static const char sosreport_filename_marker[] = "Your sosreport has been generated and saved in:"; - index_type p = pOutput.find(sosreport_filename_marker); + int p = pOutput.find(sosreport_filename_marker); ErrorCheck(p); - p += strlen(sosreport_filename_marker); + p += sizeof(sosreport_filename_marker)-1; - index_type filename_start = pOutput.find_first_not_of(" \n\t", p); + int filename_start = pOutput.find_first_not_of(" \n\t", p); ErrorCheck(p); - index_type line_end = pOutput.find_first_of('\n',filename_start); + int line_end = pOutput.find_first_of('\n',filename_start); ErrorCheck(p); - index_type filename_end = pOutput.find_last_not_of(" \n\t",line_end); + int filename_end = pOutput.find_last_not_of(" \n\t", line_end); ErrorCheck(p); - return pOutput.substr(filename_start,(filename_end-filename_start)+1); + return pOutput.substr(filename_start, filename_end - filename_start + 1); } -void CActionSOSreport::ParseArgs(const std::string& psArgs, vector_args_t& pArgs) +/* TODO: do not duplicate: RunApp.cpp has same function too */ +static void ParseArgs(const char *psArgs, vector_string_t& pArgs) { - unsigned int ii; + unsigned ii; bool is_quote = false; - std::string item = ""; - for (ii = 0; ii < psArgs.length(); ii++) + std::string item; + + for (ii = 0; psArgs[ii]; ii++) { - if (psArgs[ii] == '\"') + if (psArgs[ii] == '"') { - is_quote = is_quote == true ? false : true; + is_quote = !is_quote; } else if (psArgs[ii] == ',' && !is_quote) { pArgs.push_back(item); - item = ""; + item.clear(); } else { item += psArgs[ii]; } } - if (item != "") + + if (item.size() != 0) { pArgs.push_back(item); } } -void CActionSOSreport::Run(const std::string& pActionDir, - const std::string& pArgs) +void CActionSOSreport::Run(const char *pActionDir, const char *pArgs) { update_client(_("Executing SOSreport plugin...")); - const char command_default[] = "sosreport --batch --no-progressbar --only=anaconda --only=bootloader" + static const char command_default[] = "sosreport --batch --no-progressbar --only=anaconda --only=bootloader" " --only=devicemapper --only=filesys --only=hardware --only=kernel" " --only=libraries --only=memory --only=networking --only=nfsserver" " --only=pam --only=process --only=rpm -k rpm.rpmva=off --only=ssh" " --only=startup --only=yum 2>&1"; - const char command_prefix[] = "sosreport --batch --no-progressbar"; + static const char command_prefix[] = "sosreport --batch --no-progressbar"; std::string command; - vector_args_t args; + vector_string_t args; ParseArgs(pArgs, args); if (args.size() == 0 || args[0] == "") { - command = std::string(command_default); + command = command_default; } else { - command = std::string(command_prefix) + ' ' + args[0] + " 2>&1"; + command = ssprintf("%s %s 2>&1", command_prefix, args[0].c_str()); } - update_client(_("running sosreport: ") + command); + update_client(_("running sosreport: %s"), command.c_str()); FILE *fp = popen(command.c_str(), "r"); - if (fp == NULL) { - throw CABRTException(EXCEP_PLUGIN, std::string("CActionSOSreport::Run(): cannot execute ") + command); + throw CABRTException(EXCEP_PLUGIN, ssprintf("Can't execute '%s'", command.c_str())); } +//vda TODO: fix this mess std::ostringstream output_stream; __gnu_cxx::stdio_filebuf<char> command_output_buffer(fp, std::ios_base::in); @@ -152,13 +139,21 @@ void CActionSOSreport::Run(const std::string& pActionDir, std::string output = output_stream.str(); std::string sosreport_filename = ParseFilename(output); - std::string sosreport_dd_filename = pActionDir + "/sosreport.tar.bz2"; + std::string sosreport_dd_filename = concat_path_file(pActionDir, "sosreport.tar.bz2"); CDebugDump dd; dd.Open(pActionDir); //Not useful //dd.SaveText("sosreportoutput", output); - CopyFile(sosreport_filename,sosreport_dd_filename); + if (copy_file(sosreport_filename.c_str(), sosreport_dd_filename.c_str()) < 0) + { + throw CABRTException(EXCEP_PLUGIN, + ssprintf("Can't copy '%s' to '%s'", + sosreport_filename.c_str(), + sosreport_dd_filename.c_str() + ) + ); + } } PLUGIN_INFO(ACTION, diff --git a/lib/Plugins/SOSreport.h b/lib/Plugins/SOSreport.h index 1a352876..d4e0d733 100644 --- a/lib/Plugins/SOSreport.h +++ b/lib/Plugins/SOSreport.h @@ -22,24 +22,11 @@ #define SOSREPORT_H_ #include "Action.h" -#include <string> -#include <vector> class CActionSOSreport : public CAction { - private: - typedef std::string::size_type index_type; - - void CopyFile(const std::string& pSourceName, const std::string& pDestName); - void ErrorCheck(const index_type pI); - std::string ParseFilename(const std::string& pOutput); - - typedef std::vector<std::string> vector_args_t; - void ParseArgs(const std::string& psArgs, vector_args_t& pArgs); - public: - virtual void Run(const std::string& pActionDir, - const std::string& pArgs); + virtual void Run(const char *pActionDir, const char *pArgs); }; #endif diff --git a/lib/Plugins/SQLite3.cpp b/lib/Plugins/SQLite3.cpp index dc035d30..3aad0545 100644 --- a/lib/Plugins/SQLite3.cpp +++ b/lib/Plugins/SQLite3.cpp @@ -325,7 +325,7 @@ void CSQLite3::Delete(const std::string& pUUID, const std::string& pUID) void CSQLite3::SetReported(const std::string& pUUID, const std::string& pUID, const std::string& pMessage) { - if(pUID == "0") + if (pUID == "0") { Exec("UPDATE "ABRT_TABLE" " "SET "DATABASE_COLUMN_REPORTED" = 1 " @@ -398,20 +398,24 @@ database_row_t CSQLite3::GetUUIDData(const std::string& pUUID, const std::string void CSQLite3::SetSettings(const map_plugin_settings_t& pSettings) { - if (pSettings.find("DBPath") != pSettings.end()) + m_pSettings = pSettings; + + map_plugin_settings_t::const_iterator end = pSettings.end(); + map_plugin_settings_t::const_iterator it; + it = pSettings.find("DBPath"); + if (it != end) { - m_sDBPath = pSettings.find("DBPath")->second; + m_sDBPath = it->second; } } -map_plugin_settings_t CSQLite3::GetSettings() -{ - map_plugin_settings_t ret; - - ret["DBPath"] = m_sDBPath; - - return ret; -} +//ok to delete? +//const map_plugin_settings_t& CSQLite3::GetSettings() +//{ +// m_pSettings["DBPath"] = m_sDBPath; +// +// return m_pSettings; +//} PLUGIN_INFO(DATABASE, CSQLite3, diff --git a/lib/Plugins/SQLite3.h b/lib/Plugins/SQLite3.h index e7ca8ae2..fc13bd73 100644 --- a/lib/Plugins/SQLite3.h +++ b/lib/Plugins/SQLite3.h @@ -58,7 +58,8 @@ class CSQLite3 : public CDatabase virtual database_row_t GetUUIDData(const std::string& pUUID, const std::string& pUID); virtual void SetSettings(const map_plugin_settings_t& pSettings); - virtual map_plugin_settings_t GetSettings(); +//ok to delete? +// virtual const map_plugin_settings_t& GetSettings(); }; #endif /* SQLITE3_H_ */ diff --git a/lib/Plugins/TicketUploader.cpp b/lib/Plugins/TicketUploader.cpp index 179ccc07..76bda400 100644 --- a/lib/Plugins/TicketUploader.cpp +++ b/lib/Plugins/TicketUploader.cpp @@ -17,26 +17,20 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ - +#include <string> +#include <fstream> +#include <sstream> +#include <curl/curl.h> +#include "abrtlib.h" #include "TicketUploader.h" #include "DebugDump.h" #include "ABRTException.h" #include "CommLayerInner.h" -#include <stdlib.h> -#include <sys/stat.h> - -#include <string> -#include <fstream> -#include <sstream> -#include <ext/stdio_filebuf.h> -#include <curl/curl.h> +using namespace std; CTicketUploader::CTicketUploader() : - m_sCustomer(""), - m_sTicket(""), - m_sURL(""), m_bEncrypt(false), m_bUpload(false), m_nRetryCount(3), @@ -47,197 +41,131 @@ CTicketUploader::~CTicketUploader() {} - -void CTicketUploader::Error(string func, string msg) +static void Error(const char *msg) { - update_client(msg); - throw CABRTException(EXCEP_PLUGIN, func + msg); -} - -void CTicketUploader::CopyFile(const std::string& pSourceName, const std::string& pDestName) -{ - std::ifstream source(pSourceName.c_str(), std::fstream::binary); - - if (!source) - { - throw CABRTException(EXCEP_PLUGIN, "CActionSOSreport::CopyFile(): could not open input sosreport filename:" + pSourceName); - } - std::ofstream dest(pDestName.c_str(),std::fstream::trunc|std::fstream::binary); - if (!dest) - { - throw CABRTException(EXCEP_PLUGIN, "CActionSOSreport::CopyFile(): could not open output sosreport filename:" + pDestName); - } - dest << source.rdbuf(); + update_client("%s", msg); + throw CABRTException(EXCEP_PLUGIN, msg); } -void CTicketUploader::RunCommand(string cmd) +static void RunCommand(const char *cmd) { - int retcode = system(cmd.c_str()); - if (retcode == -1) - { - Error("TicketUploader::RunCommand:", "error: could not start subshell: " + cmd); - } + int retcode = system(cmd); if (retcode) { - std::ostringstream msg; - msg << "error: subshell failed (rc=" << retcode << "):" << cmd; - Error("TicketUploader::RunCommand:", msg.str()); + Error(ssprintf("'%s' exited with %d", cmd, retcode).c_str()); } } -string CTicketUploader::ReadCommand(string cmd) +static string ReadCommand(const char *cmd) { - FILE* fp = popen(cmd.c_str(),"r"); + FILE* fp = popen(cmd, "r"); if (!fp) { - Error("TicketUploader::ReadCommand:", "error: could not start subshell: " + cmd); + Error(ssprintf("error running '%s'", cmd).c_str()); } - __gnu_cxx::stdio_filebuf<char> command_output_buffer(fp, std::ios_base::in); - std::ostringstream output_stream; - output_stream << &command_output_buffer; + string result; + char buff[1024]; + while (fgets(buff, sizeof(buff), fp) != NULL) + { + result += buff; + } int retcode = pclose(fp); if (retcode) { - std::ostringstream msg; - msg << "error: subshell failed (rc=" << retcode << "):" << cmd; - Error("TicketUploader::ReadCommand:", msg.str()); + Error(ssprintf("'%s' exited with %d", cmd, retcode).c_str()); } - return output_stream.str(); + return result; } -void CTicketUploader::WriteCommand(string cmd,string input) +static void WriteCommand(const char *cmd, const char *input) { - FILE* fp = popen(cmd.c_str(),"w"); + FILE* fp = popen(cmd, "w"); if (!fp) { - Error("TicketUploader::WriteCommand:", "error: could not start subshell: " + cmd); + Error(ssprintf("error running '%s'", cmd).c_str()); } - size_t input_length = input.length(); - size_t check = fwrite(input.c_str(),1,input_length,fp); - if (input_length != check) - { - Error("TicketUploader::WriteCommand:", "error: could not send input to subshell: " + cmd); - } + /* Hoping it's not too big to get us forever blocked... */ + fputs(input, fp); int retcode = pclose(fp); if (retcode) { - std::ostringstream msg; - msg << "error: subshell failed (rc=" << retcode << "):" << cmd; - Error("TicketUploader::ReadCommand:", msg.str()); + Error(ssprintf("'%s' exited with %d", cmd, retcode).c_str()); } - } -void CTicketUploader::SendFile(const std::string& pURL, - const std::string& pFilename) +void CTicketUploader::SendFile(const char *pURL, const char *pFilename) { - FILE * f; - struct stat buf; - CURL * curl; - std::string wholeURL, protocol; - int result, i, count = m_nRetryCount; - int len = pURL.length(); - std::string file; - - if (pURL == "") + if (pURL[0] == '\0') { - warn_client(_("FileTransfer: URL not specified")); + error_msg(_("FileTransfer: URL not specified")); return; } - protocol = ""; - i = 0; - while(pURL[i] != ':') - { - protocol += pURL[i]; - i++; - if(i == len) - { - throw CABRTException(EXCEP_PLUGIN, "CFileTransfer::SendFile(): malformed URL, does not contain protocol"); - } - } - - file = pFilename.substr(pFilename.rfind("/") + 1, pFilename.length()); - - if( pURL[len-1] == '/' ) - { - wholeURL = pURL + file; - } - else - { - wholeURL = pURL + "/" + file; - } - update_client(_("Sending archive ") + pFilename + _(" via ") + protocol + _(" to ") + pURL); + update_client(_("Sending archive %s to %s"), pFilename, pURL); + const char *base = (strrchr(pFilename, '/') ? : pFilename-1) + 1; + string wholeURL = concat_path_file(pURL, base); + int count = m_nRetryCount; + int result; do { - f = fopen(pFilename.c_str(),"r"); - if(!f) + FILE* f = fopen(pFilename, "r"); + if (!f) { - throw CABRTException(EXCEP_PLUGIN, "CFileTransfer::SendFile(): cannot open archive file "+pFilename); + throw CABRTException(EXCEP_PLUGIN, ssprintf("Can't open archive file '%s'", pFilename)); } - if (stat(pFilename.c_str(), &buf) == -1) + struct stat buf; + if (fstat(fileno(f), &buf) == -1) { - throw CABRTException(EXCEP_PLUGIN, "CFileTransfer::SendFile(): cannot stat archive file "+pFilename); + throw CABRTException(EXCEP_PLUGIN, ssprintf("Can't stat archive file '%s'", pFilename)); } - curl = curl_easy_init(); - if(!curl) + CURL* curl = curl_easy_init(); + if (!curl) { - throw CABRTException(EXCEP_PLUGIN, "CFileTransfer::SendFile(): Curl library error."); + throw CABRTException(EXCEP_PLUGIN, "Curl library init error"); } /* enable uploading */ curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); /* specify target */ curl_easy_setopt(curl, CURLOPT_URL, wholeURL.c_str()); - /*file handle: passed to the default callback, it will fread() it*/ curl_easy_setopt(curl, CURLOPT_READDATA, f); - /*get file size*/ curl_easy_setopt(curl, CURLOPT_INFILESIZE, buf.st_size); - /*everything is done here; result 0 means success*/ + /* everything is done here; result 0 means success */ result = curl_easy_perform(curl); - /*goodbye*/ + /* goodbye */ curl_easy_cleanup(curl); fclose(f); if (result != 0) { - update_client(_("Sending failed, try it again: ") + std::string(curl_easy_strerror((CURLcode)result))); + update_client(_("Sending failed, trying again. %s"), curl_easy_strerror((CURLcode)result)); } } /*retry the upload if not succesful, wait a bit before next try*/ - while( result!=0 && --count != 0 && (sleep(m_nRetryDelay),1) ); + while (result != 0 && --count != 0 && (sleep(m_nRetryDelay), 1)); if (count <= 0 && result != 0) { - throw CABRTException(EXCEP_PLUGIN, "CFileTransfer::SendFile(): Curl can not send a ticket."); + throw CABRTException(EXCEP_PLUGIN, "Curl can not send a ticket"); } } string CTicketUploader::Report(const map_crash_report_t& pCrashReport, - const map_plugin_settings_t& pSettings, const std::string& pArgs) + const map_plugin_settings_t& pSettings, const string& pArgs) { - string ret; update_client(_("Creating an TicketUploader report...")); - - // Get ticket name, customer name, and do_encrypt from config settings - string ticket_name; - string customer_name; - string upload_url; - bool do_encrypt = false; - bool do_upload = false; - - customer_name = m_sCustomer; - ticket_name = m_sTicket; - upload_url = m_sURL; - do_encrypt = m_bEncrypt; - do_upload = m_bUpload; + string customer_name = m_sCustomer; + string ticket_name = m_sTicket; + string upload_url = m_sURL; + bool do_encrypt = m_bEncrypt; + bool do_upload = m_bUpload; bool have_ticket_name = false; if (ticket_name == "") @@ -249,239 +177,224 @@ string CTicketUploader::Report(const map_crash_report_t& pCrashReport, have_ticket_name = true; } - - // Format the time to add to the file name const int timebufmax = 256; char timebuf[timebufmax]; time_t curtime = time(NULL); - if (!strftime(timebuf,timebufmax,"-%G%m%d%k%M%S",gmtime(&curtime))) + if (!strftime(timebuf, timebufmax, "-%G%m%d%k%M%S", gmtime(&curtime))) { - Error("TicketUploader::Report:","could not format time"); + Error("Can't format time"); } - - // Create a tmp work directory, and within that the directory // that will be the root of the tarball string file_name = ticket_name + timebuf; - char TEMPLATE[] = "/tmp/rhuploadXXXXXX"; - string tmpdir_name = mkdtemp(TEMPLATE); - string tmptar_name = tmpdir_name + '/' + file_name; + char tmpdir_name[] = "/tmp/rhuploadXXXXXX"; + if (mkdtemp(tmpdir_name) == NULL) + { + Error("Can't mkdir a temporary directory in /tmp"); + } + string tmptar_name = concat_path_file(tmpdir_name, file_name.c_str()); if (mkdir(tmptar_name.c_str(),S_IRWXU)) { - Error("TicketUploader::Report:","error: could not mkdir: " + tmptar_name); + Error(ssprintf("Can't mkdir '%s'", tmptar_name.c_str()).c_str()); } - - // Copy each entry into the tarball root, // files are simply copied, strings are written to a file map_crash_report_t::const_iterator it; for (it = pCrashReport.begin(); it != pCrashReport.end(); it++) { - if (it->second[CD_TYPE] == CD_TXT) - { - string ofile_name = tmptar_name + '/' + it->first; - std::ofstream ofile(ofile_name.c_str(),std::fstream::trunc|std::fstream::binary); + if (it->second[CD_TYPE] == CD_TXT + || it->second[CD_TYPE] == CD_ATT + ) { + string ofile_name = concat_path_file(tmptar_name.c_str(), it->first.c_str()); + ofstream ofile(ofile_name.c_str(), fstream::trunc|fstream::binary); if (!ofile) { - Error("TicketUploader::Report:","error: could not open: " + ofile_name); + Error(ssprintf("Can't open '%s'", ofile_name.c_str()).c_str()); } - ofile << it->second[CD_CONTENT] << std::endl; + ofile << it->second[CD_CONTENT] << endl; ofile.close(); } - if (it->second[CD_TYPE] == CD_ATT) + else if (it->second[CD_TYPE] == CD_BIN) { - string ofile_name = tmptar_name + '/' + it->first; - std::ofstream ofile(ofile_name.c_str(),std::fstream::trunc|std::fstream::binary); - if (!ofile) + string ofile_name = concat_path_file(tmptar_name.c_str(), it->first.c_str()); + if (copy_file(it->second[CD_CONTENT].c_str(), ofile_name.c_str()) < 0) { - Error("TicketUploader::Report:","error: could not open: " + ofile_name); + throw CABRTException(EXCEP_PLUGIN, + ssprintf("Can't copy '%s' to '%s'", + it->second[CD_CONTENT].c_str(), + ofile_name.c_str() + ) + ); } - ofile << it->second[CD_CONTENT] << std::endl; - ofile.close(); - } - if (it->second[CD_TYPE] == CD_BIN) - { - string ofile_name = tmptar_name + '/' + it->first; - CopyFile(it->second[CD_CONTENT],ofile_name); } } - - // add ticket_name and customer name to tarball if (have_ticket_name) { string ofile_name = tmptar_name + "/TICKET"; - std::ofstream ofile(ofile_name.c_str(),std::fstream::trunc|std::fstream::binary); + ofstream ofile(ofile_name.c_str(), fstream::trunc|fstream::binary); if (!ofile) { - Error("TicketUploader::Report:","error: could not open: " + ofile_name); + Error(ssprintf("Can't open '%s'", ofile_name.c_str()).c_str()); } - ofile << ticket_name << std::endl; + ofile << ticket_name << endl; ofile.close(); } if (customer_name != "") { string ofile_name = tmptar_name + "/CUSTOMER"; - std::ofstream ofile(ofile_name.c_str(),std::fstream::trunc|std::fstream::binary); + ofstream ofile(ofile_name.c_str(), fstream::trunc|fstream::binary); if (!ofile) { - Error("TicketUploader::Report:","error: could not open: " + ofile_name); + Error(ssprintf("Can't open '%s'", ofile_name.c_str()).c_str()); } - ofile << customer_name << std::endl; + ofile << customer_name << endl; ofile.close(); } - - // Create the compressed tarball string outfile_basename = file_name + ".tar.gz"; - string outfile_name = tmpdir_name + '/' + outfile_basename; - string cmd = string("tar -C ") + tmpdir_name + - " --create --gzip --file=" + outfile_name + ' ' + file_name; - RunCommand(cmd); - - - + string outfile_name = concat_path_file(tmpdir_name, outfile_basename.c_str()); + string cmd = ssprintf("tar -C %s --create --gzip --file=%s %s", tmpdir_name, outfile_name.c_str(), file_name.c_str()); + RunCommand(cmd.c_str()); // encrypt if requested string key; if (do_encrypt) { - cmd = string("openssl rand -base64 48"); - key = ReadCommand(cmd); + key = ReadCommand("openssl rand -base64 48"); string infile_name = outfile_name; outfile_basename += ".aes"; outfile_name += ".aes"; - cmd = string("openssl aes-128-cbc -in ") + infile_name + - " -out " + outfile_name + " -pass stdin"; - WriteCommand(cmd,key); + cmd = ssprintf("openssl aes-128-cbc -in %s -out %s -pass stdin", infile_name.c_str(), outfile_name.c_str()); + WriteCommand(cmd.c_str(), key.c_str()); } - - // generate md5sum - cmd = string("cd ") + tmpdir_name + string("; md5sum ") + outfile_basename; - string md5sum = ReadCommand(cmd); - - + cmd = ssprintf("cd %s; md5sum %s", tmpdir_name, outfile_basename.c_str()); + string md5sum = ReadCommand(cmd.c_str()); // upload or cp to /tmp if (do_upload) { // FIXME: SendFile isn't working sometime (scp) - SendFile(upload_url,outfile_name); + SendFile(upload_url.c_str(), outfile_name.c_str()); } else { - cmd = string("cp ") + outfile_name + " /tmp/"; - RunCommand(cmd); + cmd = ssprintf("cp %s /tmp/", outfile_name.c_str()); + RunCommand(cmd.c_str()); } - - // generate a reciept telling md5sum and encryption key - std::ostringstream msgbuf; + ostringstream msgbuf; if (have_ticket_name) - msgbuf << _("Please copy this into ticket: ") << ticket_name << std::endl; + msgbuf << _("Please copy this into ticket: ") << ticket_name << endl; else - msgbuf << _("Please send this to your technical support: ") << std::endl; + msgbuf << _("Please send this to your technical support: ") << endl; if (do_upload) - msgbuf << _("RHUPLOAD: This report was sent to ") + upload_url << std::endl; + msgbuf << _("RHUPLOAD: This report was sent to ") + upload_url << endl; else - msgbuf << _("RHUPLOAD: This report was copied into /tmp/: ") << std::endl; + msgbuf << _("RHUPLOAD: This report was copied into /tmp/: ") << endl; if (have_ticket_name) - msgbuf << _("TICKET: ") << ticket_name << std::endl; - msgbuf << _("FILE: ") << outfile_basename << std::endl; - msgbuf << _("MD5SUM: ") << std::endl; + msgbuf << _("TICKET: ") << ticket_name << endl; + msgbuf << _("FILE: ") << outfile_basename << endl; + msgbuf << _("MD5SUM: ") << endl; msgbuf << md5sum; if (do_encrypt) { - msgbuf << _("KEY: aes-128-cbc") << std::endl; + msgbuf << _("KEY: aes-128-cbc") << endl; msgbuf << key; } - msgbuf << _("END: ") << std::endl; + msgbuf << _("END: ") << endl; - warn_client(msgbuf.str()); + error_msg("%s", msgbuf.str().c_str()); + string ret; if (do_upload) { string xx = _("report sent to ") + upload_url + '/' + outfile_basename; - update_client(xx); + update_client("%s", xx.c_str()); ret = xx; } else { string xx = _("report copied to /tmp/") + outfile_basename; - update_client(xx); + update_client("%s", xx.c_str()); ret = xx; } // delete the temporary directory - cmd = string("rm -rf ") + tmpdir_name; - RunCommand(cmd); + cmd = ssprintf("rm -rf %s", tmpdir_name); + RunCommand(cmd.c_str()); return ret; } void CTicketUploader::SetSettings(const map_plugin_settings_t& pSettings) { - if (pSettings.find("Customer") != pSettings.end()) + m_pSettings = pSettings; + + map_plugin_settings_t::const_iterator end = pSettings.end(); + map_plugin_settings_t::const_iterator it; + it = pSettings.find("Customer"); + if (it != end) { - m_sCustomer = pSettings.find("Customer")->second; + m_sCustomer = it->second; } - if (pSettings.find("Ticket") != pSettings.end()) + it = pSettings.find("Ticket"); + if (it != end) { - m_sTicket = pSettings.find("Ticket")->second; + m_sTicket = it->second; } - if (pSettings.find("URL") != pSettings.end()) + it = pSettings.find("URL"); + if (it != end) { - m_sURL = pSettings.find("URL")->second; + m_sURL = it->second; } - if (pSettings.find("Encrypt") != pSettings.end()) + it = pSettings.find("Encrypt"); + if (it != end) { - m_bEncrypt = pSettings.find("Encrypt")->second == "yes"; + m_bEncrypt = string_to_bool(it->second.c_str()); } - if (pSettings.find("Upload") != pSettings.end()) + it = pSettings.find("Upload"); + if (it != end) { - m_bUpload = pSettings.find("Upload")->second == "yes"; + m_bUpload = string_to_bool(it->second.c_str()); } - if (pSettings.find("RetryCount") != pSettings.end()) + it = pSettings.find("RetryCount"); + if (it != end) { - m_nRetryCount = atoi(pSettings.find("RetryCount")->second.c_str()); + m_nRetryCount = atoi(it->second.c_str()); } - if (pSettings.find("RetryDelay") != pSettings.end()) + it = pSettings.find("RetryDelay"); + if (it != end) { - m_nRetryDelay = atoi(pSettings.find("RetryDelay")->second.c_str()); + m_nRetryDelay = atoi(it->second.c_str()); } } -map_plugin_settings_t CTicketUploader::GetSettings() -{ - map_plugin_settings_t ret; - - ret["Customer"] = m_sCustomer; - ret["Ticket"] = m_sTicket; - ret["URL"] = m_sURL; - ret["Encrypt"] = m_bEncrypt ? "yes" : "no"; - ret["Upload"] = m_bEncrypt ? "yes" : "no"; - - std::stringstream ss; - ss << m_nRetryCount; - ret["RetryCount"] = ss.str(); - ss.str(""); - ss << m_nRetryDelay; - ret["RetryDelay"] = ss.str(); - - return ret; -} +//ok to delete? +//const map_plugin_settings_t& CTicketUploader::GetSettings() +//{ +// m_pSettings["Customer"] = m_sCustomer; +// m_pSettings["Ticket"] = m_sTicket; +// m_pSettings["URL"] = m_sURL; +// m_pSettings["Encrypt"] = m_bEncrypt ? "yes" : "no"; +// m_pSettings["Upload"] = m_bEncrypt ? "yes" : "no"; +// m_pSettings["RetryCount"] = to_string(m_nRetryCount); +// m_pSettings["RetryDelay"] = to_string(m_nRetryDelay); +// +// return m_pSettings; +//} PLUGIN_INFO(REPORTER, CTicketUploader, diff --git a/lib/Plugins/TicketUploader.h b/lib/Plugins/TicketUploader.h index 92e33872..2a7c98af 100644 --- a/lib/Plugins/TicketUploader.h +++ b/lib/Plugins/TicketUploader.h @@ -29,46 +29,29 @@ #include "Reporter.h" #include "CrashTypes.h" -typedef std::string string; - class CTicketUploader : public CReporter { private: - string m_sCustomer; - string m_sTicket; - string m_sURL; - bool m_bEncrypt; - bool m_bUpload; - - int m_nRetryCount; - int m_nRetryDelay; - - void Error(string func, string msg); - void CopyFile(const std::string& pSourceName, const std::string& pDestName); - // Wrappers around popen/system - // the wrapper in each case handles errors, - // and converts from string->char* - // RunCommand - a wrapper around system(cmd) - void RunCommand(string cmd); - // ReadCommand - a wrapper around popen(cmd,"r") - string ReadCommand(string cmd); - // WriteCommand - a wrapper around popen(cmd,"w") - void WriteCommand(string cmd, string input ); + std::string m_sCustomer; + std::string m_sTicket; + std::string m_sURL; + bool m_bEncrypt; + bool m_bUpload; + int m_nRetryCount; + int m_nRetryDelay; - void SendFile(const std::string& pURL, - const std::string& pFilename); + void SendFile(const char *pURL, const char *pFilename); public: CTicketUploader(); virtual ~CTicketUploader(); - virtual map_plugin_settings_t GetSettings(); +//ok to delete? +// virtual const map_plugin_settings_t& GetSettings(); virtual void SetSettings(const map_plugin_settings_t& pSettings); - virtual string Report(const map_crash_report_t& pCrashReport, + virtual std::string Report(const map_crash_report_t& pCrashReport, const map_plugin_settings_t& pSettings, const std::string& pArgs); - - }; -#endif /* TICKETUPLOADER_H_ */ +#endif diff --git a/lib/Utils/Action.h b/lib/Utils/Action.h index 1286feba..5992cbff 100644 --- a/lib/Utils/Action.h +++ b/lib/Utils/Action.h @@ -22,7 +22,6 @@ #ifndef ACTION_H_ #define ACTION_H_ -#include <string> #include "Plugin.h" /** @@ -40,8 +39,7 @@ class CAction : public CPlugin * @param pActionDir An actual directory. * @param pArgs Plugin's arguments. */ - virtual void Run(const std::string& pActionDir, - const std::string& pArgs) = 0; + virtual void Run(const char *pActionDir, const char *pArgs) = 0; }; -#endif /*ACTION_H_*/ +#endif diff --git a/lib/Utils/Analyzer.h b/lib/Utils/Analyzer.h index e5bda574..9108a914 100644 --- a/lib/Utils/Analyzer.h +++ b/lib/Utils/Analyzer.h @@ -37,20 +37,20 @@ class CAnalyzer : public CPlugin * @param pDebugDumpPath A debugdump dir containing all necessary data. * @return A local UUID. */ - virtual std::string GetLocalUUID(const std::string& pDebugDumpPath) = 0; + virtual std::string GetLocalUUID(const char *pDebugDumpDir) = 0; /** * A method, which gets a global UUID of particular crash. * @param pDebugDumpPath A debugdump dir containing all necessary data. * @return A global UUID. */ - virtual std::string GetGlobalUUID(const std::string& pDebugDumpPath) = 0; + virtual std::string GetGlobalUUID(const char *pDebugDumpDir) = 0; /** * A method, which takes care of getting all additional data needed * for computing UUIDs and creating a report. This report could be send * somewhere afterwards. * @param pDebugDumpPath A debugdump dir containing all necessary data. */ - virtual void CreateReport(const std::string& pDebugDumpPath, int force) = 0; + virtual void CreateReport(const char *pDebugDumpDir, int force) = 0; }; #endif /*ANALYZER_H_*/ diff --git a/lib/Utils/CommLayerInner.cpp b/lib/Utils/CommLayerInner.cpp index b5b8db78..307fe66d 100644 --- a/lib/Utils/CommLayerInner.cpp +++ b/lib/Utils/CommLayerInner.cpp @@ -10,29 +10,48 @@ static map_uint_str_t s_mapClientID; static pthread_mutex_t s_map_mutex; static bool s_map_mutex_inited; +/* called via [p]error_msg() */ +static void warn_client(const char *msg) +{ + if (!s_pObs) + return; + + uint64_t key = uint64_t(pthread_self()); + + pthread_mutex_lock(&s_map_mutex); + map_uint_str_t::const_iterator ki = s_mapClientID.find(key); + const char* peer = (ki != s_mapClientID.end() ? ki->second.c_str() : NULL); + pthread_mutex_unlock(&s_map_mutex); + + if (peer) + s_pObs->Warning(msg, peer, key); +} + void init_daemon_logging(CObserver *pObs) { s_pObs = pObs; if (!s_map_mutex_inited) { - pthread_mutex_init(&s_map_mutex, NULL); s_map_mutex_inited = true; + pthread_mutex_init(&s_map_mutex, NULL); + g_custom_logger = &warn_client; } } -void set_client_name(const char* name) +void set_client_name(const char *name) { uint64_t key = uint64_t(pthread_self()); pthread_mutex_lock(&s_map_mutex); - if (!name) + if (!name) { s_mapClientID.erase(key); - else + } else { s_mapClientID[key] = name; + } pthread_mutex_unlock(&s_map_mutex); } -void warn_client(const std::string& pMessage) +void update_client(const char *fmt, ...) { if (!s_pObs) return; @@ -44,26 +63,16 @@ void warn_client(const std::string& pMessage) const char* peer = (ki != s_mapClientID.end() ? ki->second.c_str() : NULL); pthread_mutex_unlock(&s_map_mutex); - if (peer) - s_pObs->Warning(pMessage, peer, key); - else /* Bug: someone tries to warn_client() without set_client_name()!? */ - log("Hmm, stray %s: '%s'", __func__, pMessage.c_str()); -} - -void update_client(const std::string& pMessage) -{ - if (!s_pObs) + if (!peer) return; - uint64_t key = uint64_t(pthread_self()); + va_list p; + va_start(p, fmt); + char *msg; + int used = vasprintf(&msg, fmt, p); + va_end(p); + if (used < 0) + return; - pthread_mutex_lock(&s_map_mutex); - map_uint_str_t::const_iterator ki = s_mapClientID.find(key); - const char* peer = (ki != s_mapClientID.end() ? ki->second.c_str() : NULL); - pthread_mutex_unlock(&s_map_mutex); - - if (peer) - s_pObs->Status(pMessage, peer, key); - else - log("Hmm, stray %s: '%s'", __func__, pMessage.c_str()); + s_pObs->Status(msg, peer, key); } diff --git a/lib/Utils/CommLayerInner.h b/lib/Utils/CommLayerInner.h index d161cfc7..9c22968a 100644 --- a/lib/Utils/CommLayerInner.h +++ b/lib/Utils/CommLayerInner.h @@ -9,15 +9,19 @@ void init_daemon_logging(CObserver *pObs); * Set client's name (dbus ID). NULL unsets it. */ void set_client_name(const char* name); -/* Ask a client to warn the user about a non-fatal, but unexpected condition. + +/* + * Ask a client to warn the user about a non-fatal, but unexpected condition. * In GUI, it will usually be presented as a popup message. + * Usually there is no need to call it directly, just use [p]error_msg(). */ -void warn_client(const std::string& pMessage); -/* Logs a message to a client. +//now static: void warn_client(const char *msg); + +/* + * Logs a message to a client. * In UI, it will usually appear as a new status line message in GUI, * or as a new message line in CLI. */ -void update_client(const std::string& pMessage); - -#endif /* COMMLAYERINNER_H_ */ +void update_client(const char *fmt, ...); +#endif diff --git a/lib/Utils/DebugDump.cpp b/lib/Utils/DebugDump.cpp index ec9e4703..ba11d965 100644 --- a/lib/Utils/DebugDump.cpp +++ b/lib/Utils/DebugDump.cpp @@ -39,9 +39,16 @@ static bool isdigit_str(const char *str) return true; } -static std::string RemoveBackSlashes(const std::string& pDir); +static std::string RemoveBackSlashes(const char *pDir) +{ + unsigned len = strlen(pDir); + while (len != 0 && pDir[len-1] == '/') + len--; + return std::string(pDir, len); +} + static bool ExistFileDir(const char* pPath); -static void LoadTextFile(const std::string& pPath, std::string& pData); +static void LoadTextFile(const char *pPath, std::string& pData); CDebugDump::CDebugDump() : m_sDebugDumpDir(""), @@ -50,7 +57,7 @@ CDebugDump::CDebugDump() : m_bLocked(false) {} -void CDebugDump::Open(const std::string& pDir) +void CDebugDump::Open(const char *pDir) { if (m_bOpened) { @@ -59,7 +66,7 @@ void CDebugDump::Open(const std::string& pDir) m_sDebugDumpDir = RemoveBackSlashes(pDir); if (!ExistFileDir(m_sDebugDumpDir.c_str())) { - throw CABRTException(EXCEP_DD_OPEN, "CDebugDump::CDebugDump(): "+m_sDebugDumpDir+" does not exist."); + throw CABRTException(EXCEP_DD_OPEN, "CDebugDump::CDebugDump(): " + m_sDebugDumpDir + " does not exist."); } Lock(); m_bOpened = true; @@ -208,17 +215,17 @@ void CDebugDump::UnLock() } } -void CDebugDump::Create(const std::string& pDir, int64_t uid) +void CDebugDump::Create(const char *pDir, int64_t uid) { if (m_bOpened) { - throw CABRTException(EXCEP_ERROR, "CDebugDump::CDebugDump(): DebugDump is already opened."); + throw CABRTException(EXCEP_ERROR, "DebugDump is already opened"); } m_sDebugDumpDir = RemoveBackSlashes(pDir); if (ExistFileDir(m_sDebugDumpDir.c_str())) { - throw CABRTException(EXCEP_DD_OPEN, "CDebugDump::CDebugDump(): "+m_sDebugDumpDir+" already exists."); + throw CABRTException(EXCEP_DD_OPEN, ssprintf("'%s' already exists", m_sDebugDumpDir.c_str())); } Lock(); @@ -228,13 +235,13 @@ void CDebugDump::Create(const std::string& pDir, int64_t uid) { UnLock(); m_bOpened = false; - throw CABRTException(EXCEP_DD_OPEN, "CDebugDump::Create(): Cannot create dir: " + pDir); + throw CABRTException(EXCEP_DD_OPEN, ssprintf("Can't create dir '%s'", pDir)); } if (chmod(m_sDebugDumpDir.c_str(), 0700) == -1) { UnLock(); m_bOpened = false; - throw CABRTException(EXCEP_DD_OPEN, "CDebugDump::Create(): Cannot change permissions, dir: " + pDir); + throw CABRTException(EXCEP_DD_OPEN, ssprintf("Can't change mode of '%s'", pDir)); } struct passwd* pw = getpwuid(uid); gid_t gid = pw ? pw->pw_gid : uid; @@ -245,14 +252,15 @@ void CDebugDump::Create(const std::string& pDir, int64_t uid) perror_msg("can't change '%s' ownership to %u:%u", m_sDebugDumpDir.c_str(), (int)uid, (int)gid); } - SaveText(FILENAME_UID, ssprintf("%li", uid)); + SaveText(FILENAME_UID, to_string(uid).c_str()); SaveKernelArchitectureRelease(); - SaveTime(); + time_t t = time(NULL); + SaveText(FILENAME_TIME, to_string(t).c_str()); } -static void DeleteFileDir(const std::string& pDir) +static void DeleteFileDir(const char *pDir) { - DIR *dir = opendir(pDir.c_str()); + DIR *dir = opendir(pDir); if (!dir) return; @@ -261,26 +269,33 @@ static void DeleteFileDir(const std::string& pDir) { if (dot_or_dotdot(dent->d_name)) continue; - std::string fullPath = pDir + "/" + dent->d_name; + std::string fullPath = concat_path_file(pDir, dent->d_name); if (unlink(fullPath.c_str()) == -1) { if (errno != EISDIR) { closedir(dir); - throw CABRTException(EXCEP_DD_DELETE, std::string(__func__) + ": Cannot remove file: " + fullPath); + throw CABRTException(EXCEP_DD_DELETE, ssprintf("Can't remove dir %s", fullPath.c_str())); } - DeleteFileDir(fullPath); + DeleteFileDir(fullPath.c_str()); } } closedir(dir); - if (remove(pDir.c_str()) == -1) + if (remove(pDir) == -1) { - throw CABRTException(EXCEP_DD_DELETE, std::string(__func__) + ": Cannot remove dir: " + pDir); + throw CABRTException(EXCEP_DD_DELETE, ssprintf("Can't remove dir %s", pDir)); } } static bool IsTextFile(const char *name) { + /* Some files in our dump directories are known to always be textual */ + if (strcmp(name, "backtrace") == 0 + || strcmp(name, "cmdline") == 0 + ) { + return true; + } + /* This idiotic library thinks that file containing just "0" is not text (!!) magic_t m = magic_open(MAGIC_MIME_TYPE); @@ -320,25 +335,22 @@ static bool IsTextFile(const char *name) int r = full_read(fd, buf, sizeof(buf)); close(fd); + /* Every once in a while, even a text file contains a few garbled + * or unexpected non-ASCII chars. We should not declare it "binary". + */ + const unsigned RATIO = 50; + unsigned total_chars = r + RATIO; + unsigned bad_chars = 1; /* 1 prevents division by 0 later */ while (--r >= 0) { - if (buf[r] >= 0x7f) - return false; - /* Among control chars, only '\t','\n' etc are allowed */ - if (buf[r] < ' ' && !isspace(buf[r])) - return false; - } - return true; -} - -static std::string RemoveBackSlashes(const std::string& pDir) -{ - std::string ret = pDir; - while (ret[ret.length() - 1] == '/') - { - ret = ret.substr(0, ret.length() - 2); + if (buf[r] >= 0x7f + /* among control chars, only '\t','\n' etc are allowed */ + || (buf[r] < ' ' && !isspace(buf[r])) + ) { + bad_chars++; + } } - return ret; + return (total_chars / bad_chars) >= RATIO; } void CDebugDump::Delete() @@ -347,7 +359,7 @@ void CDebugDump::Delete() { return; } - DeleteFileDir(m_sDebugDumpDir); + DeleteFileDir(m_sDebugDumpDir.c_str()); } void CDebugDump::Close() @@ -374,100 +386,44 @@ void CDebugDump::SaveKernelArchitectureRelease() const char *release_ptr = release.c_str(); unsigned len_1st_str = strchrnul(release_ptr, '\n') - release_ptr; release.erase(len_1st_str); /* usually simply removes trailing '\n' */ - SaveText(FILENAME_RELEASE, release); + SaveText(FILENAME_RELEASE, release.c_str()); } -void CDebugDump::SaveTime() +static void LoadTextFile(const char *pPath, std::string& pData) { - time_t t = time(NULL); - SaveText(FILENAME_TIME, to_string(t)); -} - -static void LoadTextFile(const std::string& pPath, std::string& pData) -{ - std::ifstream fIn; + FILE *fp = fopen(pPath, "r"); + if (!fp) + { + throw CABRTException(EXCEP_DD_LOAD, ssprintf("Can't open file '%s'", pPath)); + } pData = ""; - fIn.open(pPath.c_str()); - if (fIn.is_open()) + int ch; + while ((ch = fgetc(fp)) != EOF) { - // TODO: rewrite this - int ch; - while ((ch = fIn.get())!= EOF) + if (ch == '\0') { - if (ch == 0) - { - pData += " "; - } - else if (isspace(ch) || (isascii(ch) && !iscntrl(ch))) - { - pData += ch; - } + pData += ' '; } - fIn.close(); - } - else - { - throw CABRTException(EXCEP_DD_LOAD, std::string(__func__) + ": Cannot open file " + pPath); - } -} - -static void LoadBinaryFile(const std::string& pPath, char** pData, unsigned int* pSize) -{ - std::ifstream fIn; - fIn.open(pPath.c_str(), std::ios::binary | std::ios::ate); - unsigned int size; - if (fIn.is_open()) - { - size = fIn.tellg(); - char *data = new char [size]; - fIn.read(data, size); - - *pData = data; - *pSize = size; - - fIn.close(); - } - else - { - throw CABRTException(EXCEP_DD_LOAD, std::string(__func__) + ": Cannot open file " + pPath); - } -} - -static void SaveTextFile(const std::string& pPath, const std::string& pData) -{ - std::ofstream fOut; - fOut.open(pPath.c_str()); - if (fOut.is_open()) - { - fOut << pData; - if (!fOut.good()) + else if (isspace(ch) || (isascii(ch) && !iscntrl(ch))) { - throw CABRTException(EXCEP_DD_SAVE, std::string(__func__) + ": Cannot save file " + pPath); + pData += ch; } - fOut.close(); - } - else - { - throw CABRTException(EXCEP_DD_SAVE, std::string(__func__) + ": Cannot open file " + pPath); } + fclose(fp); } -static void SaveBinaryFile(const std::string& pPath, const char* pData, const unsigned pSize) +static void SaveBinaryFile(const char *pPath, const char* pData, unsigned pSize) { - std::ofstream fOut; - fOut.open(pPath.c_str(), std::ios::binary); - if (fOut.is_open()) + int fd = open(pPath, O_WRONLY | O_TRUNC | O_CREAT, 0666); + if (fd < 0) { - fOut.write(pData, pSize); - if (!fOut.good()) - { - throw CABRTException(EXCEP_DD_SAVE, std::string(__func__) + ": Cannot save file " + pPath); - } - fOut.close(); + throw CABRTException(EXCEP_DD_SAVE, ssprintf("Can't open file '%s'", pPath)); } - else + unsigned r = full_write(fd, pData, pSize); + close(fd); + if (r != pSize) { - throw CABRTException(EXCEP_DD_SAVE, std::string(__func__) + ": Cannot open file " + pPath); + throw CABRTException(EXCEP_DD_SAVE, ssprintf("Can't save file '%s'", pPath)); } } @@ -477,36 +433,27 @@ 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; - LoadTextFile(fullPath, pData); -} -void CDebugDump::LoadBinary(const char* pName, char** pData, unsigned int* pSize) -{ - if (!m_bOpened) - { - throw CABRTException(EXCEP_DD_OPEN, "CDebugDump::LoadBinary(): DebugDump is not opened."); - } - std::string fullPath = m_sDebugDumpDir + "/" + pName; - LoadBinaryFile(fullPath, pData, pSize); + std::string fullPath = m_sDebugDumpDir + '/' + pName; + LoadTextFile(fullPath.c_str(), pData); } -void CDebugDump::SaveText(const char* pName, const std::string& pData) +void CDebugDump::SaveText(const char* pName, const char* pData) { if (!m_bOpened) { throw CABRTException(EXCEP_DD_OPEN, "CDebugDump::SaveText(): DebugDump is not opened."); } std::string fullPath = m_sDebugDumpDir + "/" + pName; - SaveTextFile(fullPath, pData); + SaveBinaryFile(fullPath.c_str(), pData, strlen(pData)); } -void CDebugDump::SaveBinary(const char* pName, const char* pData, const unsigned int pSize) +void CDebugDump::SaveBinary(const char* pName, const char* pData, unsigned pSize) { if (!m_bOpened) { throw CABRTException(EXCEP_DD_OPEN, "CDebugDump::SaveBinary(): DebugDump is not opened."); } std::string fullPath = m_sDebugDumpDir + "/" + pName; - SaveBinaryFile(fullPath, pData, pSize); + SaveBinaryFile(fullPath.c_str(), pData, pSize); } void CDebugDump::InitGetNextFile() @@ -538,7 +485,7 @@ bool CDebugDump::GetNextFile(std::string& pFileName, std::string& pContent, bool { if (is_regular_file(dent, m_sDebugDumpDir.c_str())) { - std::string fullname = m_sDebugDumpDir + "/" + dent->d_name; + std::string fullname = concat_path_file(m_sDebugDumpDir.c_str(), dent->d_name); pFileName = dent->d_name; if (IsTextFile(fullname.c_str())) @@ -548,7 +495,7 @@ bool CDebugDump::GetNextFile(std::string& pFileName, std::string& pContent, bool } else { - pContent = ""; + pContent.clear(); pIsTextFile = false; } return true; @@ -558,4 +505,3 @@ bool CDebugDump::GetNextFile(std::string& pFileName, std::string& pContent, bool m_pGetNextFileDir = NULL; return false; } - diff --git a/lib/Utils/DebugDump.h b/lib/Utils/DebugDump.h index 189b42d0..b48a386d 100644 --- a/lib/Utils/DebugDump.h +++ b/lib/Utils/DebugDump.h @@ -51,7 +51,6 @@ class CDebugDump bool m_bLocked; void SaveKernelArchitectureRelease(); - void SaveTime(); void Lock(); void UnLock(); @@ -60,18 +59,17 @@ class CDebugDump CDebugDump(); ~CDebugDump() { Close(); } - void Open(const std::string& pDir); - void Create(const std::string& pDir, int64_t uid); + void Open(const char *pDir); + void Create(const char *pDir, int64_t uid); void Delete(); void Close(); bool Exist(const char* pFileName); void LoadText(const char* pName, std::string& pData); - void LoadBinary(const char* pName, char** pData, unsigned int* pSize); - void SaveText(const char* pName, const std::string& pData); - void SaveBinary(const char* pName, const char* pData, const unsigned int pSize); + void SaveText(const char* pName, const char *pData); + void SaveBinary(const char* pName, const char* pData, unsigned pSize); void InitGetNextFile(); bool GetNextFile(std::string& pFileName, std::string& pContent, bool& pIsTextFile); diff --git a/lib/Utils/Makefile.am b/lib/Utils/Makefile.am index 68c925fd..1b141bd7 100644 --- a/lib/Utils/Makefile.am +++ b/lib/Utils/Makefile.am @@ -11,10 +11,12 @@ libABRTUtils_la_SOURCES = \ logging.cpp \ copyfd.cpp \ skip_whitespace.cpp \ + parse_release.cpp \ CrashTypesSocket.cpp \ DebugDump.h DebugDump.cpp \ CommLayerInner.h CommLayerInner.cpp \ abrt_dbus.h abrt_dbus.cpp \ + abrt_xmlrpc.h abrt_xmlrpc.cpp \ Plugin.h Plugin.cpp make_descr.cpp \ Polkit.h Polkit.cpp \ Action.h Database.h Reporter.h Analyzer.h \ @@ -30,6 +32,7 @@ libABRTUtils_la_CPPFLAGS = \ -DVAR_RUN=\"$(VAR_RUN)\" \ $(GLIB_CFLAGS) \ $(DBUS_CFLAGS) \ + $(XMLRPC_CFLAGS) $(XMLRPC_CLIENT_CFLAGS) \ $(POLKIT_CFLAGS) \ -D_GNU_SOURCE libABRTUtils_la_LDFLAGS = \ @@ -37,8 +40,10 @@ libABRTUtils_la_LDFLAGS = \ $(DL_LIBS) \ $(DBUS_LIBS) libABRTUtils_la_LIBADD = \ + $(XMLRPC_LIBS) $(XMLRPC_CLIENT_LIBS) \ $(POLKIT_LIBS) + install-data-local: $(mkdir_p) '$(DESTDIR)/$(DEBUG_DUMPS_DIR)' chmod 1777 '$(DESTDIR)/$(DEBUG_DUMPS_DIR)' diff --git a/lib/Utils/Observer.h b/lib/Utils/Observer.h index d6ec6f35..db748659 100644 --- a/lib/Utils/Observer.h +++ b/lib/Utils/Observer.h @@ -8,8 +8,8 @@ class CObserver { public: virtual ~CObserver() {} - virtual void Status(const std::string& pMessage, const char* peer, uint64_t pDest) = 0; - virtual void Warning(const std::string& pMessage, const char* peer, uint64_t pDest) = 0; + virtual void Status(const char *pMessage, const char* peer, uint64_t pDest) = 0; + virtual void Warning(const char *pMessage, const char* peer, uint64_t pDest) = 0; }; #endif diff --git a/lib/Utils/Plugin.cpp b/lib/Utils/Plugin.cpp index 161ead8a..4d561b46 100644 --- a/lib/Utils/Plugin.cpp +++ b/lib/Utils/Plugin.cpp @@ -19,9 +19,18 @@ #include "Plugin.h" +CPlugin::CPlugin() {} + /* class CPlugin's virtuals */ CPlugin::~CPlugin() {} void CPlugin::Init() {} void CPlugin::DeInit() {} -void CPlugin::SetSettings(const map_plugin_settings_t& pSettings) {} -map_plugin_settings_t CPlugin::GetSettings() {return map_plugin_settings_t();} +void CPlugin::SetSettings(const map_plugin_settings_t& pSettings) +{ + m_pSettings = pSettings; +} + +const map_plugin_settings_t& CPlugin::GetSettings() +{ + return m_pSettings; +} diff --git a/lib/Utils/Plugin.h b/lib/Utils/Plugin.h index 00c7e5be..f93f7e7b 100644 --- a/lib/Utils/Plugin.h +++ b/lib/Utils/Plugin.h @@ -47,7 +47,11 @@ */ class CPlugin { + protected: + map_plugin_settings_t m_pSettings; + public: + CPlugin(); /** * A destructor. */ @@ -69,7 +73,7 @@ class CPlugin * A method, which return current settings. It is not mandatory method. * @return Plugin's settings */ - virtual map_plugin_settings_t GetSettings(); + virtual const map_plugin_settings_t& GetSettings(); }; /** diff --git a/lib/Utils/abrt_xmlrpc.cpp b/lib/Utils/abrt_xmlrpc.cpp new file mode 100644 index 00000000..11c431b8 --- /dev/null +++ b/lib/Utils/abrt_xmlrpc.cpp @@ -0,0 +1,76 @@ +#if HAVE_CONFIG_H +# include "config.h" +#endif +#include "abrtlib.h" +#include "abrt_xmlrpc.h" +#include "ABRTException.h" + +void throw_if_xml_fault_occurred(xmlrpc_env *env) +{ + if (env->fault_occurred) + { + std::string errmsg = ssprintf("XML-RPC Fault: %s(%d)", env->fault_string, env->fault_code); + xmlrpc_env_clean(env); // this is needed ONLY if fault_occurred + xmlrpc_env_init(env); // just in case user catches ex and _continues_ to use env + error_msg("%s", errmsg.c_str()); // show error in daemon log + throw CABRTException(EXCEP_PLUGIN, errmsg); + } +} + +void abrt_xmlrpc_conn::new_xmlrpc_client(const char* url, bool no_ssl_verify) +{ + m_pClient = NULL; + m_pServer_info = NULL; + + xmlrpc_env env; + xmlrpc_env_init(&env); + + /* This should be done at program startup, once. + * We do it in abrtd's main */ + /* xmlrpc_client_setup_global_const(&env); */ + + struct xmlrpc_curl_xportparms curlParms; + memset(&curlParms, 0, sizeof(curlParms)); + /* curlParms.network_interface = NULL; - done by memset */ + curlParms.no_ssl_verifypeer = no_ssl_verify; + curlParms.no_ssl_verifyhost = no_ssl_verify; +#ifdef VERSION + curlParms.user_agent = PACKAGE_NAME"/"VERSION; +#else + curlParms.user_agent = "abrt"; +#endif + + struct xmlrpc_clientparms clientParms; + memset(&clientParms, 0, sizeof(clientParms)); + clientParms.transport = "curl"; + clientParms.transportparmsP = &curlParms; + clientParms.transportparm_size = XMLRPC_CXPSIZE(user_agent); + + xmlrpc_client_create(&env, XMLRPC_CLIENT_NO_FLAGS, + PACKAGE_NAME, VERSION, + &clientParms, XMLRPC_CPSIZE(transportparm_size), + &m_pClient); + throw_if_xml_fault_occurred(&env); + + m_pServer_info = xmlrpc_server_info_new(&env, url); + if (env.fault_occurred) + { + xmlrpc_client_destroy(m_pClient); + m_pClient = NULL; + } + throw_if_xml_fault_occurred(&env); +} + +void abrt_xmlrpc_conn::destroy_xmlrpc_client() +{ + if (m_pServer_info) + { + xmlrpc_server_info_free(m_pServer_info); + m_pServer_info = NULL; + } + if (m_pClient) + { + xmlrpc_client_destroy(m_pClient); + m_pClient = NULL; + } +} diff --git a/lib/Utils/abrt_xmlrpc.h b/lib/Utils/abrt_xmlrpc.h new file mode 100644 index 00000000..e67ab19a --- /dev/null +++ b/lib/Utils/abrt_xmlrpc.h @@ -0,0 +1,27 @@ +#ifndef ABRT_XMLRPC_H_ +#define ABRT_XMLRPC_H_ 1 + +#include <xmlrpc-c/base.h> +#include <xmlrpc-c/client.h> + +/* + * Simple class holding XMLRPC connection data. + * Used mainly to ensure we always destroy xmlrpc client and server_info + * on return or throw. + */ + +struct abrt_xmlrpc_conn { + xmlrpc_client* m_pClient; + xmlrpc_server_info* m_pServer_info; + + abrt_xmlrpc_conn(const char* url, bool no_ssl_verify) { new_xmlrpc_client(url, no_ssl_verify); } + ~abrt_xmlrpc_conn() { destroy_xmlrpc_client(); } + + void new_xmlrpc_client(const char* url, bool no_ssl_verify); + void destroy_xmlrpc_client(); +}; + +/* Utility function */ +void throw_if_xml_fault_occurred(xmlrpc_env *env); + +#endif diff --git a/lib/Utils/copyfd.cpp b/lib/Utils/copyfd.cpp index cda52b03..9abe7522 100644 --- a/lib/Utils/copyfd.cpp +++ b/lib/Utils/copyfd.cpp @@ -105,3 +105,25 @@ off_t copyfd_eof(int fd1, int fd2) { return full_fd_action(fd1, fd2, 0); } + +off_t copy_file(const char *src_name, const char *dst_name) +{ + off_t r; + int src = open(src_name, O_RDONLY); + if (src < 0) + { + perror_msg("Can't open '%s'", src_name); + return -1; + } + int dst = open(dst_name, O_WRONLY | O_TRUNC | O_CREAT, 0666); + if (dst < 0) + { + close(src); + perror_msg("Can't open '%s'", dst_name); + return -1; + } + r = copyfd_eof(src, dst); + close(src); + close(dst); + return r; +} diff --git a/lib/Utils/logging.cpp b/lib/Utils/logging.cpp index f70d23f3..cae609bc 100644 --- a/lib/Utils/logging.cpp +++ b/lib/Utils/logging.cpp @@ -7,19 +7,18 @@ #include <syslog.h> int xfunc_error_retval = EXIT_FAILURE; - int g_verbose; +int logmode = LOGMODE_STDIO; +const char *msg_prefix = ""; +const char *msg_eol = "\n"; +void (*g_custom_logger)(const char*); void xfunc_die(void) { exit(xfunc_error_retval); } -const char *msg_prefix = ""; -const char *msg_eol = "\n"; -int logmode = LOGMODE_STDIO; - -void verror_msg(const char *s, va_list p, const char* strerr) +static void verror_msg_helper(const char *s, va_list p, const char* strerr, int flags) { char *msg; int prefix_len, strerr_len, msgeol_len, used; @@ -27,9 +26,6 @@ void verror_msg(const char *s, va_list p, const char* strerr) if (!logmode) return; - if (!s) /* nomsg[_and_die] uses NULL fmt */ - s = ""; /* some libc don't like printf(NULL) */ - used = vasprintf(&msg, s, p); if (used < 0) return; @@ -51,7 +47,7 @@ void verror_msg(const char *s, va_list p, const char* strerr) memcpy(msg, msg_prefix, prefix_len); } if (strerr) { - if (s[0]) { /* not perror_nomsg? */ + if (s[0]) { msg[used++] = ':'; msg[used++] = ' '; } @@ -60,24 +56,26 @@ void verror_msg(const char *s, va_list p, const char* strerr) } strcpy(&msg[used], msg_eol); - if (logmode & LOGMODE_STDIO) { + if (flags & LOGMODE_STDIO) { fflush(stdout); full_write(STDERR_FILENO, msg, used + msgeol_len); } - if (logmode & LOGMODE_SYSLOG) { + if (flags & LOGMODE_SYSLOG) { syslog(LOG_ERR, "%s", msg + prefix_len); } + if ((flags & LOGMODE_CUSTOM) && g_custom_logger) { + g_custom_logger(msg + prefix_len); + } free(msg); } -void error_msg_and_die(const char *s, ...) +void log_msg(const char *s, ...) { va_list p; va_start(p, s); - verror_msg(s, p, NULL); + verror_msg_helper(s, p, NULL, logmode); va_end(p); - xfunc_die(); } void error_msg(const char *s, ...) @@ -85,8 +83,18 @@ void error_msg(const char *s, ...) va_list p; va_start(p, s); - verror_msg(s, p, NULL); + verror_msg_helper(s, p, NULL, (logmode | LOGMODE_CUSTOM)); + va_end(p); +} + +void error_msg_and_die(const char *s, ...) +{ + va_list p; + + va_start(p, s); + verror_msg_helper(s, p, NULL, (logmode | LOGMODE_CUSTOM)); va_end(p); + xfunc_die(); } void perror_msg_and_die(const char *s, ...) @@ -95,7 +103,7 @@ void perror_msg_and_die(const char *s, ...) va_start(p, s); /* Guard against "<error message>: Success" */ - verror_msg(s, p, errno ? strerror(errno) : NULL); + verror_msg_helper(s, p, errno ? strerror(errno) : NULL, (logmode | LOGMODE_CUSTOM)); va_end(p); xfunc_die(); } @@ -106,7 +114,7 @@ void perror_msg(const char *s, ...) va_start(p, s); /* Guard against "<error message>: Success" */ - verror_msg(s, p, errno ? strerror(errno) : NULL); + verror_msg_helper(s, p, errno ? strerror(errno) : NULL, (logmode | LOGMODE_CUSTOM)); va_end(p); } @@ -122,5 +130,5 @@ void simple_perror_msg(const char *s) void die_out_of_memory(void) { - error_msg_and_die("Out of memory, exiting"); + error_msg_and_die("Out of memory, exiting"); } diff --git a/lib/Utils/parse_release.cpp b/lib/Utils/parse_release.cpp new file mode 100644 index 00000000..33d3edb1 --- /dev/null +++ b/lib/Utils/parse_release.cpp @@ -0,0 +1,38 @@ +#include "abrtlib.h" +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +using namespace std; + +void parse_release(const char *pRelease, string& pProduct, string& pVersion) +{ + if (strstr(pRelease, "Rawhide")) + { + pProduct = "Fedora"; + pVersion = "rawhide"; + return; + } + if (strstr(pRelease, "Fedora")) + { + pProduct = "Fedora"; + } + else if (strstr(pRelease, "Red Hat Enterprise Linux")) + { + pProduct = "Red Hat Enterprise Linux "; + } + + const char *release = strstr(pRelease, "release"); + const char *space = release ? strchr(release, ' ') : NULL; + + if (space++) while (*space != '\0' && *space != ' ') + { + /* Eat string like "5.2" */ + pVersion += *space; + if (pProduct == "Red Hat Enterprise Linux ") + { + pProduct += *space; + } + space++; + } +} diff --git a/lib/Utils/xfuncs.cpp b/lib/Utils/xfuncs.cpp index 533fbfa8..97c2f763 100644 --- a/lib/Utils/xfuncs.cpp +++ b/lib/Utils/xfuncs.cpp @@ -355,3 +355,16 @@ std::string concat_path_file(const char *path, const char *filename) lc = last_char_is(path, '/'); return ssprintf("%s%s%s", path, (lc==NULL ? "/" : ""), filename); } + +bool string_to_bool(const char *s) +{ + if (s[0] == '1' && s[1] == '\0') + return true; + if (strcasecmp(s, "on") == 0) + return true; + if (strcasecmp(s, "yes") == 0) + return true; + if (strcasecmp(s, "true") == 0) + return true; + return false; +} |
