diff options
| author | Jiri Moskovcak <jmoskovc@redhat.com> | 2009-10-26 16:28:12 +0100 |
|---|---|---|
| committer | Jiri Moskovcak <jmoskovc@redhat.com> | 2009-10-26 16:28:12 +0100 |
| commit | be0c8d7252ae74610d885e21f47e454f8538898f (patch) | |
| tree | e3da4305d7e8ea44d7732051013a71198e664aea /lib | |
| parent | 53ed713b135762ad7b572f39301d80a646173820 (diff) | |
| parent | b1756b440359c381ebafd62709ddcfa78ea74805 (diff) | |
Merge branch 'master' of git://git.fedorahosted.org/git/abrt
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/Plugins/Bugzilla.cpp | 544 | ||||
| -rw-r--r-- | lib/Plugins/Bugzilla.h | 26 | ||||
| -rw-r--r-- | lib/Plugins/CCpp.cpp | 15 | ||||
| -rw-r--r-- | lib/Plugins/Makefile.am | 4 | ||||
| -rw-r--r-- | lib/Utils/Makefile.am | 3 | ||||
| -rw-r--r-- | lib/Utils/skip_whitespace.cpp | 22 | ||||
| -rw-r--r-- | lib/Utils/time.cpp | 65 | ||||
| -rw-r--r-- | lib/Utils/xconnect.cpp | 416 | ||||
| -rw-r--r-- | lib/Utils/xfuncs.cpp | 16 |
9 files changed, 833 insertions, 278 deletions
diff --git a/lib/Plugins/Bugzilla.cpp b/lib/Plugins/Bugzilla.cpp index 48c5eb5..d6f6c0c 100644 --- a/lib/Plugins/Bugzilla.cpp +++ b/lib/Plugins/Bugzilla.cpp @@ -1,5 +1,4 @@ -#include <xmlrpc-c/base.hpp> #include "abrtlib.h" #include "Bugzilla.h" #include "CrashTypes.h" @@ -7,52 +6,98 @@ #include "ABRTException.h" #include "CommLayerInner.h" + +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + #define XML_RPC_SUFFIX "/xmlrpc.cgi" -CReporterBugzilla::CReporterBugzilla() : - m_pXmlrpcTransport(NULL), - m_pXmlrpcClient(NULL), - m_pCarriageParm(NULL), - m_sBugzillaURL("https://bugzilla.redhat.com"), - m_sBugzillaXMLRPC("https://bugzilla.redhat.com" + std::string(XML_RPC_SUFFIX)), - m_bNoSSLVerify(false), - m_bLoggedIn(false) -{} +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; -CReporterBugzilla::~CReporterBugzilla() -{} -void CReporterBugzilla::NewXMLRPCClient() -{ - m_pXmlrpcTransport = new xmlrpc_c::clientXmlTransport_curl( - xmlrpc_c::clientXmlTransport_curl::constrOpt() - .no_ssl_verifyhost(m_bNoSSLVerify) - .no_ssl_verifypeer(m_bNoSSLVerify) - ); - m_pXmlrpcClient = new xmlrpc_c::client_xml(m_pXmlrpcTransport); - m_pCarriageParm = new xmlrpc_c::carriageParm_curl0(m_sBugzillaXMLRPC); -} +static void 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 int32_t check_uuid_in_bugzilla(const char* component, const char* UUID); + +static bool check_cc_and_reporter(const uint32_t bug_id, const char* login); + +static void add_plus_one_cc(const uint32_t bug_id, const char* login); + +static void create_new_bug_description(const map_crash_report_t& pCrashReport, std::string& pDescription); + +static void get_product_and_version(const std::string& pRelease, + std::string& pProduct, + std::string& pVersion); -void CReporterBugzilla::DeleteXMLRPCClient() + +static void throw_if_fault_occurred(xmlrpc_env* e) { - if (m_pCarriageParm != NULL) - { - delete m_pCarriageParm; - m_pCarriageParm = NULL; - } - if (m_pXmlrpcClient != NULL) - { - delete m_pXmlrpcClient; - m_pXmlrpcClient = NULL; - } - if (m_pXmlrpcTransport != NULL) + if (e->fault_occurred) { - delete m_pXmlrpcTransport; - m_pXmlrpcTransport = NULL; + throw CABRTException(EXCEP_PLUGIN, ssprintf("XML-RPC Fault: %s(%d)", e->fault_string, e->fault_code));; } } +static void new_xmlrpc_client(const char* url, bool no_ssl_verify) +{ + xmlrpc_env_init(&env); + 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_fault_occurred(&env); + + server_info = xmlrpc_server_info_new(&env, url); + throw_if_fault_occurred(&env); +} + +static void destroy_xmlrpc_client() +{ + xmlrpc_server_info_free(server_info); + xmlrpc_env_clean(&env); + xmlrpc_client_destroy(client); + xmlrpc_client_teardown_global_const(); +} + +CReporterBugzilla::CReporterBugzilla() : + m_bNoSSLVerify(false), + m_bLoggedIn(false), + m_sBugzillaURL("https://bugzilla.redhat.com"), + m_sBugzillaXMLRPC("https://bugzilla.redhat.com" + std::string(XML_RPC_SUFFIX)) +{} + +CReporterBugzilla::~CReporterBugzilla() +{} + +#if 1 PRInt32 CReporterBugzilla::Base64Encode_cb(void *arg, const char *obuf, PRInt32 size) +#else +static PRint32 base64_encode_cb(void *arg, const char* obuff, PRInt32 size) +#endif { CReporterBugzilla* bz = static_cast<CReporterBugzilla*>(arg); int ii; @@ -66,150 +111,158 @@ PRInt32 CReporterBugzilla::Base64Encode_cb(void *arg, const char *obuf, PRInt32 return 1; } -void CReporterBugzilla::Login() + +static void login(const char* login, const char* passwd) { - xmlrpc_c::paramList paramList; - map_xmlrpc_params_t loginParams; - map_xmlrpc_params_t ret; - loginParams["login"] = xmlrpc_c::value_string(m_sLogin); - loginParams["password"] = xmlrpc_c::value_string(m_sPassword); - paramList.add(xmlrpc_c::value_struct(loginParams)); - xmlrpc_c::rpcPtr rpc(new xmlrpc_c::rpc("User.login", paramList)); - try - { - if( (m_sLogin == "") && (m_sPassword=="") ) - { - log("Empty login and password"); - throw std::string(_("Empty login and password. Please check Bugzilla.conf")); - } - rpc->call(m_pXmlrpcClient, m_pCarriageParm); - ret = xmlrpc_c::value_struct(rpc->getResult()); - std::stringstream ss; - ss << xmlrpc_c::value_int(ret["id"]); - log("Login id: %s", ss.str().c_str()); - } - catch (std::exception& e) - { - throw CABRTException(EXCEP_PLUGIN, std::string("CReporterBugzilla::Login(): ") + e.what()); - } - catch (std::string& s) - { - throw CABRTException(EXCEP_PLUGIN, s); - } + xmlrpc_value* result = NULL; + xmlrpc_value* param = NULL; + + param = xmlrpc_build_value(&env, "({s:s,s:s})", "login", login, "password", passwd); + throw_if_fault_occurred(&env); + + xmlrpc_client_call2(&env, client, server_info, "User.login", param, &result); + throw_if_fault_occurred(&env); } -void CReporterBugzilla::Logout() +static void logout() { - xmlrpc_c::paramList paramList; - paramList.add(xmlrpc_c::value_string("")); - xmlrpc_c::rpcPtr rpc(new xmlrpc_c::rpc("User.logout", paramList)); - try - { - rpc->call(m_pXmlrpcClient, m_pCarriageParm); - } - catch (std::exception& e) - { - throw CABRTException(EXCEP_PLUGIN, std::string("CReporterBugzilla::Logout(): ") + e.what()); - } + xmlrpc_value* result = NULL; + xmlrpc_value* param = NULL; + + param = xmlrpc_build_value(&env, "(s)", ""); + throw_if_fault_occurred(&env); + + xmlrpc_client_call2(&env, client, server_info, "User.logout", param, &result); + throw_if_fault_occurred(&env); } -bool CReporterBugzilla::CheckCCAndReporter(const std::string& pBugId) +static bool check_cc_and_reporter(const uint32_t bug_id, const char* login) { - xmlrpc_c::paramList paramList; - map_xmlrpc_params_t ret; + xmlrpc_value* param = NULL; + xmlrpc_value* result = NULL; + xmlrpc_value* reporter_member = NULL; + xmlrpc_value* cc_member = NULL; - paramList.add(xmlrpc_c::value_string(pBugId)); - xmlrpc_c::rpcPtr rpc(new xmlrpc_c::rpc("bugzilla.getBug", paramList)); - try - { - rpc->call(m_pXmlrpcClient, m_pCarriageParm); - ret = xmlrpc_c::value_struct(rpc->getResult()); - } - catch (std::exception& e) - { - throw CABRTException(EXCEP_PLUGIN, std::string("CReporterBugzilla::CheckCCAndReporter(): ") + e.what()); - } - std::string reporter = xmlrpc_c::value_string(ret["reporter"]); - if (reporter == m_sLogin) + const char* bug = to_string(bug_id).c_str(); + + param = xmlrpc_build_value(&env, "(s)", bug); + throw_if_fault_occurred(&env); + + xmlrpc_client_call2(&env, client, server_info, "bugzilla.getBug", param, &result); + throw_if_fault_occurred(&env); + + xmlrpc_struct_find_value(&env, result, "reporter", &reporter_member); + throw_if_fault_occurred(&env); + + if (reporter_member) { - return true; + const char* reporter = NULL; + xmlrpc_read_string(&env, reporter_member, &reporter); + throw_if_fault_occurred(&env); + + if (strcmp(reporter, login) == 0 ) + { + return true; + } } - std::vector<xmlrpc_c::value> ccs = xmlrpc_c::value_array(ret["cc"]).vectorValueValue(); - int ii; - for (ii = 0; ii < ccs.size(); ii++) + + xmlrpc_struct_find_value(&env, result, "cc", &cc_member); + throw_if_fault_occurred(&env); + + if (cc_member) { - std::string cc = xmlrpc_c::value_string(ccs[ii]); - if (cc == m_sLogin) + xmlrpc_value* item = NULL; + uint32_t array_size = xmlrpc_array_size(&env, cc_member); + + for (uint32_t i = 0; i < array_size; i++) { - return true; + xmlrpc_array_read_item(&env, cc_member, i, &item); // Correct + throw_if_fault_occurred(&env); + + const char* cc = NULL; + xmlrpc_read_string(&env, item, &cc); + throw_if_fault_occurred(&env); + + if (strcmp(cc, login) == 0) + { + return true; + } } } + + xmlrpc_DECREF(result); return false; } -void CReporterBugzilla::AddPlusOneCC(const std::string& pBugId) +static void add_plus_one_cc(const uint32_t bug_id, const char* login) { - xmlrpc_c::paramList paramList; - map_xmlrpc_params_t addCCParams; - map_xmlrpc_params_t ret; - map_xmlrpc_params_t updates; + xmlrpc_value* param = NULL; + xmlrpc_value* result = NULL; - std::vector<xmlrpc_c::value> CCList; - CCList.push_back(xmlrpc_c::value_string(m_sLogin)); - updates["add_cc"] = xmlrpc_c::value_array(CCList); + param = xmlrpc_build_value(&env, "({s:i,s:{s:(s)}})", "ids", bug_id, "updates", "add_cc", login); + throw_if_fault_occurred(&env); - addCCParams["ids"] = xmlrpc_c::value_int(atoi(pBugId.c_str())); - addCCParams["updates"] = xmlrpc_c::value_struct(updates); + xmlrpc_client_call2(&env, client, server_info, "Bug.update", param, &result); + throw_if_fault_occurred(&env); - paramList.add(xmlrpc_c::value_struct(addCCParams)); - xmlrpc_c::rpcPtr rpc(new xmlrpc_c::rpc("Bug.update", paramList)); - try - { - rpc->call(m_pXmlrpcClient, m_pCarriageParm); - } - catch (std::exception& e) - { - throw CABRTException(EXCEP_PLUGIN, std::string("CReporterBugzilla::AddPlusOneComment(): ") + e.what()); - } - ret = xmlrpc_c::value_struct(rpc->getResult()); + xmlrpc_DECREF(result); } -std::string CReporterBugzilla::CheckUUIDInBugzilla(const std::string& pComponent, const std::string& pUUID) +static int32_t check_uuid_in_bugzilla(const char* component, const char* UUID) { - xmlrpc_c::paramList paramList; - map_xmlrpc_params_t searchParams; - map_xmlrpc_params_t ret; - std::string quicksearch = "ALL component:\""+ pComponent +"\" statuswhiteboard:\""+ pUUID + "\""; - searchParams["quicksearch"] = xmlrpc_c::value_string(quicksearch.c_str()); - paramList.add(xmlrpc_c::value_struct(searchParams)); - xmlrpc_c::rpcPtr rpc(new xmlrpc_c::rpc("Bug.search", paramList)); - try - { - rpc->call(m_pXmlrpcClient, m_pCarriageParm); - } - catch (std::exception& e) - { - throw CABRTException(EXCEP_PLUGIN, std::string("CReporterBugzilla::CheckUUIDInBugzilla(): ") + e.what()); - } - ret = xmlrpc_c::value_struct(rpc->getResult()); - std::vector<xmlrpc_c::value> bugs = xmlrpc_c::value_array(ret["bugs"]).vectorValueValue(); - if (bugs.size() > 0) - { - map_xmlrpc_params_t bug; - std::stringstream ss; + xmlrpc_value* param = NULL; + xmlrpc_value* result = NULL; + xmlrpc_value* bugs_member = NULL; - bug = xmlrpc_c::value_struct(bugs[0]); - ss << xmlrpc_c::value_int(bug["bug_id"]); + xmlrpc_int bug_id; - log("Bug is already reported: %s", ss.str().c_str()); - update_client(_("Bug is already reported: ") + ss.str()); + char query[1024]; + snprintf(query, 1023, "ALL component:\"%s\" statuswhiteboard:\"%s\"", component, UUID); - return ss.str(); + param = xmlrpc_build_value(&env, "({s:s})", "quicksearch", query); + throw_if_fault_occurred(&env); + + xmlrpc_client_call2(&env, client, server_info, "Bug.search", param, &result); + throw_if_fault_occurred(&env); + + xmlrpc_struct_find_value(&env, result, "bugs", &bugs_member); + throw_if_fault_occurred(&env); + + if (bugs_member) + { + // when array size is equal 0 that means no bug reported + uint32_t array_size = xmlrpc_array_size(&env, bugs_member); + throw_if_fault_occurred(&env); + if( array_size == 0 ) + return -1; + + xmlrpc_value* item = NULL; + xmlrpc_array_read_item(&env, bugs_member, 0, &item); // Correct + throw_if_fault_occurred(&env); + + xmlrpc_value* bug = NULL; + xmlrpc_struct_find_value(&env, item,"bug_id", &bug); + throw_if_fault_occurred(&env); + if (bug) + { + xmlrpc_read_int(&env, bug, &bug_id); + log("Bug is already reported: %i", bug_id); + update_client(_("Bug is already reported: ") + to_string(bug_id)); + + xmlrpc_DECREF(result); + xmlrpc_DECREF(bug); + xmlrpc_DECREF(item); + xmlrpc_DECREF(bugs_member); + return bug_id; + } } - return ""; + + xmlrpc_DECREF(result); + xmlrpc_DECREF(bugs_member); + return -1; } -void CReporterBugzilla::CreateNewBugDescription(const map_crash_report_t& pCrashReport, std::string& pDescription) +static void create_new_bug_description(const map_crash_report_t& pCrashReport, std::string& pDescription) { std::string howToReproduce; std::string comment; @@ -264,9 +317,9 @@ void CReporterBugzilla::CreateNewBugDescription(const map_crash_report_t& pCrash } } -void CReporterBugzilla::GetProductAndVersion(const std::string& pRelease, - std::string& pProduct, - std::string& pVersion) +static void get_product_and_version(const std::string& pRelease, + std::string& pProduct, + std::string& pVersion) { if (pRelease.find("Rawhide") != std::string::npos) { @@ -295,53 +348,63 @@ void CReporterBugzilla::GetProductAndVersion(const std::string& pRelease, } } -std::string CReporterBugzilla::NewBug(const map_crash_report_t& pCrashReport) +static uint32_t new_bug(const map_crash_report_t& pCrashReport) { - xmlrpc_c::paramList paramList; - map_xmlrpc_params_t bugParams; - map_xmlrpc_params_t ret; + xmlrpc_value* param = NULL; + xmlrpc_value* result = NULL; + xmlrpc_value* id = NULL; + + xmlrpc_int bug_id = -1; + std::string package = pCrashReport.find(FILENAME_PACKAGE)->second[CD_CONTENT]; std::string component = pCrashReport.find(FILENAME_COMPONENT)->second[CD_CONTENT]; + std::string release = pCrashReport.find(FILENAME_RELEASE)->second[CD_CONTENT]; + std::string arch = pCrashReport.find(FILENAME_ARCHITECTURE)->second[CD_CONTENT]; + std::string uuid = pCrashReport.find(CD_UUID)->second[CD_CONTENT]; + std::string description; - std::string release = pCrashReport.find(FILENAME_RELEASE)->second[CD_CONTENT];; std::string product; std::string version; - std::stringstream bugId; - CreateNewBugDescription(pCrashReport, description); - GetProductAndVersion(release, product, version); - - bugParams["product"] = xmlrpc_c::value_string(product); - bugParams["component"] = xmlrpc_c::value_string(component); - bugParams["version"] = xmlrpc_c::value_string(version); - //bugParams["op_sys"] = xmlrpc_c::value_string("Linux"); - bugParams["summary"] = xmlrpc_c::value_string("[abrt] crash detected in " + package); - bugParams["description"] = xmlrpc_c::value_string(description); - bugParams["status_whiteboard"] = xmlrpc_c::value_string("abrt_hash:" + pCrashReport.find(CD_UUID)->second[CD_CONTENT]); - bugParams["platform"] = xmlrpc_c::value_string(pCrashReport.find(FILENAME_ARCHITECTURE)->second[CD_CONTENT]); - paramList.add(xmlrpc_c::value_struct(bugParams)); - - xmlrpc_c::rpcPtr rpc(new xmlrpc_c::rpc("Bug.create", paramList)); - try - { - rpc->call(m_pXmlrpcClient, m_pCarriageParm); - ret = xmlrpc_c::value_struct(rpc->getResult()); - bugId << xmlrpc_c::value_int(ret["id"]); - log("New bug id: %s", bugId.str().c_str()); - update_client(_("New bug id: ") + bugId.str()); - } - catch (std::exception& e) + std::string summary = "[abrt] crash detected in " + package; + std::string status_whiteboard = "abrt_hash:" + uuid; + + create_new_bug_description(pCrashReport, description); + get_product_and_version(release, product, version); + + param = xmlrpc_build_value(&env, "({s:s,s:s,s:s,s:s,s:s,s:s,s:s})", + "product", product.c_str(), + "component", component.c_str(), + "version", version.c_str(), + "summary", summary.c_str(), + "description", description.c_str(), + "status_whiteboard", status_whiteboard.c_str(), + "platform", arch.c_str() + ); + throw_if_fault_occurred(&env); + + xmlrpc_client_call2(&env, client, server_info, "Bug.create", param, &result); + throw_if_fault_occurred(&env); + + xmlrpc_struct_find_value(&env, result, "id", &id); + throw_if_fault_occurred(&env); + + if (id) { - throw CABRTException(EXCEP_PLUGIN, std::string("CReporterBugzilla::NewBug(): ") + e.what()); + xmlrpc_read_int(&env, id, &bug_id); + throw_if_fault_occurred(&env); + log("New bug id: %i", bug_id); + update_client(_("New bug id: ") + to_string(bug_id)); } - return bugId.str(); + + xmlrpc_DECREF(result); + return bug_id; } void CReporterBugzilla::AddAttachments(const std::string& pBugId, const map_crash_report_t& pCrashReport) { - xmlrpc_c::paramList paramList; - map_xmlrpc_params_t attachmentParams; - std::vector<xmlrpc_c::value> ret; - NSSBase64Encoder* base64; + xmlrpc_value* param = NULL; + xmlrpc_value* result = NULL; + NSSBase64Encoder* base64 = NULL; map_crash_report_t::const_iterator it; for (it = pCrashReport.begin(); it != pCrashReport.end(); it++) @@ -360,86 +423,77 @@ void CReporterBugzilla::AddAttachments(const std::string& pBugId, const map_cras it->second[CD_CONTENT].length()); NSSBase64Encoder_Destroy(base64, PR_FALSE); - paramList.add(xmlrpc_c::value_string(pBugId)); - attachmentParams["description"] = xmlrpc_c::value_string("File: " + it->first); - attachmentParams["filename"] = xmlrpc_c::value_string(it->first); - attachmentParams["contenttype"] = xmlrpc_c::value_string("text/plain"); - attachmentParams["data"] = xmlrpc_c::value_string(m_sAttchmentInBase64); - paramList.add(xmlrpc_c::value_struct(attachmentParams)); - xmlrpc_c::rpcPtr rpc(new xmlrpc_c::rpc("bugzilla.addAttachment", paramList)); - try - { - rpc->call(m_pXmlrpcClient, m_pCarriageParm); - ret = xmlrpc_c::value_array(rpc->getResult()).vectorValueValue(); - std::stringstream ss; - ss << xmlrpc_c::value_int(ret[0]); - log("New attachment id: %s", ss.str().c_str()); - } - catch (std::exception& e) - { - throw CABRTException(EXCEP_PLUGIN, std::string("CReporterBugzilla::AddAttachemnt(): ") + e.what()); - } + + std::string description = "File: " + it->first; + 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", m_sAttchmentInBase64.c_str() + ); + throw_if_fault_occurred(&env); + + xmlrpc_client_call2(&env, client, server_info, "bugzilla.addAttachment", param, &result); + throw_if_fault_occurred(&env); } } } std::string CReporterBugzilla::Report(const map_crash_report_t& pCrashReport, const std::string& pArgs) { - std::string package = pCrashReport.find(FILENAME_PACKAGE)->second[CD_CONTENT]; + int32_t bug_id = -1; + std::string component = pCrashReport.find(FILENAME_COMPONENT)->second[CD_CONTENT]; std::string uuid = pCrashReport.find(CD_UUID)->second[CD_CONTENT]; - std::string bugId; - - - NewXMLRPCClient(); - - m_bLoggedIn = false; try { + new_xmlrpc_client(m_sBugzillaXMLRPC.c_str(), m_bNoSSLVerify); + update_client(_("Checking for duplicates...")); - bugId = CheckUUIDInBugzilla(component, uuid); - if ( bugId != "" ) { - update_client(_("Logging into bugzilla...")); - Login(); - m_bLoggedIn = true; + bug_id = check_uuid_in_bugzilla(component.c_str(), uuid.c_str()); + + update_client(_("Logging into bugzilla...")); + if ((m_sLogin == "") && (m_sPassword=="")) + { + VERB3 log("Empty login and password"); + throw CABRTException(EXCEP_PLUGIN, std::string(_("Empty login and password. Please check Bugzilla.conf"))); + } + login(m_sLogin.c_str(), m_sPassword.c_str()); + + if (bug_id > 0) + { update_client(_("Checking CC...")); - if (!CheckCCAndReporter(bugId) && m_bLoggedIn) + if (!check_cc_and_reporter(bug_id, m_sLogin.c_str())) { - AddPlusOneCC(bugId); + add_plus_one_cc(bug_id, m_sLogin.c_str()); } - DeleteXMLRPCClient(); - return m_sBugzillaURL + "/show_bug.cgi?id=" + bugId; + destroy_xmlrpc_client(); + return m_sBugzillaURL + "/show_bug.cgi?id="+to_string(bug_id); } - update_client(_("Logging into bugzilla...")); - Login(); - m_bLoggedIn = true; - } - catch (CABRTException& e) - { - DeleteXMLRPCClient(); - throw CABRTException(EXCEP_PLUGIN, std::string("CReporterBugzilla::Report(): ") + e.what()); - return ""; - } + update_client(_("Creating new bug...")); + bug_id = new_bug(pCrashReport); + AddAttachments(to_string(bug_id), pCrashReport); - update_client(_("Creating new bug...")); - try - { - bugId = NewBug(pCrashReport); - AddAttachments(bugId, pCrashReport); update_client(_("Logging out...")); - Logout(); + logout(); + } catch (CABRTException& e) { - DeleteXMLRPCClient(); + destroy_xmlrpc_client(); throw CABRTException(EXCEP_PLUGIN, std::string("CReporterBugzilla::Report(): ") + e.what()); + return ""; } + destroy_xmlrpc_client(); + if (bug_id > 0) + { + return m_sBugzillaURL + "/show_bug.cgi?id="+to_string(bug_id); + } - DeleteXMLRPCClient(); - return m_sBugzillaURL + "/show_bug.cgi?id=" + bugId; - + return m_sBugzillaURL + "/show_bug.cgi?id="; } void CReporterBugzilla::SetSettings(const map_plugin_settings_t& pSettings) @@ -496,9 +550,9 @@ map_plugin_settings_t CReporterBugzilla::GetSettings() PLUGIN_INFO(REPORTER, CReporterBugzilla, "Bugzilla", - "0.0.3", + "0.0.4", "Check if a bug isn't already reported in a bugzilla " "and if not, report it.", - "zprikryl@redhat.com", + "npajkovs@redhat.com", "https://fedorahosted.org/abrt/wiki", PLUGINS_LIB_DIR"/Bugzilla.GTKBuilder"); diff --git a/lib/Plugins/Bugzilla.h b/lib/Plugins/Bugzilla.h index f6a8976..1fccbe4 100644 --- a/lib/Plugins/Bugzilla.h +++ b/lib/Plugins/Bugzilla.h @@ -3,41 +3,23 @@ #include "Plugin.h" #include "Reporter.h" -#include <xmlrpc-c/client.hpp> - #include <nssb64.h> +#include <xmlrpc-c/base.h> +#include <xmlrpc-c/client.h> class CReporterBugzilla : public CReporter { private: - typedef std::map<std::string, xmlrpc_c::value> map_xmlrpc_params_t; - - void NewXMLRPCClient(); - void DeleteXMLRPCClient(); + bool m_bNoSSLVerify; + bool m_bLoggedIn; static PRInt32 Base64Encode_cb(void *arg, const char *obuf, PRInt32 size); - void Login(); - void Logout(); - bool CheckCCAndReporter(const std::string& pBugId); - void AddPlusOneCC(const std::string& pBugId); - std::string CheckUUIDInBugzilla(const std::string& pComponent, const std::string& pUUID); - std::string NewBug(const map_crash_report_t& pCrashReport); void AddAttachments(const std::string& pBugId, const map_crash_report_t& pCrashReport); - void CreateNewBugDescription(const map_crash_report_t& pCrashReport, - std::string& pDescription); - void GetProductAndVersion(const std::string& pRelease, - std::string& pProduct, - std::string& pVersion); - xmlrpc_c::clientXmlTransport_curl* m_pXmlrpcTransport; - xmlrpc_c::client_xml* m_pXmlrpcClient; - xmlrpc_c::carriageParm_curl0 *m_pCarriageParm; std::string m_sBugzillaURL; std::string m_sBugzillaXMLRPC; std::string m_sLogin; std::string m_sPassword; std::string m_sAttchmentInBase64; - bool m_bNoSSLVerify; - bool m_bLoggedIn; public: CReporterBugzilla(); diff --git a/lib/Plugins/CCpp.cpp b/lib/Plugins/CCpp.cpp index 133811f..7d6708f 100644 --- a/lib/Plugins/CCpp.cpp +++ b/lib/Plugins/CCpp.cpp @@ -265,7 +265,7 @@ static void GetBacktrace(const std::string& pDebugDumpDir, std::string& pBacktra // when/if gdb supports it: // (https://bugzilla.redhat.com/show_bug.cgi?id=528668): //args[2] = (char*)"-ex"; - //args[3] = "set debug-file-directory /usr/lib/debug/.build-id:/var/cache/abrt-di/usr/lib/debug/.build-id"; + //args[3] = "set debug-file-directory /usr/lib/debug:/var/cache/abrt-di/usr/lib/debug"; /* * Unfortunately, "file BINARY_FILE" doesn't work well if BINARY_FILE * was deleted (as often happens during system updates): @@ -656,23 +656,22 @@ static void InstallDebugInfos(const std::string& pDebugDumpDir, std::string& bui { update_client(_("Searching for debug-info packages...")); - int pipein[2], pipeout[2]; //TODO: get rid of pipein. Can we use ExecVP? - xpipe(pipein); + int pipeout[2]; //TODO: can we use ExecVP? xpipe(pipeout); pid_t child = fork(); if (child < 0) { - /*close(pipein[0]); close(pipeout[0]); - why bother */ - /*close(pipein[1]); close(pipeout[1]); */ + /*close(pipeout[0]); - why bother */ + /*close(pipeout[1]); */ perror_msg_and_die("fork"); } if (child == 0) { - close(pipein[1]); close(pipeout[0]); - xmove_fd(pipein[0], STDIN_FILENO); xmove_fd(pipeout[1], STDOUT_FILENO); + close(STDIN_FILENO); + xopen("/dev/null", O_RDONLY); /* Not a good idea, we won't see any error messages */ /*close(STDERR_FILENO);*/ @@ -686,7 +685,6 @@ static void InstallDebugInfos(const std::string& pDebugDumpDir, std::string& bui exit(1); } - close(pipein[0]); close(pipeout[1]); update_client(_("Downloading and installing debug-info packages...")); @@ -834,7 +832,6 @@ void CAnalyzerCCpp::CreateReport(const std::string& pDebugDumpDir, int force) dd.Open(pDebugDumpDir); dd.SaveText(FILENAME_BACKTRACE, build_ids + backtrace); -log("BACKTRACE:'%s'", (build_ids + backtrace).c_str()); if (m_bMemoryMap) { dd.SaveText(FILENAME_MEMORYMAP, "memory map of the crashed C/C++ application, not implemented yet"); diff --git a/lib/Plugins/Makefile.am b/lib/Plugins/Makefile.am index bc032d7..a5c5a46 100644 --- a/lib/Plugins/Makefile.am +++ b/lib/Plugins/Makefile.am @@ -80,9 +80,9 @@ libSOSreport_la_LDFLAGS = -avoid-version # Bugzilla libBugzilla_la_SOURCES = Bugzilla.h Bugzilla.cpp -libBugzilla_la_LIBADD = $(XMLRPC_CPP_LIBS) $(XMLRPC_CLIENT_CPP_LIBS) $(NSS_LIBS) +libBugzilla_la_LIBADD = $(XMLRPC_LIBS) $(XMLRPC_CLIENT_LIBS) $(NSS_LIBS) libBugzilla_la_LDFLAGS = -avoid-version -libBugzilla_la_CPPFLAGS = $(XMLRPC_CPP_CFLAGS) $(XMLRPC_CLIENT_CPP_CFLAGS) $(NSS_CFLAGS) -I$(srcdir)/../../inc -I$(srcdir)/../Utils -DPLUGINS_LIB_DIR=\"$(PLUGINS_LIB_DIR)\" +libBugzilla_la_CPPFLAGS = $(XMLRPC_CFLAGS) $(XMLRPC_CLIENT_CFLAGS) $(NSS_CFLAGS) -I$(srcdir)/../../inc -I$(srcdir)/../Utils -DPLUGINS_LIB_DIR=\"$(PLUGINS_LIB_DIR)\" # TicketUploader libTicketUploader_la_SOURCES = TicketUploader.h TicketUploader.cpp diff --git a/lib/Utils/Makefile.am b/lib/Utils/Makefile.am index 713fe86..d24afa7 100644 --- a/lib/Utils/Makefile.am +++ b/lib/Utils/Makefile.am @@ -1,7 +1,10 @@ lib_LTLIBRARIES = libABRTUtils.la libABRTUtils_la_SOURCES = \ + time.cpp \ xfuncs.cpp \ + xconnect.cpp \ + skip_whitespace.cpp \ read_write.cpp \ logging.cpp \ copyfd.cpp \ diff --git a/lib/Utils/skip_whitespace.cpp b/lib/Utils/skip_whitespace.cpp new file mode 100644 index 0000000..816928b --- /dev/null +++ b/lib/Utils/skip_whitespace.cpp @@ -0,0 +1,22 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org> + * + * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. + */ +#include "abrtlib.h" + +char* skip_whitespace(const char *s) +{ + /* NB: isspace('\0') returns 0 */ + while (isspace(*s)) ++s; + + return (char *) s; +} + +char* skip_non_whitespace(const char *s) +{ + while (*s && !isspace(*s)) ++s; + + return (char *) s; +} diff --git a/lib/Utils/time.cpp b/lib/Utils/time.cpp new file mode 100644 index 0000000..37ade2c --- /dev/null +++ b/lib/Utils/time.cpp @@ -0,0 +1,65 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Licensed under GPL version 2, see file LICENSE in this tarball for details. + */ +#include "abrtlib.h" + +#define ENABLE_MONOTONIC_SYSCALL 1 + +#if ENABLE_MONOTONIC_SYSCALL + +#include <sys/syscall.h> +/* Old glibc (< 2.3.4) does not provide this constant. We use syscall + * directly so this definition is safe. */ +#ifndef CLOCK_MONOTONIC +#define CLOCK_MONOTONIC 1 +#endif + +/* libc has incredibly messy way of doing this, + * typically requiring -lrt. We just skip all this mess */ +static void get_mono(struct timespec *ts) +{ + if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, ts)) + error_msg_and_die("clock_gettime(MONOTONIC) failed"); +} +unsigned long long monotonic_ns(void) +{ + struct timespec ts; + get_mono(&ts); + return ts.tv_sec * 1000000000ULL + ts.tv_nsec; +} +unsigned long long monotonic_us(void) +{ + struct timespec ts; + get_mono(&ts); + return ts.tv_sec * 1000000ULL + ts.tv_nsec/1000; +} +unsigned monotonic_sec(void) +{ + struct timespec ts; + get_mono(&ts); + return ts.tv_sec; +} + +#else + +unsigned long long monotonic_ns(void) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000000000ULL + tv.tv_usec * 1000; +} +unsigned long long monotonic_us(void) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000000ULL + tv.tv_usec; +} +unsigned monotonic_sec(void) +{ + return time(NULL); +} + +#endif diff --git a/lib/Utils/xconnect.cpp b/lib/Utils/xconnect.cpp new file mode 100644 index 0000000..746edd6 --- /dev/null +++ b/lib/Utils/xconnect.cpp @@ -0,0 +1,416 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Connect to host at port using address resolution from getaddrinfo + * + * Licensed under GPLv2, see file LICENSE in this tarball for details. + */ + +#include "abrtlib.h" +#include <sys/socket.h> /* netinet/in.h needs it */ +#include <netinet/in.h> +#include <net/if.h> +#include <sys/un.h> +#include <netdb.h> + +#define ENABLE_FEATURE_IPV6 1 +#define ENABLE_FEATURE_PREFER_IPV4_ADDRESS 1 + +static const int const_int_1 = 1; + +void setsockopt_reuseaddr(int fd) +{ + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &const_int_1, sizeof(const_int_1)); +} +int setsockopt_broadcast(int fd) +{ + return setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &const_int_1, sizeof(const_int_1)); +} +int setsockopt_bindtodevice(int fd, const char *iface) +{ + int r; + struct ifreq ifr; + strncpy(ifr.ifr_name, iface, IFNAMSIZ); + /* NB: passing (iface, strlen(iface) + 1) does not work! + * (maybe it works on _some_ kernels, but not on 2.6.26) + * Actually, ifr_name is at offset 0, and in practice + * just giving char[IFNAMSIZ] instead of struct ifreq works too. + * But just in case it's not true on some obscure arch... */ + r = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)); + if (r) + perror_msg("can't bind to interface %s", iface); + return r; +} + +len_and_sockaddr* get_sock_lsa(int fd) +{ + len_and_sockaddr lsa; + len_and_sockaddr *lsa_ptr; + + lsa.len = LSA_SIZEOF_SA; + if (getsockname(fd, &lsa.u.sa, &lsa.len) != 0) + return NULL; + + lsa_ptr = (len_and_sockaddr *)xzalloc(LSA_LEN_SIZE + lsa.len); + if (lsa.len > LSA_SIZEOF_SA) { /* rarely (if ever) happens */ + lsa_ptr->len = lsa.len; + getsockname(fd, &lsa_ptr->u.sa, &lsa_ptr->len); + } else { + memcpy(lsa_ptr, &lsa, LSA_LEN_SIZE + lsa.len); + } + return lsa_ptr; +} + +void xconnect(int s, const struct sockaddr *s_addr, socklen_t addrlen) +{ + if (connect(s, s_addr, addrlen) < 0) { + close(s); + if (s_addr->sa_family == AF_INET) + perror_msg_and_die("%s (%s)", + "cannot connect to remote host", + inet_ntoa(((struct sockaddr_in *)s_addr)->sin_addr)); + perror_msg_and_die("cannot connect to remote host"); + } +} + +/* Return port number for a service. + * If "port" is a number use it as the port. + * If "port" is a name it is looked up in /etc/services, + * if it isnt found return default_port + */ +unsigned lookup_port(const char *port, const char *protocol, unsigned default_port) +{ + unsigned port_nr = default_port; + if (port) { + int old_errno; + char *end; + + /* Since this is a lib function, we're not allowed to reset errno to 0. + * Doing so could break an app that is deferring checking of errno. */ + old_errno = errno; + errno = 0; + port_nr = strtoul(port, &end, 10); + if (errno || *end || port_nr > 65535) { + struct servent *tserv = getservbyname(port, protocol); + port_nr = default_port; + if (tserv) + port_nr = ntohs(tserv->s_port); + } + errno = old_errno; + } + return (uint16_t)port_nr; +} + +int get_nport(const struct sockaddr *sa) +{ +#if ENABLE_FEATURE_IPV6 + if (sa->sa_family == AF_INET6) { + return ((struct sockaddr_in6*)sa)->sin6_port; + } +#endif + if (sa->sa_family == AF_INET) { + return ((struct sockaddr_in*)sa)->sin_port; + } + /* What? UNIX socket? IPX?? :) */ + return -1; +} + +void set_nport(len_and_sockaddr *lsa, unsigned port) +{ +#if ENABLE_FEATURE_IPV6 + if (lsa->u.sa.sa_family == AF_INET6) { + lsa->u.sin6.sin6_port = port; + return; + } +#endif + if (lsa->u.sa.sa_family == AF_INET) { + lsa->u.sin.sin_port = port; + return; + } + /* What? UNIX socket? IPX?? :) */ +} + +/* We hijack this constant to mean something else */ +/* It doesn't hurt because we will remove this bit anyway */ +#define DIE_ON_ERROR AI_CANONNAME + +/* host: "1.2.3.4[:port]", "www.google.com[:port]" + * port: if neither of above specifies port # */ +static len_and_sockaddr* str2sockaddr( + const char *host, int port, + sa_family_t af, + int ai_flags) +{ + int rc; + len_and_sockaddr *r; + struct addrinfo *result = NULL; + struct addrinfo *used_res; + const char *org_host = host; /* only for error msg */ + const char *cp; + struct addrinfo hint; + + r = NULL; + + /* Ugly parsing of host:addr */ + if (ENABLE_FEATURE_IPV6 && host[0] == '[') { + /* Even uglier parsing of [xx]:nn */ + host++; + cp = strchr(host, ']'); + if (!cp || (cp[1] != ':' && cp[1] != '\0')) { + /* Malformed: must be [xx]:nn or [xx] */ + error_msg("bad address '%s'", org_host); + if (ai_flags & DIE_ON_ERROR) + xfunc_die(); + return NULL; + } + } else { + cp = strrchr(host, ':'); + if (ENABLE_FEATURE_IPV6 && cp && strchr(host, ':') != cp) { + /* There is more than one ':' (e.g. "::1") */ + cp = NULL; /* it's not a port spec */ + } + } + if (cp) { /* points to ":" or "]:" */ + int sz = cp - host + 1; + char *hbuf = (char*)alloca(sz); + hbuf[--sz] = '\0'; + host = strncpy(hbuf, host, sz); + if (ENABLE_FEATURE_IPV6 && *cp != ':') { + cp++; /* skip ']' */ + if (*cp == '\0') /* [xx] without port */ + goto skip; + } + cp++; /* skip ':' */ + char *end; + errno = 0; + port = strtoul(cp, &end, 10); + if (errno || *end || (unsigned)port > 0xffff) { + error_msg("bad port spec '%s'", org_host); + if (ai_flags & DIE_ON_ERROR) + xfunc_die(); + return NULL; + } + skip: ; + } + + memset(&hint, 0 , sizeof(hint)); +#if !ENABLE_FEATURE_IPV6 + hint.ai_family = AF_INET; /* do not try to find IPv6 */ +#else + hint.ai_family = af; +#endif + /* Needed. Or else we will get each address thrice (or more) + * for each possible socket type (tcp,udp,raw...): */ + hint.ai_socktype = SOCK_STREAM; + hint.ai_flags = ai_flags & ~DIE_ON_ERROR; + rc = getaddrinfo(host, NULL, &hint, &result); + if (rc || !result) { + error_msg("bad address '%s'", org_host); + if (ai_flags & DIE_ON_ERROR) + xfunc_die(); + goto ret; + } + used_res = result; +#if ENABLE_FEATURE_PREFER_IPV4_ADDRESS + while (1) { + if (used_res->ai_family == AF_INET) + break; + used_res = used_res->ai_next; + if (!used_res) { + used_res = result; + break; + } + } +#endif + r = (len_and_sockaddr *)xmalloc(offsetof(len_and_sockaddr, u.sa) + used_res->ai_addrlen); + r->len = used_res->ai_addrlen; + memcpy(&r->u.sa, used_res->ai_addr, used_res->ai_addrlen); + set_nport(r, htons(port)); + ret: + freeaddrinfo(result); + return r; +} +#if !ENABLE_FEATURE_IPV6 +#define str2sockaddr(host, port, af, ai_flags) str2sockaddr(host, port, ai_flags) +#endif + +#if ENABLE_FEATURE_IPV6 +len_and_sockaddr* host_and_af2sockaddr(const char *host, int port, sa_family_t af) +{ + return str2sockaddr(host, port, af, 0); +} + +len_and_sockaddr* xhost_and_af2sockaddr(const char *host, int port, sa_family_t af) +{ + return str2sockaddr(host, port, af, DIE_ON_ERROR); +} +#endif + +len_and_sockaddr* host2sockaddr(const char *host, int port) +{ + return str2sockaddr(host, port, AF_UNSPEC, 0); +} + +len_and_sockaddr* xhost2sockaddr(const char *host, int port) +{ + return str2sockaddr(host, port, AF_UNSPEC, DIE_ON_ERROR); +} + +len_and_sockaddr* xdotted2sockaddr(const char *host, int port) +{ + return str2sockaddr(host, port, AF_UNSPEC, AI_NUMERICHOST | DIE_ON_ERROR); +} + +#undef xsocket_type +int xsocket_type(len_and_sockaddr **lsap, int family, int sock_type) +{ + len_and_sockaddr *lsa; + int fd; + int len; + +#if ENABLE_FEATURE_IPV6 + if (family == AF_UNSPEC) { + fd = socket(AF_INET6, sock_type, 0); + if (fd >= 0) { + family = AF_INET6; + goto done; + } + family = AF_INET; + } +#endif + fd = xsocket(family, sock_type, 0); + len = sizeof(struct sockaddr_in); +#if ENABLE_FEATURE_IPV6 + if (family == AF_INET6) { + done: + len = sizeof(struct sockaddr_in6); + } +#endif + lsa = (len_and_sockaddr *)xzalloc(offsetof(len_and_sockaddr, u.sa) + len); + lsa->len = len; + lsa->u.sa.sa_family = family; + *lsap = lsa; + return fd; +} + +int xsocket_stream(len_and_sockaddr **lsap) +{ + return xsocket_type(lsap, AF_UNSPEC, SOCK_STREAM); +} + +static int create_and_bind_or_die(const char *bindaddr, int port, int sock_type) +{ + int fd; + len_and_sockaddr *lsa; + + if (bindaddr && bindaddr[0]) { + lsa = xdotted2sockaddr(bindaddr, port); + /* user specified bind addr dictates family */ + fd = xsocket(lsa->u.sa.sa_family, sock_type, 0); + } else { + fd = xsocket_type(&lsa, AF_UNSPEC, sock_type); + set_nport(lsa, htons(port)); + } + setsockopt_reuseaddr(fd); + xbind(fd, &lsa->u.sa, lsa->len); + free(lsa); + return fd; +} + +int create_and_bind_stream_or_die(const char *bindaddr, int port) +{ + return create_and_bind_or_die(bindaddr, port, SOCK_STREAM); +} + +int create_and_bind_dgram_or_die(const char *bindaddr, int port) +{ + return create_and_bind_or_die(bindaddr, port, SOCK_DGRAM); +} + + +int create_and_connect_stream_or_die(const char *peer, int port) +{ + int fd; + len_and_sockaddr *lsa; + + lsa = xhost2sockaddr(peer, port); + fd = xsocket(lsa->u.sa.sa_family, SOCK_STREAM, 0); + setsockopt_reuseaddr(fd); + xconnect(fd, &lsa->u.sa, lsa->len); + free(lsa); + return fd; +} + +int xconnect_stream(const len_and_sockaddr *lsa) +{ + int fd = xsocket(lsa->u.sa.sa_family, SOCK_STREAM, 0); + xconnect(fd, &lsa->u.sa, lsa->len); + return fd; +} + +/* We hijack this constant to mean something else */ +/* It doesn't hurt because we will add this bit anyway */ +#define IGNORE_PORT NI_NUMERICSERV +static char* sockaddr2str(const struct sockaddr *sa, int flags) +{ + char host[128]; + char serv[16]; + int rc; + socklen_t salen; + + salen = LSA_SIZEOF_SA; +#if ENABLE_FEATURE_IPV6 + if (sa->sa_family == AF_INET) + salen = sizeof(struct sockaddr_in); + if (sa->sa_family == AF_INET6) + salen = sizeof(struct sockaddr_in6); +#endif + rc = getnameinfo(sa, salen, + host, sizeof(host), + /* can do ((flags & IGNORE_PORT) ? NULL : serv) but why bother? */ + serv, sizeof(serv), + /* do not resolve port# into service _name_ */ + flags | NI_NUMERICSERV + ); + if (rc) + return NULL; + if (flags & IGNORE_PORT) + return xstrdup(host); +#if ENABLE_FEATURE_IPV6 + if (sa->sa_family == AF_INET6) { + if (strchr(host, ':')) /* heh, it's not a resolved hostname */ + return xasprintf("[%s]:%s", host, serv); + /*return xasprintf("%s:%s", host, serv);*/ + /* - fall through instead */ + } +#endif + /* For now we don't support anything else, so it has to be INET */ + /*if (sa->sa_family == AF_INET)*/ + return xasprintf("%s:%s", host, serv); + /*return xstrdup(host);*/ +} + +char* xmalloc_sockaddr2host(const struct sockaddr *sa) +{ + return sockaddr2str(sa, 0); +} + +char* xmalloc_sockaddr2host_noport(const struct sockaddr *sa) +{ + return sockaddr2str(sa, IGNORE_PORT); +} + +char* xmalloc_sockaddr2hostonly_noport(const struct sockaddr *sa) +{ + return sockaddr2str(sa, NI_NAMEREQD | IGNORE_PORT); +} +char* xmalloc_sockaddr2dotted(const struct sockaddr *sa) +{ + return sockaddr2str(sa, NI_NUMERICHOST); +} + +char* xmalloc_sockaddr2dotted_noport(const struct sockaddr *sa) +{ + return sockaddr2str(sa, NI_NUMERICHOST | IGNORE_PORT); +} diff --git a/lib/Utils/xfuncs.cpp b/lib/Utils/xfuncs.cpp index d256c19..9c8b0f1 100644 --- a/lib/Utils/xfuncs.cpp +++ b/lib/Utils/xfuncs.cpp @@ -5,6 +5,22 @@ */ #include "abrtlib.h" +/* Turn on nonblocking I/O on a fd */ +int ndelay_on(int fd) +{ + return fcntl(fd, F_SETFL, fcntl(fd,F_GETFL) | O_NONBLOCK); +} + +int ndelay_off(int fd) +{ + return fcntl(fd, F_SETFL, fcntl(fd,F_GETFL) & ~O_NONBLOCK); +} + +int close_on_exec_on(int fd) +{ + return fcntl(fd, F_SETFD, FD_CLOEXEC); +} + // Die if we can't allocate size bytes of memory. void* xmalloc(size_t size) { |
