summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorJiri Moskovcak <jmoskovc@redhat.com>2009-10-26 16:28:12 +0100
committerJiri Moskovcak <jmoskovc@redhat.com>2009-10-26 16:28:12 +0100
commitbe0c8d7252ae74610d885e21f47e454f8538898f (patch)
treee3da4305d7e8ea44d7732051013a71198e664aea /lib
parent53ed713b135762ad7b572f39301d80a646173820 (diff)
parentb1756b440359c381ebafd62709ddcfa78ea74805 (diff)
Merge branch 'master' of git://git.fedorahosted.org/git/abrt
Diffstat (limited to 'lib')
-rw-r--r--lib/Plugins/Bugzilla.cpp544
-rw-r--r--lib/Plugins/Bugzilla.h26
-rw-r--r--lib/Plugins/CCpp.cpp15
-rw-r--r--lib/Plugins/Makefile.am4
-rw-r--r--lib/Utils/Makefile.am3
-rw-r--r--lib/Utils/skip_whitespace.cpp22
-rw-r--r--lib/Utils/time.cpp65
-rw-r--r--lib/Utils/xconnect.cpp416
-rw-r--r--lib/Utils/xfuncs.cpp16
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)
{