diff options
Diffstat (limited to 'src/Daemon')
-rw-r--r-- | src/Daemon/CommLayerServer.h | 2 | ||||
-rw-r--r-- | src/Daemon/CommLayerServerDBus.cpp | 53 | ||||
-rw-r--r-- | src/Daemon/CommLayerServerDBus.h | 2 | ||||
-rw-r--r-- | src/Daemon/CommLayerServerSocket.cpp | 23 | ||||
-rw-r--r-- | src/Daemon/CrashWatcher.cpp | 66 | ||||
-rw-r--r-- | src/Daemon/CrashWatcher.h | 8 | ||||
-rw-r--r-- | src/Daemon/Daemon.cpp | 351 | ||||
-rw-r--r-- | src/Daemon/Daemon.h | 2 | ||||
-rw-r--r-- | src/Daemon/Makefile.am | 6 | ||||
-rw-r--r-- | src/Daemon/MiddleWare.cpp | 194 | ||||
-rw-r--r-- | src/Daemon/MiddleWare.h | 45 | ||||
-rw-r--r-- | src/Daemon/PluginManager.cpp | 5 | ||||
-rw-r--r-- | src/Daemon/Settings.cpp | 52 | ||||
-rwxr-xr-x | src/Daemon/abrt-debuginfo-install | 144 | ||||
-rw-r--r-- | src/Daemon/abrt.conf | 17 | ||||
-rw-r--r-- | src/Daemon/com.redhat.abrt.service | 3 |
16 files changed, 553 insertions, 420 deletions
diff --git a/src/Daemon/CommLayerServer.h b/src/Daemon/CommLayerServer.h index 6ede5815..21c1b304 100644 --- a/src/Daemon/CommLayerServer.h +++ b/src/Daemon/CommLayerServer.h @@ -13,7 +13,7 @@ class CCommLayerServer { virtual ~CCommLayerServer(); /* just stubs to be called when not implemented in specific comm layer */ - virtual void Crash(const std::string& progname, const std::string& uid) {} + virtual void Crash(const char *progname, const char *uid_str) {} virtual void JobDone(const char* pDest, const char* pUUID) = 0; virtual void QuotaExceed(const char* str) {} diff --git a/src/Daemon/CommLayerServerDBus.cpp b/src/Daemon/CommLayerServerDBus.cpp index cc98fc2c..ed7e3858 100644 --- a/src/Daemon/CommLayerServerDBus.cpp +++ b/src/Daemon/CommLayerServerDBus.cpp @@ -28,7 +28,7 @@ static DBusMessage* new_signal_msg(const char* member, const char* peer = NULL) { /* path, interface, member name */ - DBusMessage* msg = dbus_message_new_signal(CC_DBUS_PATH, CC_DBUS_IFACE, member); + DBusMessage* msg = dbus_message_new_signal(ABRTD_DBUS_PATH, ABRTD_DBUS_IFACE, member); if (!msg) die_out_of_memory(); /* Send unicast dbus signal if peer is known */ @@ -46,16 +46,24 @@ static void send_flush_and_unref(DBusMessage* msg) } /* Notify the clients (UI) about a new crash */ -void CCommLayerServerDBus::Crash(const std::string& progname, const std::string& uid) +void CCommLayerServerDBus::Crash(const char *progname, const char *uid_str) { DBusMessage* msg = new_signal_msg("Crash"); - const char* c_progname = progname.c_str(); - const char* c_uid = uid.c_str(); - dbus_message_append_args(msg, - DBUS_TYPE_STRING, &c_progname, - DBUS_TYPE_STRING, &c_uid, - DBUS_TYPE_INVALID); - VERB2 log("Sending signal Crash('%s','%s')", c_progname, c_uid); + if (uid_str) + { + dbus_message_append_args(msg, + DBUS_TYPE_STRING, &progname, + DBUS_TYPE_STRING, &uid_str, + DBUS_TYPE_INVALID); + VERB2 log("Sending signal Crash('%s','%s')", progname, uid_str); + } + else + { + dbus_message_append_args(msg, + DBUS_TYPE_STRING, &progname, + DBUS_TYPE_INVALID); + VERB2 log("Sending signal Crash('%s')", progname); + } send_flush_and_unref(msg); } @@ -127,7 +135,7 @@ static long get_remote_uid(DBusMessage* call, const char** ppSender = NULL) static int handle_GetCrashInfos(DBusMessage* call, DBusMessage* reply) { long unix_uid = get_remote_uid(call); - vector_crash_infos_t argout1 = GetCrashInfos(to_string(unix_uid)); + vector_crash_infos_t argout1 = GetCrashInfos(to_string(unix_uid).c_str()); DBusMessageIter iter; dbus_message_iter_init_append(reply, &iter); @@ -246,16 +254,14 @@ static int handle_Report(DBusMessage* call, DBusMessage* reply) } } - const char * sender = dbus_message_get_sender(call); + //const char * sender = dbus_message_get_sender(call); if (!user_conf_data.empty()) { std::string PluginName; - map_plugin_settings_t plugin_settings; map_map_string_t::const_iterator it_user_conf_data = user_conf_data.begin(); for (; it_user_conf_data != user_conf_data.end(); it_user_conf_data++) { PluginName = it_user_conf_data->first; - plugin_settings = it_user_conf_data->second; #if DEBUG std::cout << "plugin name: " << it_user_conf_data->first; map_string_t::const_iterator it_plugin_config; @@ -266,21 +272,21 @@ static int handle_Report(DBusMessage* call, DBusMessage* reply) std::cout << " key: " << it_plugin_config->first << " value: " << it_plugin_config->second << std::endl; } #endif - g_pPluginManager->SetPluginSettings(PluginName, sender, plugin_settings); + // this would overwrite the default settings + //g_pPluginManager->SetPluginSettings(PluginName, sender, plugin_settings); } } -//so far, user_conf_data is unused long unix_uid = get_remote_uid(call); report_status_t argout1; try { - argout1 = Report(argin1, to_string(unix_uid)); + argout1 = Report(argin1, user_conf_data, to_string(unix_uid).c_str()); } catch (CABRTException &e) { dbus_message_unref(reply); - reply = dbus_message_new_error(call, DBUS_ERROR_FAILED, e.what().c_str()); + reply = dbus_message_new_error(call, DBUS_ERROR_FAILED, e.what()); if (!reply) die_out_of_memory(); send_flush_and_unref(reply); @@ -309,7 +315,7 @@ static int handle_DeleteDebugDump(DBusMessage* call, DBusMessage* reply) } long unix_uid = get_remote_uid(call); - bool argout1 = DeleteDebugDump(argin1, to_string(unix_uid)); + bool argout1 = DeleteDebugDump(argin1, to_string(unix_uid).c_str()); dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &argout1, @@ -377,7 +383,12 @@ static int handle_SetPluginSettings(DBusMessage* call, DBusMessage* reply) long unix_uid = get_remote_uid(call); VERB1 log("got %s('%s',...) call from uid %ld", "SetPluginSettings", PluginName.c_str(), unix_uid); - g_pPluginManager->SetPluginSettings(PluginName, to_string(unix_uid), plugin_settings); + /* Disabled, as we don't use it, we use only temporary user settings while reporting + this method should be used to change the default setting and thus should + be protected by polkit + */ + //FIXME: protect with polkit +// g_pPluginManager->SetPluginSettings(PluginName, to_string(unix_uid), plugin_settings); send_flush_and_unref(reply); return 0; @@ -534,7 +545,7 @@ static void handle_dbus_err(bool error_flag, DBusError *err) error_msg_and_die( "Error requesting DBus name %s, possible reasons: " "abrt run by non-root; dbus config is incorrect", - CC_DBUS_NAME); + ABRTD_DBUS_NAME); } CCommLayerServerDBus::CCommLayerServerDBus() @@ -550,7 +561,7 @@ CCommLayerServerDBus::CCommLayerServerDBus() attach_dbus_conn_to_glib_main_loop(conn, "/com/redhat/abrt", message_received); VERB3 log("dbus_bus_request_name"); - int rc = dbus_bus_request_name(conn, CC_DBUS_NAME, DBUS_NAME_FLAG_REPLACE_EXISTING, &err); + int rc = dbus_bus_request_name(conn, ABRTD_DBUS_NAME, DBUS_NAME_FLAG_REPLACE_EXISTING, &err); //maybe check that r == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER instead? handle_dbus_err(rc < 0, &err); VERB3 log("dbus init done"); diff --git a/src/Daemon/CommLayerServerDBus.h b/src/Daemon/CommLayerServerDBus.h index 7b2e31d7..f159c732 100644 --- a/src/Daemon/CommLayerServerDBus.h +++ b/src/Daemon/CommLayerServerDBus.h @@ -11,7 +11,7 @@ class CCommLayerServerDBus virtual ~CCommLayerServerDBus(); /* DBus signal senders */ - virtual void Crash(const std::string& progname, const std::string& uid); + virtual void Crash(const char *progname, const char *uid_str); virtual void JobDone(const char* pDest, const char* pUUID); virtual void QuotaExceed(const char* str); diff --git a/src/Daemon/CommLayerServerSocket.cpp b/src/Daemon/CommLayerServerSocket.cpp index 6b62928b..ee775c6d 100644 --- a/src/Daemon/CommLayerServerSocket.cpp +++ b/src/Daemon/CommLayerServerSocket.cpp @@ -26,7 +26,7 @@ void CCommLayerServerSocket::Send(const std::string& pData, GIOChannel *pDestina ret = g_io_channel_write_chars(pDestination, message + offset, strlen(message + offset), &len, &err); if (ret == G_IO_STATUS_ERROR) { - warn_client("Error during sending data."); + error_msg("Error during sending data"); } } @@ -72,7 +72,7 @@ gboolean CCommLayerServerSocket::client_socket_cb(GIOChannel *source, GIOConditi ret = g_io_channel_read_chars(source, buff, 1, &len, &err); if (ret == G_IO_STATUS_ERROR) { - warn_client(std::string("Error while reading data from client socket: ") + err->message); + error_msg("Error while reading data from client socket: %s", err->message); return FALSE; } message += buff[0]; @@ -101,13 +101,13 @@ gboolean CCommLayerServerSocket::server_socket_cb(GIOChannel *source, GIOConditi condition & G_IO_ERR || condition & G_IO_NVAL) { - warn_client("Server socket error."); + error_msg("Server socket error"); return FALSE; } if ((socket = accept(serverSocket->m_nSocket, (struct sockaddr *)&remote, &len)) == -1) { - warn_client("Server can not accept client."); + error_msg("Server can not accept client"); return TRUE; } log("New socket client connected"); @@ -117,7 +117,7 @@ gboolean CCommLayerServerSocket::server_socket_cb(GIOChannel *source, GIOConditi static_cast<GIOFunc>(client_socket_cb), data)) { - warn_client("Can not init g_io_channel."); + error_msg("Can not init g_io_channel"); return TRUE; } serverSocket->m_mapClientChannels[socket] = gSocket; @@ -138,7 +138,9 @@ void CCommLayerServerSocket::ProcessMessage(const std::string& pMessage, GIOChan { std::string message = pMessage.substr(sizeof(MESSAGE_REPORT) - 1); map_crash_report_t report = string_to_crash_report(message); - Report(report, UID); + map_plugin_settings_t plugin_settings; + //FIXME: another hack to make this compile +// Report(report, plugin_settings, UID); } else if (!strncmp(pMessage.c_str(), MESSAGE_CREATE_REPORT, sizeof(MESSAGE_CREATE_REPORT) - 1)) { @@ -155,7 +157,7 @@ void CCommLayerServerSocket::ProcessMessage(const std::string& pMessage, GIOChan } else { - warn_client("Received unknown message type."); + error_msg("Received unknown message type"); } } @@ -227,7 +229,12 @@ vector_crash_infos_t CCommLayerServerSocket::GetCrashInfos(const std::string &pS report_status_t CCommLayerServerSocket::Report(const map_crash_report_t& pReport, const std::string& pSender) { report_status_t rs; - rs = ::Report(pReport, pSender); + //FIXME: a hack to make this compile, but we don't use sockets anyway + /* we could probably remove the sockets and rely only on dbus, + as it will become mandatory even on servers, but this needs some investigation + and more opinions + */ + //rs = ::Report(pReport, pSettings, pSender); return rs; } diff --git a/src/Daemon/CrashWatcher.cpp b/src/Daemon/CrashWatcher.cpp index 94fb9d79..e684277c 100644 --- a/src/Daemon/CrashWatcher.cpp +++ b/src/Daemon/CrashWatcher.cpp @@ -22,16 +22,16 @@ #include "ABRTException.h" #include "CrashWatcher.h" -void CCrashWatcher::Status(const std::string& pMessage, const char* peer, uint64_t pJobID) +void CCrashWatcher::Status(const char *pMessage, const char* peer, uint64_t pJobID) { - VERB1 log("Update('%s'): %s", peer, pMessage.c_str()); + VERB1 log("Update('%s'): %s", peer, pMessage); if (g_pCommLayer != NULL) g_pCommLayer->Update(pMessage, peer, pJobID); } -void CCrashWatcher::Warning(const std::string& pMessage, const char* peer, uint64_t pJobID) +void CCrashWatcher::Warning(const char *pMessage, const char* peer, uint64_t pJobID) { - VERB1 log("Warning('%s'): %s", peer, pMessage.c_str()); + VERB1 log("Warning('%s'): %s", peer, pMessage); if (g_pCommLayer != NULL) g_pCommLayer->Warning(pMessage, peer, pJobID); } @@ -44,7 +44,7 @@ CCrashWatcher::~CCrashWatcher() { } -vector_crash_infos_t GetCrashInfos(const std::string &pUID) +vector_crash_infos_t GetCrashInfos(const char *pUID) { vector_crash_infos_t retval; log("Getting crash infos..."); @@ -58,25 +58,24 @@ vector_crash_infos_t GetCrashInfos(const std::string &pUID) { mw_result_t res; map_crash_info_t info; + const char *uuid = UUIDsUIDs[ii].first.c_str(); + const char *uid = UUIDsUIDs[ii].second.c_str(); - res = GetCrashInfo(UUIDsUIDs[ii].first, UUIDsUIDs[ii].second, info); + res = GetCrashInfo(uuid, uid, info); switch (res) { case MW_OK: retval.push_back(info); break; case MW_ERROR: - warn_client("Can not find debug dump directory for UUID: " + UUIDsUIDs[ii].first + ", deleting from database"); - update_client("Can not find debug dump directory for UUID: " + UUIDsUIDs[ii].first + ", deleting from database"); - DeleteCrashInfo(UUIDsUIDs[ii].first, UUIDsUIDs[ii].second); + error_msg("Can't find dump directory for UUID %s, deleting from database", uuid); + DeleteCrashInfo(uuid, uid); break; case MW_FILE_ERROR: + error_msg("Can't open file in dump directory for UUID %s, deleting", uuid); { - std::string debugDumpDir; - warn_client("Can not open file in debug dump directory for UUID: " + UUIDsUIDs[ii].first + ", deleting"); - update_client("Can not open file in debug dump directory for UUID: " + UUIDsUIDs[ii].first + ", deleting"); - debugDumpDir = DeleteCrashInfo(UUIDsUIDs[ii].first, UUIDsUIDs[ii].second); - DeleteDebugDumpDir(debugDumpDir); + std::string debugDumpDir = DeleteCrashInfo(uuid, uid); + DeleteDebugDumpDir(debugDumpDir.c_str()); } break; default: @@ -90,8 +89,7 @@ vector_crash_infos_t GetCrashInfos(const std::string &pUID) { throw e; } - warn_client(e.what()); - update_client(e.what()); + error_msg("%s", e.what()); } //retval = GetCrashInfos(pUID); @@ -124,17 +122,17 @@ map_crash_report_t GetJobResult(const char* pUUID, const char* pUID, int force) case MW_OK: break; case MW_IN_DB_ERROR: - warn_client(std::string("Did not find crash with UUID ") + pUUID + " in database"); + error_msg("Can't find crash with UUID %s in database", pUUID); break; case MW_PLUGIN_ERROR: - warn_client("Particular analyzer plugin isn't loaded or there is an error within plugin(s)"); + error_msg("Particular analyzer plugin isn't loaded or there is an error within plugin(s)"); break; case MW_CORRUPTED: case MW_FILE_ERROR: default: - warn_client(std::string("Corrupted crash with UUID ") + pUUID + ", deleting"); + error_msg("Corrupted crash with UUID %s, deleting", pUUID); std::string debugDumpDir = DeleteCrashInfo(pUUID, pUID); - DeleteDebugDumpDir(debugDumpDir); + DeleteDebugDumpDir(debugDumpDir.c_str()); break; } return crashReport; @@ -163,18 +161,9 @@ static void* create_report(void* arg) } catch (CABRTException& e) { - if (e.type() == EXCEP_FATAL) - { - set_client_name(NULL); - /* free strduped strings */ - free(thread_data->UUID); - free(thread_data->UID); - free(thread_data->peer); - free(thread_data); - throw e; - } - warn_client(e.what()); + error_msg("%s", e.what()); } + catch (...) {} set_client_name(NULL); /* free strduped strings */ @@ -193,10 +182,12 @@ int CreateReportThread(const char* pUUID, const char* pUID, int force, const cha thread_data->UID = xstrdup(pUID); thread_data->force = force; thread_data->peer = xstrdup(pSender); + //TODO: do we need this? //pthread_attr_t attr; //pthread_attr_init(&attr); //pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + int r = pthread_create(&thread_data->thread_id, NULL, create_report, thread_data); if (r != 0) { @@ -208,21 +199,19 @@ int CreateReportThread(const char* pUUID, const char* pUID, int force, const cha * or ulimit is exceeded (someone floods us with CreateReport() dbus calls?) */ error_msg("Can't create thread"); + return r; } - else - { - VERB3 log("Thread %llx created", (unsigned long long)thread_data->thread_id); - } + VERB3 log("Thread %llx created", (unsigned long long)thread_data->thread_id); //pthread_attr_destroy(&attr); return r; } -bool DeleteDebugDump(const std::string& pUUID, const std::string& pUID) +bool DeleteDebugDump(const char *pUUID, const char *pUID) { try { std::string debugDumpDir = DeleteCrashInfo(pUUID, pUID); - DeleteDebugDumpDir(debugDumpDir); + DeleteDebugDumpDir(debugDumpDir.c_str()); } catch (CABRTException& e) { @@ -230,8 +219,7 @@ bool DeleteDebugDump(const std::string& pUUID, const std::string& pUID) { throw e; } - warn_client(e.what()); - update_client(e.what()); + error_msg("%s", e.what()); return false; } return true; diff --git a/src/Daemon/CrashWatcher.h b/src/Daemon/CrashWatcher.h index d8c7c28a..995d2a12 100644 --- a/src/Daemon/CrashWatcher.h +++ b/src/Daemon/CrashWatcher.h @@ -44,13 +44,13 @@ class CCrashWatcher public: /* Observer methods */ - virtual void Status(const std::string& pMessage, const char* peer, uint64_t pJobID); - virtual void Warning(const std::string& pMessage, const char* peer, uint64_t pJobID); + virtual void Status(const char *pMessage, const char* peer, uint64_t pJobID); + virtual void Warning(const char *pMessage, const char* peer, uint64_t pJobID); }; -vector_crash_infos_t GetCrashInfos(const std::string &pUID); +vector_crash_infos_t GetCrashInfos(const char *pUID); int CreateReportThread(const char* pUUID, const char* pUID, int force, const char* pSender); map_crash_report_t GetJobResult(const char* pUUID, const char* pUID, int force); -bool DeleteDebugDump(const std::string& pUUID, const std::string& pUID); +bool DeleteDebugDump(const char *pUUID, const char *pUID); #endif /*CRASHWATCHER_H_*/ diff --git a/src/Daemon/Daemon.cpp b/src/Daemon/Daemon.cpp index d1ab188e..67e72cca 100644 --- a/src/Daemon/Daemon.cpp +++ b/src/Daemon/Daemon.cpp @@ -18,10 +18,14 @@ */ #include <syslog.h> -#include <sys/inotify.h> -#include <glib.h> #include <pthread.h> +#include <resolv.h> /* res_init */ #include <string> +#include <limits.h> +#include <sys/inotify.h> +#include <xmlrpc-c/base.h> +#include <xmlrpc-c/client.h> +#include <glib.h> #if HAVE_CONFIG_H #include <config.h> #endif @@ -105,24 +109,14 @@ typedef struct cron_callback_data_t } cron_callback_data_t; -static uint8_t s_sig_caught; -static GMainLoop* g_pMainloop; +static uint8_t s_sig_caught; /* must be one byte */ +static int s_signal_pipe[2]; +static int s_signal_pipe_write = -1; +static unsigned s_timeout; +static bool s_exiting; CCommLayerServer* g_pCommLayer; -pthread_mutex_t g_pJobsMutex; - - -/* Is it "." or ".."? */ -/* abrtlib candidate */ -static bool dot_or_dotdot(const char *filename) -{ - if (filename[0] != '.') return false; - if (filename[1] == '\0') return true; - if (filename[1] != '.') return false; - if (filename[2] == '\0') return true; - return false; -} static double GetDirSize(const std::string &pPath, std::string *worst_dir = NULL, const char *excluded = NULL) { @@ -171,6 +165,18 @@ static double GetDirSize(const std::string &pPath, std::string *worst_dir = NULL return size; } +static bool analyzer_has_InformAllUsers(const char *analyzer_name) +{ + CAnalyzer* analyzer = g_pPluginManager->GetAnalyzer(analyzer_name); + if (!analyzer) + return false; + map_plugin_settings_t settings = analyzer->GetSettings(); + map_plugin_settings_t::const_iterator it = settings.find("InformAllUsers"); + if (it == settings.end()) + return false; + return string_to_bool(it->second.c_str()); +} + static void cron_delete_callback_data_cb(gpointer data) { cron_callback_data_t* cronDeleteCallbackData = static_cast<cron_callback_data_t*>(data); @@ -182,8 +188,9 @@ static gboolean cron_activation_periodic_cb(gpointer data) cron_callback_data_t* cronPeriodicCallbackData = static_cast<cron_callback_data_t*>(data); VERB1 log("Activating plugin: %s", cronPeriodicCallbackData->m_sPluginName.c_str()); RunAction(DEBUG_DUMPS_DIR, - cronPeriodicCallbackData->m_sPluginName, - cronPeriodicCallbackData->m_sPluginArgs); + cronPeriodicCallbackData->m_sPluginName.c_str(), + cronPeriodicCallbackData->m_sPluginArgs.c_str() + ); return TRUE; } static gboolean cron_activation_one_cb(gpointer data) @@ -191,8 +198,9 @@ static gboolean cron_activation_one_cb(gpointer data) cron_callback_data_t* cronOneCallbackData = static_cast<cron_callback_data_t*>(data); VERB1 log("Activating plugin: %s", cronOneCallbackData->m_sPluginName.c_str()); RunAction(DEBUG_DUMPS_DIR, - cronOneCallbackData->m_sPluginName, - cronOneCallbackData->m_sPluginArgs); + cronOneCallbackData->m_sPluginName.c_str(), + cronOneCallbackData->m_sPluginArgs.c_str() + ); return FALSE; } static gboolean cron_activation_reshedule_cb(gpointer data) @@ -206,7 +214,8 @@ static gboolean cron_activation_reshedule_cb(gpointer data) cronPeriodicCallbackData->m_nTimeout, cron_activation_periodic_cb, static_cast<gpointer>(cronPeriodicCallbackData), - cron_delete_callback_data_cb); + cron_delete_callback_data_cb + ); return FALSE; } @@ -232,7 +241,7 @@ static void SetUpMW() vector_pair_string_string_t::iterator it_ar = g_settings_vectorActionsAndReporters.begin(); for (; it_ar != g_settings_vectorActionsAndReporters.end(); it_ar++) { - AddActionOrReporter(it_ar->first, it_ar->second); + AddActionOrReporter(it_ar->first.c_str(), it_ar->second.c_str()); } VERB1 log("Adding analyzers, actions or reporters"); map_analyzer_actions_and_reporters_t::iterator it_aar = g_settings_mapAnalyzerActionsAndReporters.begin(); @@ -241,7 +250,7 @@ static void SetUpMW() vector_pair_string_string_t::iterator it_ar = it_aar->second.begin(); for (; it_ar != it_aar->second.end(); it_ar++) { - AddAnalyzerActionOrReporter(it_aar->first, it_ar->first, it_ar->second); + AddAnalyzerActionOrReporter(it_aar->first.c_str(), it_ar->first.c_str(), it_ar->second.c_str()); } } } @@ -322,13 +331,13 @@ static int SetUpCron() vector_pair_string_string_t::iterator it_ar = it_c->second.begin(); for (; it_ar != it_c->second.end(); it_ar++) { - cron_callback_data_t* cronOneCallbackData = new cron_callback_data_t((*it_ar).first, (*it_ar).second, timeout); + cron_callback_data_t* cronOneCallbackData = new cron_callback_data_t(it_ar->first, it_ar->second, timeout); g_timeout_add_seconds_full(G_PRIORITY_DEFAULT, timeout, cron_activation_one_cb, static_cast<gpointer>(cronOneCallbackData), cron_delete_callback_data_cb); - cron_callback_data_t* cronResheduleCallbackData = new cron_callback_data_t((*it_ar).first, (*it_ar).second, 24 * 60 * 60); + cron_callback_data_t* cronResheduleCallbackData = new cron_callback_data_t(it_ar->first, it_ar->second, 24 * 60 * 60); g_timeout_add_seconds_full(G_PRIORITY_DEFAULT, timeout, cron_activation_reshedule_cb, @@ -375,13 +384,12 @@ static void FindNewDumps(const char* pPath) map_crash_info_t crashinfo; try { - mw_result_t res; - res = SaveDebugDump(*itt, crashinfo); + mw_result_t res = SaveDebugDump(itt->c_str(), crashinfo); switch (res) { case MW_OK: VERB1 log("Saving into database (%s)", itt->c_str()); - RunActionsAndReporters(crashinfo[CD_MWDDD][CD_CONTENT]); + RunActionsAndReporters(crashinfo[CD_MWDDD][CD_CONTENT].c_str()); break; case MW_IN_DB: VERB1 log("Already saved in database (%s)", itt->c_str()); @@ -397,7 +405,7 @@ static void FindNewDumps(const char* pPath) //Perhaps corrupted & bad needs to be logged unconditionally, //already saved one - only on VERB1 VERB1 log("Corrupted, bad or already saved crash, deleting"); - DeleteDebugDumpDir(*itt); + DeleteDebugDumpDir(itt->c_str()); break; } } @@ -407,7 +415,7 @@ static void FindNewDumps(const char* pPath) { throw e; } - error_msg("%s", e.what().c_str()); + error_msg("%s", e.what()); } } } @@ -453,63 +461,44 @@ static int Lock() /* we leak opened lfd intentionally */ } -static void handle_fatal_signal(int signal) +static void handle_fatal_signal(int signo) { - s_sig_caught = signal; + s_sig_caught = signo; + VERB3 log("Got signal %d", signo); + if (s_signal_pipe_write >= 0) + write(s_signal_pipe_write, &s_sig_caught, 1); } -/* One of our event sources is s_sig_caught when it becomes != 0. - * glib machinery we need to hook it up to the main loop: - * prepare(): - * If the source can determine that it is ready here (without waiting - * for the results of the poll() call) it should return TRUE. It can also - * return a timeout_ value which should be the maximum timeout (in milliseconds) - * which should be passed to the poll() call. - * check(): - * Called after all the file descriptors are polled. The source should - * return TRUE if it is ready to be dispatched. - * dispatch(): - * Called to dispatch the event source, after it has returned TRUE - * in either its prepare or its check function. The dispatch function - * is passed in a callback function and data. The callback function - * may be NULL if the source was never connected to a callback using - * g_source_set_callback(). The dispatch function should - * call the callback function with user_data and whatever additional - * parameters are needed for this type of event source. - */ -static gboolean waitsignal_prepare(GSource *source, gint *timeout_) +/* Signal pipe handler */ +static gboolean handle_signal_cb(GIOChannel *gio, GIOCondition condition, gpointer ptr_unused) { - /* We depend on the fact that in Unix, poll() is interrupted - * by caught signals (in returns EINTR). Thus we do not need to set - * a small timeout here: infinite timeout (-1) works too */ - *timeout_ = -1; - return s_sig_caught != 0; -} -static gboolean waitsignal_check(GSource *source) -{ - return s_sig_caught != 0; -} -static gboolean waitsignal_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) -{ - g_main_quit(g_pMainloop); - return 1; + char signo; + gsize len = 0; + g_io_channel_read(gio, &signo, 1, &len); + if (len == 1) + { + /* we did receive a signal */ + VERB3 log("Got signal %d through signal pipe", signo); + s_exiting = 1; + return TRUE; + } + return FALSE; } /* Inotify handler */ -static gboolean handle_event_cb(GIOChannel *gio, GIOCondition condition, gpointer ptr_unused) +static gboolean handle_inotify_cb(GIOChannel *gio, GIOCondition condition, gpointer ptr_unused) { /* 128 simultaneous actions */ #define INOTIFY_BUFF_SIZE ((sizeof(struct inotify_event) + FILENAME_MAX)*128) - GIOError err; - char *buf = new char[INOTIFY_BUFF_SIZE]; + char *buf = (char*)xmalloc(INOTIFY_BUFF_SIZE); gsize len; gsize i = 0; errno = 0; - err = g_io_channel_read(gio, buf, INOTIFY_BUFF_SIZE, &len); + GIOError err = g_io_channel_read(gio, buf, INOTIFY_BUFF_SIZE, &len); if (err != G_IO_ERROR_NONE) { perror_msg("Error reading inotify fd"); - delete[] buf; + free(buf); return FALSE; } /* reconstruct each event and send message to the dbus */ @@ -540,29 +529,34 @@ static gboolean handle_event_cb(GIOChannel *gio, GIOCondition condition, gpointe ) { log("Size of '%s' >= %u MB, deleting '%s'", DEBUG_DUMPS_DIR, g_settings_nMaxCrashReportsSize, worst_dir.c_str()); g_pCommLayer->QuotaExceed(_("Report size exceeded the quota. Please check system's MaxCrashReportsSize value in abrt.conf.")); - DeleteDebugDumpDir(std::string(DEBUG_DUMPS_DIR) + "/" + worst_dir); + DeleteDebugDumpDir(concat_path_file(DEBUG_DUMPS_DIR, worst_dir.c_str()).c_str()); worst_dir = ""; } map_crash_info_t crashinfo; try { - mw_result_t res; - res = SaveDebugDump(std::string(DEBUG_DUMPS_DIR) + "/" + name, crashinfo); + std::string fullname = concat_path_file(DEBUG_DUMPS_DIR, name); + + mw_result_t res = SaveDebugDump(fullname.c_str(), crashinfo); switch (res) { case MW_OK: - log("New crash, saving..."); - RunActionsAndReporters(crashinfo[CD_MWDDD][CD_CONTENT]); - /* Send dbus signal */ - g_pCommLayer->Crash(crashinfo[CD_PACKAGE][CD_CONTENT], crashinfo[CD_UID][CD_CONTENT]); - break; + log("New crash, saving"); + RunActionsAndReporters(crashinfo[CD_MWDDD][CD_CONTENT].c_str()); + /* Fall through to "send dbus signal" */ case MW_REPORTED: case MW_OCCURED: - log("Already saved crash, deleting..."); + if (res != MW_OK) + log("Already saved crash, just sending dbus signal"); /* Send dbus signal */ - g_pCommLayer->Crash(crashinfo[CD_PACKAGE][CD_CONTENT], crashinfo[CD_UID][CD_CONTENT]); - DeleteDebugDumpDir(std::string(DEBUG_DUMPS_DIR) + "/" + name); + { + const char *uid_str = analyzer_has_InformAllUsers(crashinfo[CD_MWANALYZER][CD_CONTENT].c_str()) + ? NULL + : crashinfo[CD_UID][CD_CONTENT].c_str(); + g_pCommLayer->Crash(crashinfo[CD_PACKAGE][CD_CONTENT].c_str(), uid_str); + } + //DeleteDebugDumpDir(fullname.c_str()); break; case MW_BLACKLISTED: case MW_CORRUPTED: @@ -571,31 +565,96 @@ static gboolean handle_event_cb(GIOChannel *gio, GIOCondition condition, gpointe case MW_IN_DB: case MW_FILE_ERROR: default: - log("Corrupted or bad crash, deleting..."); - DeleteDebugDumpDir(std::string(DEBUG_DUMPS_DIR) + "/" + name); + log("Corrupted or bad crash, deleting"); + DeleteDebugDumpDir(fullname.c_str()); break; } } catch (CABRTException& e) { - warn_client(e.what()); + error_msg(e.what()); if (e.type() == EXCEP_FATAL) { - delete[] buf; + free(buf); return -1; } } catch (...) { - delete[] buf; + free(buf); throw; } } /* while */ - delete[] buf; + free(buf); return TRUE; } +/* Run main loop with idle timeout. + * Basically, almost like glib's g_main_run(loop) + */ +static void run_main_loop(GMainLoop* loop) +{ + GMainContext *context = g_main_loop_get_context(loop); + time_t old_time = 0; + time_t dns_conf_hash = 0; + + while (!s_exiting) + { + /* we have just a handful of sources, 32 should be ample */ + const unsigned NUM_POLLFDS = 32; + GPollFD fds[NUM_POLLFDS]; + gboolean some_ready; + gint max_priority; + gint timeout; + + some_ready = g_main_context_prepare(context, &max_priority); + if (some_ready) + g_main_context_dispatch(context); + + gint nfds = g_main_context_query(context, max_priority, &timeout, fds, NUM_POLLFDS); + if (nfds > NUM_POLLFDS) + error_msg_and_die("Internal error"); + + if (s_timeout) + alarm(s_timeout); + g_poll(fds, nfds, timeout); + if (s_timeout) + alarm(0); + + /* res_init() makes glibc reread /etc/resolv.conf. + * I'd think libc should be clever enough to do it itself + * at every name resolution attempt, but no... + * We need to guess ourself whether we want to do it. + */ + time_t now = time(NULL) >> 2; + if (old_time != now) /* check once in 4 seconds */ + { + old_time = now; + + time_t hash = 0; + struct stat sb; + if (stat("/etc/resolv.conf", &sb) == 0) + hash = sb.st_mtime; + if (stat("/etc/host.conf", &sb) == 0) + hash += sb.st_mtime; + if (stat("/etc/hosts", &sb) == 0) + hash += sb.st_mtime; + if (stat("/etc/nsswitch.conf", &sb) == 0) + hash += sb.st_mtime; + if (dns_conf_hash != hash) + { + dns_conf_hash = hash; + res_init(); + } + } + + some_ready = g_main_context_check(context, max_priority, fds, nfds); + if (some_ready) + g_main_context_dispatch(context); + } +} + static void start_syslog_logging() { /* Open stdin to /dev/null */ @@ -611,23 +670,29 @@ static void start_syslog_logging() logmode = LOGMODE_SYSLOG; } -static void sanitize_dump_dir_rights() +static void ensure_root_writable_dir(const char *dir) { struct stat sb; - if (mkdir(DEBUG_DUMPS_DIR, 0755) != 0 && errno != EEXIST) - perror_msg_and_die("Can't create '%s'", DEBUG_DUMPS_DIR); - if (stat(DEBUG_DUMPS_DIR, &sb) != 0 || !S_ISDIR(sb.st_mode)) - error_msg_and_die("'%s' is not a directory", DEBUG_DUMPS_DIR); - - if (sb.st_uid != 0 || sb.st_gid != 0 || chown(DEBUG_DUMPS_DIR, 0, 0) != 0) - perror_msg_and_die("Can't set owner 0:0 on '%s'", DEBUG_DUMPS_DIR); + if (mkdir(dir, 0755) != 0 && errno != EEXIST) + perror_msg_and_die("Can't create '%s'", dir); + if (stat(dir, &sb) != 0 || !S_ISDIR(sb.st_mode)) + error_msg_and_die("'%s' is not a directory", dir); + if ((sb.st_uid != 0 || sb.st_gid != 0) && chown(dir, 0, 0) != 0) + perror_msg_and_die("Can't set owner 0:0 on '%s'", dir); /* We can't allow anyone to create dumps: otherwise users can flood * us with thousands of bogus or malicious dumps */ /* 07000 bits are setuid, setgit, and sticky, and they must be unset */ - /* 00777 bits are usual "rwx" access rights */ - if ((sb.st_mode & 07777) != 0755 && chmod(DEBUG_DUMPS_DIR, 0755) != 0) - perror_msg_and_die("Can't set mode rwxr-xr-x on '%s'", DEBUG_DUMPS_DIR); + /* 00777 bits are usual "rwxrwxrwx" access rights */ + if ((sb.st_mode & 07777) != 0755 && chmod(dir, 0755) != 0) + perror_msg_and_die("Can't set mode rwxr-xr-x on '%s'", dir); +} + +static void sanitize_dump_dir_rights() +{ + ensure_root_writable_dir(DEBUG_DUMPS_DIR); + ensure_root_writable_dir(DEBUG_DUMPS_DIR"-di"); /* debuginfo cache */ + ensure_root_writable_dir(VAR_RUN"/abrt"); /* temp dir */ } int main(int argc, char** argv) @@ -643,8 +708,10 @@ int main(int argc, char** argv) textdomain(PACKAGE); #endif - while ((opt = getopt(argc, argv, "dsv")) != -1) + while ((opt = getopt(argc, argv, "dsvt:")) != -1) { + unsigned long ul; + switch (opt) { case 'd': @@ -656,20 +723,32 @@ int main(int argc, char** argv) case 'v': g_verbose++; break; + case 't': + char *end; + errno = 0; + s_timeout = ul = strtoul(optarg, &end, 0); + if (errno == 0 && *end == '\0' && ul <= INT_MAX) + break; + /* fall through to error */ default: error_msg_and_die( "Usage: abrtd [-dv]\n" - "\nOptions:" + "\nOptions:" "\n\t-d\tDo not daemonize" "\n\t-s\tLog to syslog even with -d" + "\n\t-t SEC\tExit after SEC seconds of inactivity" "\n\t-v\tVerbose" ); } } msg_prefix = "abrtd: "; /* for log(), error_msg() and such */ + + xpipe(s_signal_pipe); signal(SIGTERM, handle_fatal_signal); - signal(SIGINT, handle_fatal_signal); + signal(SIGINT, handle_fatal_signal); + if (s_timeout) + signal(SIGALRM, handle_fatal_signal); /* Daemonize unless -d */ if (daemonize) @@ -705,7 +784,9 @@ int main(int argc, char** argv) start_syslog_logging(); } - GIOChannel* pGio = NULL; + GMainLoop* pMainloop = NULL; + GIOChannel* pGiochannel_inotify = NULL; + GIOChannel* pGiochannel_signal = NULL; bool lockfile_created = false; bool pidfile_created = false; CCrashWatcher watcher; @@ -713,17 +794,24 @@ int main(int argc, char** argv) /* Initialization */ try { - pthread_mutex_init(&g_pJobsMutex, NULL); /* never fails */ init_daemon_logging(&watcher); + + VERB1 log("Initializing XML-RPC library"); + xmlrpc_env env; + xmlrpc_env_init(&env); + xmlrpc_client_setup_global_const(&env); + if (env.fault_occurred) + error_msg_and_die("XML-RPC Fault: %s(%d)", env.fault_string, env.fault_code); VERB1 log("Creating glib main loop"); - g_pMainloop = g_main_loop_new(NULL, FALSE); + pMainloop = g_main_loop_new(NULL, FALSE); /* Watching DEBUG_DUMPS_DIR for new files... */ VERB1 log("Initializing inotify"); - /*FIXME: python hook runs with ordinary user privileges, - so it fails if everyone doesn't have write acces - to DEBUG_DUMPS_DIR - */ - //sanitize_dump_dir_rights(); +// Enabled again since we have new abrt-pyhook-helper, remove comment when verified to work + /* FIXME: python hook runs with ordinary user privileges, + * so it fails if everyone doesn't have write acces + * to DEBUG_DUMPS_DIR + */ + sanitize_dump_dir_rights(); errno = 0; int inotify_fd = inotify_init(); if (inotify_fd == -1) @@ -738,7 +826,7 @@ int main(int argc, char** argv) SetUpMW(); /* logging is inside */ if (SetUpCron() != 0) throw 1; -#ifdef ENABLE_DBUS +#if 1 //def ENABLE_DBUS VERB1 log("Initializing dbus"); g_pCommLayer = new CCommLayerServerDBus(); #elif ENABLE_SOCKET @@ -747,18 +835,12 @@ int main(int argc, char** argv) if (g_pCommLayer->m_init_error) throw 1; VERB1 log("Adding inotify watch to glib main loop"); - pGio = g_io_channel_unix_new(inotify_fd); - g_io_add_watch(pGio, G_IO_IN, handle_event_cb, NULL); + pGiochannel_inotify = g_io_channel_unix_new(inotify_fd); + g_io_add_watch(pGiochannel_inotify, G_IO_IN, handle_inotify_cb, NULL); /* Add an event source which waits for INT/TERM signal */ - VERB1 log("Adding signal watch to glib main loop"); - GSourceFuncs waitsignal_funcs; - memset(&waitsignal_funcs, 0, sizeof(waitsignal_funcs)); - waitsignal_funcs.prepare = waitsignal_prepare; - waitsignal_funcs.check = waitsignal_check; - waitsignal_funcs.dispatch = waitsignal_dispatch; - /*waitsignal_funcs.finalize = NULL; - already done */ - GSource *waitsignal_src = (GSource*) g_source_new(&waitsignal_funcs, sizeof(*waitsignal_src)); - g_source_attach(waitsignal_src, g_main_context_default()); + VERB1 log("Adding signal pipe watch to glib main loop"); + pGiochannel_signal = g_io_channel_unix_new(s_signal_pipe[0]); + g_io_add_watch(pGiochannel_signal, G_IO_IN, handle_signal_cb, NULL); /* Mark the territory */ VERB1 log("Creating lock file"); if (Lock() != 0) @@ -788,17 +870,20 @@ int main(int argc, char** argv) start_syslog_logging(); } + /* Only now we want signal pipe to work */ + s_signal_pipe_write = s_signal_pipe[1]; + /* Enter the event loop */ try { /* This may take a while, therefore we don't do it in init section */ FindNewDumps(DEBUG_DUMPS_DIR); log("Running..."); - g_main_run(g_pMainloop); + run_main_loop(pMainloop); } catch (CABRTException& e) { - error_msg("Error: %s", e.what().c_str()); + error_msg("Error: %s", e.what()); } catch (std::exception& e) { @@ -813,8 +898,12 @@ int main(int argc, char** argv) unlink(VAR_RUN_PIDFILE); if (lockfile_created) unlink(VAR_RUN_LOCK_FILE); - if (pGio) - g_io_channel_unref(pGio); + + if (pGiochannel_signal) + g_io_channel_unref(pGiochannel_signal); + if (pGiochannel_inotify) + g_io_channel_unref(pGiochannel_inotify); + delete g_pCommLayer; if (g_pPluginManager) { @@ -822,13 +911,11 @@ int main(int argc, char** argv) g_pPluginManager->UnLoadPlugins(); delete g_pPluginManager; } - if (g_pMainloop) - g_main_loop_unref(g_pMainloop); - if (pthread_mutex_destroy(&g_pJobsMutex) != 0) - error_msg("Threading error: job mutex locked"); + if (pMainloop) + g_main_loop_unref(pMainloop); /* Exiting */ - if (s_sig_caught) + if (s_sig_caught && s_sig_caught != SIGALRM) { error_msg_and_die("Got signal %d, exiting", s_sig_caught); signal(s_sig_caught, SIG_DFL); diff --git a/src/Daemon/Daemon.h b/src/Daemon/Daemon.h index c9a653ac..ac998b93 100644 --- a/src/Daemon/Daemon.h +++ b/src/Daemon/Daemon.h @@ -39,6 +39,4 @@ extern CPluginManager* g_pPluginManager; */ extern set_string_t g_setBlackList; -extern pthread_mutex_t g_pJobsMutex; - #endif diff --git a/src/Daemon/Makefile.am b/src/Daemon/Makefile.am index 0067e5dd..a5bb64f6 100644 --- a/src/Daemon/Makefile.am +++ b/src/Daemon/Makefile.am @@ -2,6 +2,7 @@ bin_SCRIPTS = abrt-debuginfo-install sbin_PROGRAMS = abrtd +# disabled: CommLayerServerSocket.h CommLayerServerSocket.cpp abrtd_SOURCES = \ ABRTPlugin.h ABRTPlugin.cpp \ PluginManager.h PluginManager.cpp \ @@ -9,7 +10,6 @@ abrtd_SOURCES = \ MiddleWare.h MiddleWare.cpp \ CrashWatcher.h CrashWatcher.cpp \ CommLayerServer.h CommLayerServer.cpp \ - CommLayerServerSocket.h CommLayerServerSocket.cpp \ CommLayerServerDBus.h CommLayerServerDBus.cpp \ Daemon.h Daemon.cpp \ Settings.h Settings.cpp @@ -24,13 +24,15 @@ abrtd_CPPFLAGS = \ -DPLUGINS_CONF_DIR=\"$(PLUGINS_CONF_DIR)\" \ $(GLIB_CFLAGS) \ $(DBUS_CFLAGS) \ + $(XMLRPC_CFLAGS) $(XMLRPC_CLIENT_CFLAGS) \ $(ENABLE_SOCKET_OR_DBUS) \ -D_GNU_SOURCE abrtd_LDADD = \ ../../lib/Utils/libABRTUtils.la \ $(DL_LIBS) \ $(DBUS_LIBS) \ - $(RPM_LIBS) + $(RPM_LIBS) \ + $(XMLRPC_LIBS) $(XMLRPC_CLIENT_LIBS) dbusabrtconfdir = ${sysconfdir}/dbus-1/system.d/ dist_dbusabrtconf_DATA = dbus-abrt.conf diff --git a/src/Daemon/MiddleWare.cpp b/src/Daemon/MiddleWare.cpp index 2ccd5890..6a635642 100644 --- a/src/Daemon/MiddleWare.cpp +++ b/src/Daemon/MiddleWare.cpp @@ -20,6 +20,7 @@ */ #include "abrtlib.h" +#include "abrt_types.h" #include "Daemon.h" #include "Settings.h" #include "RPM.h" @@ -60,7 +61,7 @@ static map_analyzer_actions_and_reporters_t s_mapAnalyzerActionsAndReporters; static vector_pair_string_string_t s_vectorActionsAndReporters; -static void RunAnalyzerActions(const std::string& pAnalyzer, const std::string& pDebugDumpDir); +static void RunAnalyzerActions(const char *pAnalyzer, const char *pDebugDumpDir); /** @@ -69,7 +70,7 @@ static void RunAnalyzerActions(const std::string& pAnalyzer, const std::string& * @param pDebugDumpDir A debugdump dir containing all necessary data. * @param pCrashReport A created crash report. */ -static void DebugDumpToCrashReport(const std::string& pDebugDumpDir, map_crash_report_t& pCrashReport) +static void DebugDumpToCrashReport(const char *pDebugDumpDir, map_crash_report_t& pCrashReport) { std::string fileName; std::string content; @@ -84,19 +85,22 @@ static void DebugDumpToCrashReport(const std::string& pDebugDumpDir, map_crash_r !dd.Exist(FILENAME_RELEASE) || !dd.Exist(FILENAME_EXECUTABLE)) { - throw CABRTException(EXCEP_ERROR, "DebugDumpToCrashReport(): One or more of important file(s)'re missing."); + throw CABRTException(EXCEP_ERROR, "DebugDumpToCrashReport(): One or more of important file(s)'re missing"); } + pCrashReport.clear(); dd.InitGetNextFile(); while (dd.GetNextFile(fileName, content, isTextFile)) { + //VERB3 log(" file:'%s' text:%d", fileName.c_str(), isTextFile); if (!isTextFile) { add_crash_data_to_crash_report(pCrashReport, fileName, CD_BIN, CD_ISNOTEDITABLE, - pDebugDumpDir + "/" + fileName); + concat_path_file(pDebugDumpDir, fileName.c_str()) + ); } else { @@ -135,8 +139,8 @@ static void DebugDumpToCrashReport(const std::string& pDebugDumpDir, map_crash_r * @param pDebugDumpDir A debugdump dir containing all necessary data. * @return A local UUID. */ -static std::string GetLocalUUID(const std::string& pAnalyzer, - const std::string& pDebugDumpDir) +static std::string GetLocalUUID(const char *pAnalyzer, + const char *pDebugDumpDir) { CAnalyzer* analyzer = g_pPluginManager->GetAnalyzer(pAnalyzer); return analyzer->GetLocalUUID(pDebugDumpDir); @@ -148,8 +152,8 @@ static std::string GetLocalUUID(const std::string& pAnalyzer, * @param pDebugDumpDir A debugdump dir containing all necessary data. * @return A global UUID. */ -static std::string GetGlobalUUID(const std::string& pAnalyzer, - const std::string& pDebugDumpDir) +static std::string GetGlobalUUID(const char *pAnalyzer, + const char *pDebugDumpDir) { CAnalyzer* analyzer = g_pPluginManager->GetAnalyzer(pAnalyzer); return analyzer->GetGlobalUUID(pDebugDumpDir); @@ -162,32 +166,32 @@ static std::string GetGlobalUUID(const std::string& pAnalyzer, * @param pAnalyzer A name of an analyzer plugin. * @param pDebugDumpPath A debugdump dir containing all necessary data. */ -static void CreateReport(const std::string& pAnalyzer, - const std::string& pDebugDumpDir, +static void CreateReport(const char *pAnalyzer, + const char *pDebugDumpDir, int force) { CAnalyzer* analyzer = g_pPluginManager->GetAnalyzer(pAnalyzer); analyzer->CreateReport(pDebugDumpDir, force); } -mw_result_t CreateCrashReport(const std::string& pUUID, - const std::string& pUID, +mw_result_t CreateCrashReport(const char *pUUID, + const char *pUID, int force, map_crash_report_t& pCrashReport) { - VERB2 log("CreateCrashReport('%s','%s',result)", pUUID.c_str(), pUID.c_str()); + VERB2 log("CreateCrashReport('%s','%s',result)", pUUID, pUID); database_row_t row; - if (pUUID != "") + if (pUUID[0] != '\0') { CDatabase* database = g_pPluginManager->GetDatabase(g_settings_sDatabase); database->Connect(); row = database->GetUUIDData(pUUID, pUID); database->DisConnect(); } - if (pUUID == "" || row.m_sUUID != pUUID) + if (pUUID[0] == '\0' || row.m_sUUID != pUUID) { - warn_client("CreateCrashReport(): UUID '"+pUUID+"' is not in database"); + error_msg("UUID '%s' is not in database", pUUID); return MW_IN_DB_ERROR; } @@ -200,7 +204,7 @@ mw_result_t CreateCrashReport(const std::string& pUUID, std::string reproduce = "1.\n2.\n3.\n"; VERB3 log(" LoadText(FILENAME_ANALYZER,'%s')", row.m_sDebugDumpDir.c_str()); - dd.Open(row.m_sDebugDumpDir); + dd.Open(row.m_sDebugDumpDir.c_str()); dd.LoadText(FILENAME_ANALYZER, analyzer); if (dd.Exist(FILENAME_COMMENT)) { @@ -213,15 +217,15 @@ mw_result_t CreateCrashReport(const std::string& pUUID, dd.Close(); VERB3 log(" CreateReport('%s')", analyzer.c_str()); - CreateReport(analyzer, row.m_sDebugDumpDir, force); + CreateReport(analyzer.c_str(), row.m_sDebugDumpDir.c_str(), force); - gUUID = GetGlobalUUID(analyzer, row.m_sDebugDumpDir); + gUUID = GetGlobalUUID(analyzer.c_str(), row.m_sDebugDumpDir.c_str()); VERB3 log(" GetGlobalUUID:'%s'", gUUID.c_str()); VERB3 log(" RunAnalyzerActions"); - RunAnalyzerActions(analyzer, row.m_sDebugDumpDir); + RunAnalyzerActions(analyzer.c_str(), row.m_sDebugDumpDir.c_str()); VERB3 log(" DebugDumpToCrashReport"); - DebugDumpToCrashReport(row.m_sDebugDumpDir, pCrashReport); + DebugDumpToCrashReport(row.m_sDebugDumpDir.c_str(), pCrashReport); add_crash_data_to_crash_report(pCrashReport, CD_UUID, CD_TXT, CD_ISNOTEDITABLE, gUUID); add_crash_data_to_crash_report(pCrashReport, CD_MWANALYZER, CD_SYS, CD_ISNOTEDITABLE, analyzer); @@ -232,16 +236,16 @@ mw_result_t CreateCrashReport(const std::string& pUUID, } catch (CABRTException& e) { - warn_client("CreateCrashReport(): " + e.what()); + error_msg("%s", e.what()); if (e.type() == EXCEP_DD_OPEN) { return MW_ERROR; } - else if (e.type() == EXCEP_DD_LOAD) + if (e.type() == EXCEP_DD_LOAD) { return MW_FILE_ERROR; } - else if (e.type() == EXCEP_PLUGIN) + if (e.type() == EXCEP_PLUGIN) { return MW_PLUGIN_ERROR; } @@ -251,48 +255,46 @@ mw_result_t CreateCrashReport(const std::string& pUUID, return MW_OK; } -void RunAction(const std::string& pActionDir, - const std::string& pPluginName, - const std::string& pPluginArgs) +void RunAction(const char *pActionDir, + const char *pPluginName, + const char *pPluginArgs) { try { CAction* action = g_pPluginManager->GetAction(pPluginName); - action->Run(pActionDir, pPluginArgs); } catch (CABRTException& e) { - warn_client("RunAction(): " + e.what()); - update_client("Execution of '"+pPluginName+"' was not successful: " + e.what()); + error_msg("Execution of '%s' was not successful: %s", pPluginName, e.what()); } } -void RunActionsAndReporters(const std::string& pDebugDumpDir) +void RunActionsAndReporters(const char *pDebugDumpDir) { vector_pair_string_string_t::iterator it_ar = s_vectorActionsAndReporters.begin(); + map_plugin_settings_t plugin_settings; for (; it_ar != s_vectorActionsAndReporters.end(); it_ar++) { try { - if (g_pPluginManager->GetPluginType((*it_ar).first) == REPORTER) + if (g_pPluginManager->GetPluginType(it_ar->first) == REPORTER) { - CReporter* reporter = g_pPluginManager->GetReporter((*it_ar).first); + CReporter* reporter = g_pPluginManager->GetReporter(it_ar->first); map_crash_report_t crashReport; DebugDumpToCrashReport(pDebugDumpDir, crashReport); - reporter->Report(crashReport, (*it_ar).second); + reporter->Report(crashReport, plugin_settings, it_ar->second); } - else if (g_pPluginManager->GetPluginType((*it_ar).first) == ACTION) + else if (g_pPluginManager->GetPluginType(it_ar->first) == ACTION) { - CAction* action = g_pPluginManager->GetAction((*it_ar).first); - action->Run(pDebugDumpDir, (*it_ar).second); + CAction* action = g_pPluginManager->GetAction(it_ar->first); + action->Run(pDebugDumpDir, it_ar->second.c_str()); } } catch (CABRTException& e) { - warn_client("RunActionsAndReporters(): " + e.what()); - update_client("Activation of plugin '"+(*it_ar).first+"' was not successful: " + e.what()); + error_msg("Activation of plugin '%s' was not successful: %s", it_ar->first.c_str(), e.what()); } } } @@ -312,6 +314,11 @@ static bool CheckReport(const map_crash_report_t& pCrashReport) map_crash_report_t::const_iterator it_executable = pCrashReport.find(FILENAME_EXECUTABLE); map_crash_report_t::const_iterator end = pCrashReport.end(); + + // FIXME: bypass the test if it's kerneloops + if (it_package->second[CD_CONTENT] == "kernel") + return true; + if (it_analyzer == end || it_mwuid == end || it_mwuuid == end || it_package == end || it_architecture == end || it_kernel == end || @@ -334,7 +341,8 @@ static bool CheckReport(const map_crash_report_t& pCrashReport) } report_status_t Report(const map_crash_report_t& pCrashReport, - const std::string& pUID) + map_map_string_t& pSettings, + const char *pUID) { report_status_t ret; @@ -352,18 +360,18 @@ report_status_t Report(const map_crash_report_t& pCrashReport, // Save comments and how to reproduciton map_crash_report_t::const_iterator it_comment = pCrashReport.find(CD_COMMENT); map_crash_report_t::const_iterator it_reproduce = pCrashReport.find(CD_REPRODUCE); - std::string pDumpDir = getDebugDumpDir(UUID,UID); + std::string pDumpDir = getDebugDumpDir(UUID.c_str(), UID.c_str()); { CDebugDump dd; - dd.Open(pDumpDir); + dd.Open(pDumpDir.c_str()); if (it_comment != pCrashReport.end()) { - dd.SaveText(FILENAME_COMMENT, it_comment->second[CD_CONTENT]); + dd.SaveText(FILENAME_COMMENT, it_comment->second[CD_CONTENT].c_str()); } if (it_reproduce != pCrashReport.end()) { - dd.SaveText(FILENAME_REPRODUCE, it_reproduce->second[CD_CONTENT]); + dd.SaveText(FILENAME_REPRODUCE, it_reproduce->second[CD_CONTENT].c_str()); } } @@ -407,7 +415,8 @@ report_status_t Report(const map_crash_report_t& pCrashReport, } } #endif - std::string res = reporter->Report(pCrashReport, it_r->second); + map_plugin_settings_t plugin_settings = pSettings[pluginName]; + std::string res = reporter->Report(pCrashReport, plugin_settings, it_r->second); #if 0 /* Using ~user/.abrt/ is bad wrt security */ if (home != "") @@ -424,8 +433,7 @@ report_status_t Report(const map_crash_report_t& pCrashReport, { ret[pluginName].push_back("0"); ret[pluginName].push_back(e.what()); - warn_client("Report(): " + e.what()); - update_client("Reporting via '" + pluginName + "' was not successful: " + e.what()); + update_client("Reporting via %s' was not successful: %s", pluginName.c_str(), e.what()); } } } @@ -438,15 +446,15 @@ report_status_t Report(const map_crash_report_t& pCrashReport, return ret; } -void DeleteDebugDumpDir(const std::string& pDebugDumpDir) +void DeleteDebugDumpDir(const char *pDebugDumpDir) { CDebugDump dd; dd.Open(pDebugDumpDir); dd.Delete(); } -std::string DeleteCrashInfo(const std::string& pUUID, - const std::string& pUID) +std::string DeleteCrashInfo(const char *pUUID, + const char *pUID) { database_row_t row; CDatabase* database = g_pPluginManager->GetDatabase(g_settings_sDatabase); @@ -466,8 +474,8 @@ std::string DeleteCrashInfo(const std::string& pUUID, * @return It returns true if debugdump dir is already saved, otherwise * it returns false. */ -static bool IsDebugDumpSaved(const std::string& pUID, - const std::string& pDebugDumpDir) +static bool IsDebugDumpSaved(const char *pUID, + const char *pDebugDumpDir) { CDatabase* database = g_pPluginManager->GetDatabase(g_settings_sDatabase); database->Connect(); @@ -501,19 +509,19 @@ void LoadOpenGPGPublicKey(const char* key) * @param pDebugDumpDir A debugdump dir containing all necessary data. * @return It return results of operation. See mw_result_t. */ -static mw_result_t SavePackageDescriptionToDebugDump(const std::string& pExecutable, - const std::string& pDebugDumpDir) +static mw_result_t SavePackageDescriptionToDebugDump(const char *pExecutable, + const char *pDebugDumpDir) { std::string package; std::string packageName; - if (pExecutable == "kernel") + if (strcmp(pExecutable, "kernel") == 0) { packageName = package = "kernel"; } else { - package = GetPackage(pExecutable.c_str()); + package = GetPackage(pExecutable); packageName = package.substr(0, package.rfind("-", package.rfind("-") - 1)); if (packageName == "" || (g_setBlackList.find(packageName) != g_setBlackList.end())) @@ -533,7 +541,7 @@ static mw_result_t SavePackageDescriptionToDebugDump(const std::string& pExecuta error_msg("package isn't signed with proper key"); return MW_GPG_ERROR; } - if (!CheckHash(packageName.c_str(), pExecutable.c_str())) + if (!CheckHash(packageName.c_str(), pExecutable)) { error_msg("executable has bad hash"); return MW_GPG_ERROR; @@ -542,19 +550,19 @@ static mw_result_t SavePackageDescriptionToDebugDump(const std::string& pExecuta } std::string description = GetDescription(packageName.c_str()); - std::string component = GetComponent(pExecutable.c_str()); + std::string component = GetComponent(pExecutable); try { CDebugDump dd; dd.Open(pDebugDumpDir); - dd.SaveText(FILENAME_PACKAGE, package); - dd.SaveText(FILENAME_DESCRIPTION, description); - dd.SaveText(FILENAME_COMPONENT, component); + dd.SaveText(FILENAME_PACKAGE, package.c_str()); + dd.SaveText(FILENAME_DESCRIPTION, description.c_str()); + dd.SaveText(FILENAME_COMPONENT, component.c_str()); } catch (CABRTException& e) { - warn_client("SavePackageDescriptionToDebugDump(): " + e.what()); + error_msg("%s", e.what()); if (e.type() == EXCEP_DD_SAVE) { return MW_FILE_ERROR; @@ -571,7 +579,7 @@ static mw_result_t SavePackageDescriptionToDebugDump(const std::string& pExecuta * @param pAnalyzer A name of an analyzer plugin. * @param pDebugDumpPath A debugdump dir containing all necessary data. */ -static void RunAnalyzerActions(const std::string& pAnalyzer, const std::string& pDebugDumpDir) +static void RunAnalyzerActions(const char *pAnalyzer, const char *pDebugDumpDir) { map_analyzer_actions_and_reporters_t::iterator analyzer = s_mapAnalyzerActionsAndReporters.find(pAnalyzer); if (analyzer != s_mapAnalyzerActionsAndReporters.end()) @@ -585,13 +593,12 @@ static void RunAnalyzerActions(const std::string& pAnalyzer, const std::string& if (g_pPluginManager->GetPluginType(pluginName) == ACTION) { CAction* action = g_pPluginManager->GetAction(pluginName); - action->Run(pDebugDumpDir, it_a->second); + action->Run(pDebugDumpDir, it_a->second.c_str()); } } catch (CABRTException& e) { - warn_client("RunAnalyzerActions(): " + e.what()); - update_client("Action performed by '" + pluginName + "' was not successful: " + e.what()); + update_client("Action performed by '%s' was not successful: %s", pluginName.c_str(), e.what()); } } } @@ -608,10 +615,10 @@ static void RunAnalyzerActions(const std::string& pAnalyzer, const std::string& * @param pCrashInfo A filled crash info. * @return It return results of operation. See mw_result_t. */ -static mw_result_t SaveDebugDumpToDatabase(const std::string& pUUID, - const std::string& pUID, - const std::string& pTime, - const std::string& pDebugDumpDir, +static mw_result_t SaveDebugDumpToDatabase(const char *pUUID, + const char *pUID, + const char *pTime, + const char *pDebugDumpDir, map_crash_info_t& pCrashInfo) { mw_result_t res; @@ -635,8 +642,8 @@ static mw_result_t SaveDebugDumpToDatabase(const std::string& pUUID, return res; } -std::string getDebugDumpDir( const std::string& pUUID, - const std::string& pUID) +std::string getDebugDumpDir(const char *pUUID, + const char *pUID) { CDatabase* database = g_pPluginManager->GetDatabase(g_settings_sDatabase); database_row_t row; @@ -646,13 +653,13 @@ std::string getDebugDumpDir( const std::string& pUUID, return row.m_sDebugDumpDir; } -mw_result_t SaveDebugDump(const std::string& pDebugDumpDir) +mw_result_t SaveDebugDump(const char *pDebugDumpDir) { map_crash_info_t info; return SaveDebugDump(pDebugDumpDir, info); } -mw_result_t SaveDebugDump(const std::string& pDebugDumpDir, +mw_result_t SaveDebugDump(const char *pDebugDumpDir, map_crash_info_t& pCrashInfo) { std::string lUUID; @@ -673,7 +680,7 @@ mw_result_t SaveDebugDump(const std::string& pDebugDumpDir, } catch (CABRTException& e) { - warn_client("SaveDebugDump(): " + e.what()); + error_msg("%s", e.what()); if (e.type() == EXCEP_DD_SAVE) { return MW_FILE_ERROR; @@ -681,24 +688,24 @@ mw_result_t SaveDebugDump(const std::string& pDebugDumpDir, return MW_ERROR; } - if (IsDebugDumpSaved(UID, pDebugDumpDir)) + if (IsDebugDumpSaved(UID.c_str(), pDebugDumpDir)) { return MW_IN_DB; } - res = SavePackageDescriptionToDebugDump(executable, pDebugDumpDir); + res = SavePackageDescriptionToDebugDump(executable.c_str(), pDebugDumpDir); if (res != MW_OK) { return res; } - lUUID = GetLocalUUID(analyzer, pDebugDumpDir); + lUUID = GetLocalUUID(analyzer.c_str(), pDebugDumpDir); - return SaveDebugDumpToDatabase(lUUID, UID, time, pDebugDumpDir, pCrashInfo); + return SaveDebugDumpToDatabase(lUUID.c_str(), UID.c_str(), time.c_str(), pDebugDumpDir, pCrashInfo); } -mw_result_t GetCrashInfo(const std::string& pUUID, - const std::string& pUID, - map_crash_info_t& pCrashInfo) +mw_result_t GetCrashInfo(const char *pUUID, + const char *pUID, + map_crash_info_t& pCrashInfo) { pCrashInfo.clear(); CDatabase* database = g_pPluginManager->GetDatabase(g_settings_sDatabase); @@ -710,18 +717,20 @@ mw_result_t GetCrashInfo(const std::string& pUUID, std::string package; std::string executable; std::string description; + std::string analyzer; try { CDebugDump dd; - dd.Open(row.m_sDebugDumpDir); + dd.Open(row.m_sDebugDumpDir.c_str()); dd.LoadText(FILENAME_EXECUTABLE, executable); dd.LoadText(FILENAME_PACKAGE, package); dd.LoadText(FILENAME_DESCRIPTION, description); + dd.LoadText(FILENAME_ANALYZER, analyzer); } catch (CABRTException& e) { - warn_client("GetCrashInfo(): " + e.what()); + error_msg("%s", e.what()); if (e.type() == EXCEP_DD_LOAD) { return MW_FILE_ERROR; @@ -738,11 +747,12 @@ mw_result_t GetCrashInfo(const std::string& pUUID, add_crash_data_to_crash_info(pCrashInfo, CD_REPORTED, row.m_sReported); add_crash_data_to_crash_info(pCrashInfo, CD_MESSAGE, row.m_sMessage); add_crash_data_to_crash_info(pCrashInfo, CD_MWDDD, row.m_sDebugDumpDir); + add_crash_data_to_crash_info(pCrashInfo, CD_MWANALYZER, analyzer); return MW_OK; } -vector_pair_string_string_t GetUUIDsOfCrash(const std::string& pUID) +vector_pair_string_string_t GetUUIDsOfCrash(const char *pUID) { CDatabase* database = g_pPluginManager->GetDatabase(g_settings_sDatabase); vector_database_rows_t rows; @@ -760,15 +770,15 @@ vector_pair_string_string_t GetUUIDsOfCrash(const std::string& pUID) return UUIDsUIDs; } -void AddAnalyzerActionOrReporter(const std::string& pAnalyzer, - const std::string& pAnalyzerOrReporter, - const std::string& pArgs) +void AddAnalyzerActionOrReporter(const char *pAnalyzer, + const char *pAnalyzerOrReporter, + const char *pArgs) { - s_mapAnalyzerActionsAndReporters[pAnalyzer].push_back(make_pair(pAnalyzerOrReporter, pArgs)); + s_mapAnalyzerActionsAndReporters[pAnalyzer].push_back(make_pair(std::string(pAnalyzerOrReporter), std::string(pArgs))); } -void AddActionOrReporter(const std::string& pActionOrReporter, - const std::string& pArgs) +void AddActionOrReporter(const char *pActionOrReporter, + const char *pArgs) { - s_vectorActionsAndReporters.push_back(make_pair(pActionOrReporter, pArgs)); + s_vectorActionsAndReporters.push_back(make_pair(std::string(pActionOrReporter), std::string(pArgs))); } diff --git a/src/Daemon/MiddleWare.h b/src/Daemon/MiddleWare.h index fab822fe..0671dd02 100644 --- a/src/Daemon/MiddleWare.h +++ b/src/Daemon/MiddleWare.h @@ -63,8 +63,8 @@ void LoadOpenGPGPublicKey(const char* key); * @param pCrashReport A filled crash report. * @return It return results of operation. See mw_result_t. */ -mw_result_t CreateCrashReport(const std::string& pUUID, - const std::string& pUID, +mw_result_t CreateCrashReport(const char *pUUID, + const char *pUID, int force, map_crash_report_t& pCrashReport); /** @@ -73,15 +73,15 @@ mw_result_t CreateCrashReport(const std::string& pUUID, * @param pPluginName An action plugin name. * @param pPluginArgs Action plugin's arguments. */ -void RunAction(const std::string& pActionDir, - const std::string& pPluginName, - const std::string& pPluginArgs); +void RunAction(const char *pActionDir, + const char *pPluginName, + const char *pPluginArgs); /** * Activates all action and reporter plugins when any * crash occurs. * @param pDebugDumpDir A debugdump dir containing all necessary data. */ -void RunActionsAndReporters(const std::string& pDebugDumpDir); +void RunActionsAndReporters(const char *pDebugDumpDir); /** * Reports a crash report to particular receiver. It * takes an user uid, tries to find user config file and load it. If it @@ -93,7 +93,8 @@ void RunActionsAndReporters(const std::string& pDebugDumpDir); * @return A report status, which reporters ends successfuly with messages. */ report_status_t Report(const map_crash_report_t& pCrashReport, - const std::string& pUID); + map_map_string_t& pSettings, + const char *pUID); /** * Get debugdump direcotory. If debugdump is not found * in database it will return empty string. @@ -101,13 +102,13 @@ report_status_t Report(const map_crash_report_t& pCrashReport, * @param pUID An UID of an user. * @return A debugdump directory. */ -std::string getDebugDumpDir( const std::string& pUUID, - const std::string& pUID); +std::string getDebugDumpDir( const char *pUUID, + const char *pUID); /** * Deletes particular debugdump directory. * @param pDebugDumpDir A debugdump directory. */ -void DeleteDebugDumpDir(const std::string& pDebugDumpDir); +void DeleteDebugDumpDir(const char *pDebugDumpDir); /** * Deletes a row from database. If a deleting is * successfull, it returns a debugdump directort, which is not @@ -116,14 +117,14 @@ void DeleteDebugDumpDir(const std::string& pDebugDumpDir); * @param pUID An UID of an user. * @return A debugdump directory. */ -std::string DeleteCrashInfo(const std::string& pUUID, - const std::string& pUID); +std::string DeleteCrashInfo(const char *pUUID, + const char *pUID); /** * Saves debugdump into database. * @param pDebugDumpDir A debugdump directory. * @return It return results of operation. See mw_result_t. */ -mw_result_t SaveDebugDump(const std::string& pDebugDumpDir); +mw_result_t SaveDebugDump(const char *pDebugDumpDir); /** * Saves debugdump into database. If saving is successful, * it fills crash info. @@ -131,7 +132,7 @@ mw_result_t SaveDebugDump(const std::string& pDebugDumpDir); * @param pCrashInfo A crash info. * @return It return results of operation. See mw_result_t. */ -mw_result_t SaveDebugDump(const std::string& pDebugDumpDir, +mw_result_t SaveDebugDump(const char *pDebugDumpDir, map_crash_info_t& pCrashInfo); /** * Get one crash info. If getting is successful, @@ -141,8 +142,8 @@ mw_result_t SaveDebugDump(const std::string& pDebugDumpDir, * @param pCrashInfo A crash info. * @return It return results of operation. See mw_result_t. */ -mw_result_t GetCrashInfo(const std::string& pUUID, - const std::string& pUID, +mw_result_t GetCrashInfo(const char *pUUID, + const char *pUID, map_crash_info_t& pCrashInfo); /** * Gets all local UUIDs and UIDs of crashes. These crashes @@ -150,7 +151,7 @@ mw_result_t GetCrashInfo(const std::string& pUUID, * @param pUID an UID of an user. * @return A vector of pairs (local UUID, UID). */ -vector_pair_string_string_t GetUUIDsOfCrash(const std::string& pUID); +vector_pair_string_string_t GetUUIDsOfCrash(const char *pUID); /** * Adds one association among alanyzer plugin and its * action and reporter plugins. @@ -158,17 +159,17 @@ vector_pair_string_string_t GetUUIDsOfCrash(const std::string& pUID); * @param pActionOrReporter A name of an action or reporter plugin. * @param pArgs An arguments for action or reporter plugin. */ -void AddAnalyzerActionOrReporter(const std::string& pAnalyzer, - const std::string& pActionOrReporter, - const std::string& pArgs); +void AddAnalyzerActionOrReporter(const char *pAnalyzer, + const char *pActionOrReporter, + const char *pArgs); /** * Add action and reporter plugins, which are activated * when any crash occurs. * @param pActionOrReporter A name of an action or reporter plugin. * @param pArgs An arguments for action or reporter plugin. */ -void AddActionOrReporter(const std::string& pActionOrReporter, - const std::string& pArgs); +void AddActionOrReporter(const char *pActionOrReporter, + const char *pArgs); #endif /*MIDDLEWARE_H_*/ diff --git a/src/Daemon/PluginManager.cpp b/src/Daemon/PluginManager.cpp index 2363308a..5b871515 100644 --- a/src/Daemon/PluginManager.cpp +++ b/src/Daemon/PluginManager.cpp @@ -179,8 +179,7 @@ void CPluginManager::LoadPlugin(const std::string& pName) catch (CABRTException& e) { delete abrtPlugin; - warn_client("CPluginManager::LoadPlugin(): " + e.what()); - warn_client("Failed to load plugin " + pName); + error_msg("Failed to load plugin %s: %s", pName.c_str(), e.what()); } } } @@ -218,7 +217,7 @@ void CPluginManager::RegisterPlugin(const std::string& pName) log("Can't initialize plugin %s(%s): %s", pName.c_str(), plugin_type_str[abrt_plugin->second->GetType()], - e.what().c_str() + e.what() ); UnLoadPlugin(pName); return; diff --git a/src/Daemon/Settings.cpp b/src/Daemon/Settings.cpp index 1eb42263..d9c9a98b 100644 --- a/src/Daemon/Settings.cpp +++ b/src/Daemon/Settings.cpp @@ -54,12 +54,12 @@ map_cron_t g_settings_mapCron; * Loading */ -static set_string_t ParseList(const std::string& pList) +static set_string_t ParseList(const char* pList) { - unsigned int ii; - std::string item = ""; + unsigned ii; + std::string item; set_string_t set; - for (ii = 0; ii < pList.size(); ii++) + for (ii = 0; pList[ii]; ii++) { if (pList[ii] == ',') { @@ -78,19 +78,19 @@ static set_string_t ParseList(const std::string& pList) return set; } -static vector_pair_string_string_t ParseListWithArgs(const std::string& pValue) +static vector_pair_string_string_t ParseListWithArgs(const char *pValue) { vector_pair_string_string_t pluginsWithArgs; unsigned int ii; - std::string item = ""; - std::string action = ""; + std::string item; + std::string action; bool is_quote = false; bool is_arg = false; - for (ii = 0; ii < pValue.size(); ii++) + for (ii = 0; pValue[ii]; ii++) { if (pValue[ii] == '\"') { - is_quote = is_quote == true ? false : true; + is_quote = !is_quote; item += pValue[ii]; } else if (pValue[ii] == '(' && !is_quote) @@ -137,12 +137,12 @@ static void ParseCommon() it = s_mapSectionCommon.find("OpenGPGPublicKeys"); if (it != end) { - g_settings_setOpenGPGPublicKeys = ParseList(it->second); + g_settings_setOpenGPGPublicKeys = ParseList(it->second.c_str()); } it = s_mapSectionCommon.find("BlackList"); if (it != end) { - g_settings_mapBlackList = ParseList(it->second); + g_settings_mapBlackList = ParseList(it->second.c_str()); } it = s_mapSectionCommon.find("Database"); if (it != end) @@ -152,7 +152,7 @@ static void ParseCommon() it = s_mapSectionCommon.find("EnabledPlugins"); if (it != end) { - g_settings_setEnabledPlugins = ParseList(it->second); + g_settings_setEnabledPlugins = ParseList(it->second.c_str()); } it = s_mapSectionCommon.find("MaxCrashReportsSize"); if (it != end) @@ -162,7 +162,7 @@ static void ParseCommon() it = s_mapSectionCommon.find("ActionsAndReporters"); if (it != end) { - g_settings_vectorActionsAndReporters = ParseListWithArgs(it->second); + g_settings_vectorActionsAndReporters = ParseListWithArgs(it->second.c_str()); } } @@ -171,23 +171,23 @@ static void ParseCron() map_string_t::iterator it = s_mapSectionCron.begin(); for (; it != s_mapSectionCron.end(); it++) { - vector_pair_string_string_t actionsAndReporters = ParseListWithArgs(it->second); + vector_pair_string_string_t actionsAndReporters = ParseListWithArgs(it->second.c_str()); g_settings_mapCron[it->first] = actionsAndReporters; } } -static set_string_t ParseKey(const std::string& Key) +static set_string_t ParseKey(const char *Key) { unsigned int ii; - std::string item = ""; - std::string key = ""; + std::string item; + std::string key; set_string_t set; bool is_quote = false; - for (ii = 0; ii < Key.size(); ii++) + for (ii = 0; Key[ii]; ii++) { if (Key[ii] == '\"') { - is_quote = is_quote == true ? false : true; + is_quote = !is_quote; } else if (Key[ii] == ':' && !is_quote) { @@ -223,8 +223,8 @@ static void ParseAnalyzerActionsAndReporters() map_string_t::iterator it = s_mapSectionAnalyzerActionsAndReporters.begin(); for (; it != s_mapSectionAnalyzerActionsAndReporters.end(); it++) { - set_string_t keys = ParseKey(it->first); - vector_pair_string_string_t actionsAndReporters = ParseListWithArgs(it->second); + set_string_t keys = ParseKey(it->first.c_str()); + vector_pair_string_string_t actionsAndReporters = ParseListWithArgs(it->second.c_str()); set_string_t::iterator it_keys = keys.begin(); for (; it_keys != keys.end(); it_keys++) { @@ -241,7 +241,7 @@ void LoadSettings() if (fIn.is_open()) { std::string line; - std::string section = ""; + std::string section; while (!fIn.eof()) { getline(fIn, line); @@ -250,8 +250,8 @@ void LoadSettings() bool is_key = true; bool is_section = false; bool is_quote = false; - std::string key = ""; - std::string value = ""; + std::string key; + std::string value; for (ii = 0; ii < line.length(); ii++) { if (isspace(line[ii]) && !is_quote) @@ -269,7 +269,7 @@ void LoadSettings() } else if (line[ii] == '\"') { - is_quote = is_quote == true ? false : true; + is_quote = !is_quote; value += line[ii]; } else if (is_section) @@ -434,7 +434,7 @@ void SetSettings(const map_abrt_settings_t& pSettings, const char *dbus_sender) "org.fedoraproject.abrt.change-daemon-settings"); if (polkit_result != PolkitYes) { - log("user %s not authorized, returned %d", dbus_sender, polkit_result); + error_msg("user %s not authorized, returned %d", dbus_sender, polkit_result); return; } log("user %s succesfully authorized", dbus_sender); diff --git a/src/Daemon/abrt-debuginfo-install b/src/Daemon/abrt-debuginfo-install index fc5380ba..6070b74d 100755 --- a/src/Daemon/abrt-debuginfo-install +++ b/src/Daemon/abrt-debuginfo-install @@ -13,9 +13,10 @@ # If CACHEDIR is specified, debuginfos should be installed there. # If not, debuginfos should be installed into TEMPDIR. # -# Currently, we are called with CACHEDIR set to "/", but in the future -# it may be omitted or set to something else. script must be ready -# for those cases too. +# Currently, we are called with CACHEDIR set to "/var/cache/abrt-di", +# but in the future it may be omitted or set to something else. +# Script must be ready for those cases too. Consider, for example, +# corner cases of "" and "/". # # Output goes to GUI as debuginfo install log. The script should be careful # to give useful, but not overly cluttered info to stdout. @@ -62,10 +63,6 @@ tempdir=$2 cachedir=$3 debug=false -count_words() { - echo $# -} - exec 2>&1 test -f "$core" || exit 2 @@ -74,10 +71,41 @@ test x"$cachedir" = x"" || test -d "$cachedir" || exit 2 # tempdir must not exist test -e "$tempdir" && exit 2 -mkdir "$tempdir" || exit 2 +mkdir -- "$tempdir" || exit 2 cd "$tempdir" || exit 2 $debug && echo "Installing rpms to $tempdir" + +count_words() { + echo $# +} + +cleanup_and_report_missing() { +# Which debuginfo files are still missing, including those we just unpacked? + missing_build_ids=`for build_id in $build_ids; do + build_id1=${build_id:0:2} + build_id2=${build_id:2} + file="usr/lib/debug/.build-id/$build_id1/$build_id2.debug" + test -f "/$file" && continue + test -f "$cachedir/$file" && continue + echo -n "$build_id " + done` + $debug && echo "missing_build_ids:$missing_build_ids" + + # If cachedir is specified, tempdir is just a staging area. Delete it + if test x"$cachedir" != x""; then + $debug && echo "Removing $tempdir" + rm -rf "$tempdir" + fi + + for missing in $missing_build_ids; do + echo "MISSING:$missing" + done + + test x"$missing_build_ids" != x"" && echo "`count_words $missing_build_ids` debuginfos can't be found" +} + + # eu-unstrip output example: # 0x400000+0x209000 23c77451cf6adff77fc1f5ee2a01d75de6511dda@0x40024c - - [exe] # or @@ -86,7 +114,9 @@ $debug && echo "Installing rpms to $tempdir" # 0x3d15600000+0x208000 20196628d1bc062279622615cc9955554e5bb227@0x3d156001a0 /usr/lib64/libnotify.so.1.1.3 /usr/lib/debug/usr/lib64/libnotify.so.1.1.3.debug libnotify.so.1 # 0x7fd8ae931000+0x62d000 dd49f44f958b5a11a1635523b2f09cb2e45c1734@0x7fd8ae9311a0 /usr/lib64/libgtk-x11-2.0.so.0.1600.6 /usr/lib/debug/usr/lib64/libgtk-x11-2.0.so.0.1600.6.debug echo "Getting list of build IDs" -eu_unstrip_OUT=`eu-unstrip "--core=$core" -n 2>&1` +# Observed errors: +# eu-unstrip: /var/cache/abrt/ccpp-1256301004-2754/coredump: Callback returned failure +eu_unstrip_OUT=`eu-unstrip "--core=$core" -n 2>eu_unstrip.ERR` err=$? printf "%s\nexitcode:%s\n" "$eu_unstrip_OUT" $err >eu_unstrip.OUT test $err = 0 || exit 2 @@ -112,24 +142,19 @@ $debug && echo "build_ids:$build_ids" missing_debuginfo_files=`for build_id in $build_ids; do build_id1=${build_id:0:2} build_id2=${build_id:2} - file="usr/lib/debug/.build-id/$build_id1/$build_id2.debug" if test x"$cachedir" != x"" && test x"$cachedir" != x"/" ; then test -f "$cachedir/$file" && continue - if test -f "/$file"; then - mkdir -p "$cachedir/usr/lib/debug/.build-id/$build_id1" - # Note: this does not preserve symlinks. This is intentional - $debug && echo Copying "$file" to "$cachedir/$file" >&2 - cp "$file" "$cachedir/$file" - continue - fi fi test -f "/$file" && continue echo -n "/$file " done` $debug && echo "missing_debuginfo_files:$missing_debuginfo_files" -test x"$missing_debuginfo_files" = x"" && exit 0 +if test x"$missing_debuginfo_files" = x""; then + cleanup_and_report_missing + exit 0 +fi # We'll run something like: # yum --enablerepo='*debuginfo*' --quiet provides \ @@ -162,14 +187,31 @@ $debug && echo "packages:$packages" # yum may return "" here if it found no packages (say, if coredump is from a new, # unreleased package fresh from koji). -test x"$packages" = x"" && exit 1 +if test x"$packages" = x""; then + cleanup_and_report_missing + exit 1 +fi -# Redirecting, since progress bar stuff only messes up our output -echo "Downloading `count_words $packages` packages" -yumdownloader --enablerepo='*debuginfo*' --quiet $packages >yumdownloader.OUT 2>&1 -err=$? -echo "exitcode:$err" >>yumdownloader.OUT -test $err = 0 || exit 2 +num_packages=`count_words $packages` +echo "Downloading $num_packages packages" +## Download with one command (too silent): +## Redirecting, since progress bar stuff only messes up our output +##yumdownloader --enablerepo='*debuginfo*' --quiet $packages >yumdownloader.OUT 2>&1 +##err=$? +##echo "exitcode:$err" >>yumdownloader.OUT +##test $err = 0 || exit 2 +>yumdownloader.OUT +i=1 +for pkg in $packages; do + echo "Download $i/$num_packages: $pkg" + echo "Download $i/$num_packages: $pkg" >>yumdownloader.OUT + yumdownloader --enablerepo='*debuginfo*' --quiet $pkg >>yumdownloader.OUT 2>&1 + err=$? + echo "exitcode:$err" >>yumdownloader.OUT + echo >>yumdownloader.OUT + test $err = 0 || { echo "Download of $pkg failed!"; sleep 1; } + : $((i++)) +done for f in *.rpm; do # Happens if no .rpm's were downloaded (yumdownloader problem) @@ -180,45 +222,31 @@ for f in *.rpm; do rpm2cpio <"$f" 2>>unpack.OUT | cpio -id >>unpack.OUT 2>&1 done -# Which debuginfo files are still missing, including those we just unpacked? -missing_build_ids=`for build_id in $build_ids; do - build_id1=${build_id:0:2} - build_id2=${build_id:2} +# Copy debuginfo files to cachedir +if test x"$cachedir" != x"" && test -d "$cachedir"; then + for build_id in $build_ids; do + build_id1=${build_id:0:2} + build_id2=${build_id:2} - file="usr/lib/debug/.build-id/$build_id1/$build_id2.debug" + file="usr/lib/debug/.build-id/$build_id1/$build_id2.debug" - test -f "/$file" && continue - test x"$cachedir" != x"" \ - && test x"$cachedir" != x"/" \ - && test -f "$cachedir/$file" && continue - - if test -f "$file"; then - # file is one of those we just installed. - # Cache it if cachedir is specified. - if test x"$cachedir" != x"" && test -d "$cachedir"; then + test -f "/$file" && continue + test x"$cachedir" != x"/" && test -f "$cachedir/$file" && continue + + if test -f "$file"; then + # file is one of those we just installed. + # Cache it if cachedir is specified. mkdir -p "$cachedir/usr/lib/debug/.build-id/$build_id1" # Note: this does not preserve symlinks. This is intentional - $debug && echo Copying "$file" to "$cachedir/$file" >&2 + $debug && echo Copying2 "$file" to "$cachedir/$file" >&2 cp --remove-destination "$file" "$cachedir/$file" + continue fi - continue - fi - echo -n "$build_id " -done` -$debug && echo "missing_build_ids:$missing_build_ids" - -# If cachedir is specified, tempdir is just a staging area. Delete it -if test x"$cachedir" != x""; then - $debug && echo "Removing $tempdir" - rm -rf "$tempdir" + done fi +$debug && echo "missing_build_ids:$missing_build_ids" -test x"$missing_build_ids" = x"" && exit 0 - -for missing in $missing_build_ids; do - echo "MISSING:$missing" -done - -echo "`count_words $missing_build_ids` debuginfos can't be found" +cleanup_and_report_missing -exit 1 +test x"$missing_build_ids" != x"" && exit 1 +exit 0 diff --git a/src/Daemon/abrt.conf b/src/Daemon/abrt.conf index 1fe6123b..e9845e58 100644 --- a/src/Daemon/abrt.conf +++ b/src/Daemon/abrt.conf @@ -1,32 +1,31 @@ # test conf file. it will be generated in the future -# common abrt settings +# Common abrt settings [ Common ] # With this option set to "yes", # only crashes in signed packages will be analyzed. OpenGPGCheck = no # GPG keys OpenGPGPublicKeys = /etc/pki/rpm-gpg/RPM-GPG-KEY-fedora -# blacklisted packages -BlackList = -# enabled plugins -# there has to be exactly one database plugin +# Blacklisted packages +BlackList = nspluginwrapper +# Enabled plugins. There has to be exactly one database plugin EnabledPlugins = SQLite3, CCpp, Logger, Kerneloops, KerneloopsScanner, KerneloopsReporter, Bugzilla, Python # Database Database = SQLite3 -# max size for crash storage [MiB] +# Max size for crash storage [MiB] MaxCrashReportsSize = 1000 -# vector of actions and reporters which are activated immediately after a crash occurs +# Vector of actions and reporters which are activated immediately after a crash occurs # ActionsAndReporters = Mailx("[abrt] new crash was detected") -# reporters association with analyzers +# Reporters association with analyzers [ AnalyzerActionsAndReporters ] Kerneloops = KerneloopsReporter CCpp = Bugzilla, Logger Python = Bugzilla, Logger # CCpp : xorg-x11-apps = RunApp("date", "RunApp") -# repeated calling of Action plugins +# Repeated calling of Action plugins [ Cron ] # h:m - at h:m an action plugin is activated # s - every s seconds is an action plugin activated diff --git a/src/Daemon/com.redhat.abrt.service b/src/Daemon/com.redhat.abrt.service index 163f276c..b251ef7f 100644 --- a/src/Daemon/com.redhat.abrt.service +++ b/src/Daemon/com.redhat.abrt.service @@ -1,4 +1,7 @@ [D-BUS Service] Name=com.redhat.abrt +# For testing, you may add -t33 to use small timeout of 33 seconds. +# This will make "abrtd exited while clients existed but were idle" +# situations easy to trigger Exec=/usr/sbin/abrtd -ds User=root |