summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorKarel Klic <kklic@redhat.com>2009-12-18 19:12:50 +0100
committerKarel Klic <kklic@redhat.com>2009-12-18 19:12:50 +0100
commite7661d7e411172ddad8838040ded025ad6bfbb14 (patch)
treef2451b553b4fcf959bd2bfc29172f9fb855e5fdd /lib
parentce1904e24b576a7356488852a240d777717b2598 (diff)
parent46b2fb8df8d4e025f5bbdd9f53be1f658a9e82c6 (diff)
downloadabrt-e7661d7e411172ddad8838040ded025ad6bfbb14.tar.gz
abrt-e7661d7e411172ddad8838040ded025ad6bfbb14.tar.xz
abrt-e7661d7e411172ddad8838040ded025ad6bfbb14.zip
Merge branch 'master' of git://git.fedorahosted.org/git/abrt
Diffstat (limited to 'lib')
-rw-r--r--lib/Plugins/CCpp.cpp46
-rw-r--r--lib/Plugins/Catcut.cpp13
-rw-r--r--lib/Plugins/FileTransfer.cpp12
-rw-r--r--lib/Plugins/Firefox.cpp8
-rw-r--r--lib/Plugins/Kerneloops.conf20
-rw-r--r--lib/Plugins/KerneloopsReporter.cpp4
-rw-r--r--lib/Plugins/Mailx.cpp2
-rw-r--r--lib/Plugins/SQLite3.cpp21
-rw-r--r--lib/Plugins/TicketUploader.cpp12
-rw-r--r--lib/Utils/CrashTypesSocket.cpp2
-rw-r--r--lib/Utils/DebugDump.cpp16
-rw-r--r--lib/Utils/DebugDump.h4
-rw-r--r--lib/Utils/Makefile.am2
-rw-r--r--lib/Utils/abrt_xmlrpc.cpp10
-rw-r--r--lib/Utils/abrt_xmlrpc.h5
-rw-r--r--lib/Utils/daemon.cpp139
-rw-r--r--lib/Utils/xatonum.cpp50
17 files changed, 300 insertions, 66 deletions
diff --git a/lib/Plugins/CCpp.cpp b/lib/Plugins/CCpp.cpp
index 37a2c8b..99c1c77 100644
--- a/lib/Plugins/CCpp.cpp
+++ b/lib/Plugins/CCpp.cpp
@@ -37,7 +37,7 @@
using namespace std;
#define CORE_PATTERN_IFACE "/proc/sys/kernel/core_pattern"
-#define CORE_PATTERN "|"CCPP_HOOK_PATH" "DEBUG_DUMPS_DIR" %p %s %u"
+#define CORE_PATTERN "|"CCPP_HOOK_PATH" "DEBUG_DUMPS_DIR" %p %s %u %c"
#define FILENAME_COREDUMP "coredump"
#define FILENAME_BACKTRACE "backtrace"
@@ -96,7 +96,7 @@ static string concat_str_vector(char **strings)
}
/* Returns status. See `man 2 wait` for status information. */
-static int ExecVP(char **pArgs, uid_t uid, string& pOutput)
+static int ExecVP(char **pArgs, uid_t uid, int redirect_stderr, string& pOutput)
{
int pipeout[2];
pid_t child;
@@ -114,8 +114,6 @@ static int ExecVP(char **pArgs, uid_t uid, string& pOutput)
xmove_fd(pipeout[1], STDOUT_FILENO);
/* Make sure stdin is safely open to nothing */
xmove_fd(xopen("/dev/null", O_RDONLY), STDIN_FILENO);
- /* Not a good idea, we won't see any error messages */
- /* close(STDERR_FILENO); */
struct passwd* pw = getpwuid(uid);
gid_t gid = pw ? pw->pw_gid : uid;
@@ -136,6 +134,11 @@ static int ExecVP(char **pArgs, uid_t uid, string& pOutput)
unsetenv("LC_NUMERIC");
unsetenv("LC_TIME");
+ if (redirect_stderr)
+ {
+ /* We want parent to see errors in the same stream */
+ xdup2(STDOUT_FILENO, STDERR_FILENO);
+ }
execvp(pArgs[0], pArgs);
/* VERB1 since sometimes we expect errors here */
VERB1 perror_msg("Can't execute '%s'", pArgs[0]);
@@ -309,7 +312,7 @@ static void GetBacktrace(const char *pDebugDumpDir,
args[11] = (char*)"info sharedlib";
args[12] = NULL;
- ExecVP(args, atoi(UID.c_str()), pBacktrace);
+ ExecVP(args, xatoi_u(UID.c_str()), /*redirect_stderr:*/ 1, pBacktrace);
}
static void GetIndependentBuildIdPC(const char *unstrip_n_output,
@@ -355,7 +358,7 @@ static string run_unstrip_n(const char *pDebugDumpDir)
args[3] = NULL;
string output;
- ExecVP(args, atoi(UID.c_str()), output);
+ ExecVP(args, xatoi_u(UID.c_str()), /*redirect_stderr:*/ 0, output);
free(args[1]);
@@ -386,18 +389,18 @@ static void InstallDebugInfos(const char *pDebugDumpDir,
close(pipeout[0]);
xmove_fd(pipeout[1], STDOUT_FILENO);
xmove_fd(xopen("/dev/null", O_RDONLY), STDIN_FILENO);
- /* Not a good idea, we won't see any error messages */
- /*close(STDERR_FILENO);*/
-
- setsid();
char *coredump = xasprintf("%s/"FILENAME_COREDUMP, pDebugDumpDir);
/* SELinux guys are not happy with /tmp, using /var/run/abrt */
char *tempdir = xasprintf(LOCALSTATEDIR"/run/abrt/tmp-%u-%lu", (int)getpid(), (long)time(NULL));
/* log() goes to stderr/syslog, it's ok to use it here */
VERB1 log("Executing: %s %s %s %s", "abrt-debuginfo-install", coredump, tempdir, debuginfo_dirs);
+ /* We want parent to see errors in the same stream */
+ xdup2(STDOUT_FILENO, STDERR_FILENO);
execlp("abrt-debuginfo-install", "abrt-debuginfo-install", coredump, tempdir, debuginfo_dirs, NULL);
- exit(1);
+ perror_msg("Can't execute '%s'", "abrt-debuginfo-install");
+ /* Serious error (1 means "some debuginfos not found") */
+ exit(2);
}
close(pipeout[1]);
@@ -436,9 +439,20 @@ static void InstallDebugInfos(const char *pDebugDumpDir,
update_client("%s", buff);
}
}
-
fclose(pipeout_fp);
- wait(NULL);
+
+ int status = 0;
+ while (waitpid(child, &status, 0) < 0 && errno == EINTR)
+ continue;
+ if (WIFEXITED(status))
+ {
+ if (WEXITSTATUS(status) > 1)
+ error_msg("%s exited with %u", "abrt-debuginfo-install", (int)WEXITSTATUS(status));
+ }
+ else
+ {
+ error_msg("%s killed by signal %u", "abrt-debuginfo-install", (int)WTERMSIG(status));
+ }
}
static double get_dir_size(const char *dirname,
@@ -564,7 +578,7 @@ string CAnalyzerCCpp::GetGlobalUUID(const char *pDebugDumpDir)
close(pipeout[0]); /* read side of the pipe */
/* abrt-backtrace is executed under the user's uid and gid. */
- uid_t uid = atoi(uid_str.c_str());
+ uid_t uid = xatoi_u(uid_str.c_str());
struct passwd* pw = getpwuid(uid);
gid_t gid = pw ? pw->pw_gid : uid;
setgroups(1, &gid);
@@ -659,7 +673,7 @@ void CAnalyzerCCpp::CreateReport(const char *pDebugDumpDir, int force)
dd.Close(); /* do not keep dir locked longer than needed */
string build_ids;
- if (m_bInstallDebugInfo && DebuginfoCheckPolkit(atoi(UID.c_str())))
+ if (m_bInstallDebugInfo && DebuginfoCheckPolkit(xatoi_u(UID.c_str())))
{
if (m_nDebugInfoCacheMB > 0)
{
@@ -750,7 +764,7 @@ void CAnalyzerCCpp::SetSettings(const map_plugin_settings_t& pSettings)
it = pSettings.find("DebugInfoCacheMB");
if (it != end)
{
- m_nDebugInfoCacheMB = atoi(it->second.c_str());
+ m_nDebugInfoCacheMB = xatou(it->second.c_str());
}
it = pSettings.find("InstallDebugInfo");
if (it == end) //compat, remove after 0.0.11
diff --git a/lib/Plugins/Catcut.cpp b/lib/Plugins/Catcut.cpp
index ebddfdd..a56015d 100644
--- a/lib/Plugins/Catcut.cpp
+++ b/lib/Plugins/Catcut.cpp
@@ -1,6 +1,3 @@
-#include <xmlrpc-c/base.h>
-#include <xmlrpc-c/client.h>
-#include <curl/curl.h>
#include "abrtlib.h"
#include "abrt_xmlrpc.h"
#include "Catcut.h"
@@ -18,11 +15,7 @@ using namespace std;
static int
put_stream(const char *pURL, FILE* f, size_t content_length)
{
- CURL* curl = curl_easy_init();
- if (!curl)
- {
- throw CABRTException(EXCEP_PLUGIN, "put_stream: can't initialize curl library");
- }
+ CURL* curl = xcurl_easy_init();
/* enable uploading */
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
/* specify target */
@@ -510,12 +503,12 @@ void CReporterCatcut::SetSettings(const map_plugin_settings_t& pSettings)
it = pSettings.find("RetryCount");
if (it != end)
{
- m_nRetryCount = atoi(it->second.c_str());
+ m_nRetryCount = xatoi_u(it->second.c_str());
}
it = pSettings.find("RetryDelay");
if (it != end)
{
- m_nRetryDelay = atoi(it->second.c_str());
+ m_nRetryDelay = xatoi_u(it->second.c_str());
}
}
diff --git a/lib/Plugins/FileTransfer.cpp b/lib/Plugins/FileTransfer.cpp
index c98645c..60e1e66 100644
--- a/lib/Plugins/FileTransfer.cpp
+++ b/lib/Plugins/FileTransfer.cpp
@@ -35,8 +35,8 @@
#include <libtar.h>
#include <bzlib.h>
#include <zlib.h>
-#include <curl/curl.h>
#include "abrtlib.h"
+#include "abrt_xmlrpc.h" /* for xcurl_easy_init */
#include "FileTransfer.h"
#include "DebugDump.h"
#include "ABRTException.h"
@@ -85,11 +85,7 @@ void CFileTransfer::SendFile(const char *pURL, const char *pFilename)
fclose(f);
throw CABRTException(EXCEP_PLUGIN, "Can't stat archive file '%s'", pFilename);
}
- curl = curl_easy_init();
- if (!curl)
- {
- throw CABRTException(EXCEP_PLUGIN, "Curl library init error");
- }
+ curl = xcurl_easy_init();
/* enable uploading */
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
/* specify target */
@@ -388,13 +384,13 @@ void CFileTransfer::SetSettings(const map_plugin_settings_t& pSettings)
it = pSettings.find("RetryCount");
if (it != end)
{
- m_nRetryCount = atoi(it->second.c_str());
+ m_nRetryCount = xatoi_u(it->second.c_str());
}
it = pSettings.find("RetryDelay");
if (it != end)
{
- m_nRetryDelay = atoi(it->second.c_str());
+ m_nRetryDelay = xatoi_u(it->second.c_str());
}
it = pSettings.find("ArchiveType");
diff --git a/lib/Plugins/Firefox.cpp b/lib/Plugins/Firefox.cpp
index bcc5948..2bb7f9c 100644
--- a/lib/Plugins/Firefox.cpp
+++ b/lib/Plugins/Firefox.cpp
@@ -281,7 +281,7 @@ static void GetBacktrace(const char *pDebugDumpDir, std::string& pBacktrace)
args[9] = (char*)"thread apply all backtrace full";
args[10] = NULL;
- ExecVP(args, atoi(UID.c_str()), pBacktrace);
+ ExecVP(args, xatoi_u(UID.c_str()), pBacktrace);
free(args[5]);
free(args[7]);
@@ -454,7 +454,7 @@ static std::string run_unstrip_n(const char *pDebugDumpDir)
args[3] = NULL;
std::string output;
- ExecVP(args, atoi(UID.c_str()), output);
+ ExecVP(args, xatoi_u(UID.c_str()), output);
free(args[1]);
@@ -886,7 +886,7 @@ void CAnalyzerFirefox::CreateReport(const char *pDebugDumpDir, int force)
dd.Close(); /* do not keep dir locked longer than needed */
std::string build_ids;
- if (m_bInstallDebugInfo && DebuginfoCheckPolkit(atoi(UID.c_str()))) {
+ if (m_bInstallDebugInfo && DebuginfoCheckPolkit(xatoi_u(UID.c_str()))) {
if (m_nDebugInfoCacheMB > 0)
trim_debuginfo_cache(m_nDebugInfoCacheMB);
InstallDebugInfos(pDebugDumpDir, build_ids);
@@ -974,7 +974,7 @@ void CAnalyzerFirefox::SetSettings(const map_plugin_settings_t& pSettings)
it = pSettings.find("DebugInfoCacheMB");
if (it != end)
{
- m_nDebugInfoCacheMB = atoi(it->second.c_str());
+ m_nDebugInfoCacheMB = xatou(it->second.c_str());
}
it = pSettings.find("InstallDebugInfo");
if (it == end) //compat, remove after 0.0.11
diff --git a/lib/Plugins/Kerneloops.conf b/lib/Plugins/Kerneloops.conf
index a014153..5623596 100644
--- a/lib/Plugins/Kerneloops.conf
+++ b/lib/Plugins/Kerneloops.conf
@@ -1,15 +1,17 @@
-# compatibility with kerneloops.org tool
+# Do we want kernel oopses to be visible to any user?
+# Set to "yes" for compatibility with kerneloops.org tool.
InformAllUsers = yes
+# Automatically perform reporting.
+# With default abrt.conf, it invokes KerneloopsReporter
+# and thus reports oops to kerneloops.org.
+# ("root" because all oopses are filed by abrt with user "root")
AutoReportUIDs = root
-# KerneloopsReporter configuration. Reports kernel crashes collected by the addon.
-################################################################################
+# Kerneloops Scanner configuration
+##################################
+SysLogFile = /var/log/messages
-# kerneloops.org
+# KerneloopsReporter configuration
+##################################
SubmitURL = http://submit.kerneloops.org/submitoops.php
-
-# Kerneloops Scanner configuration.
-################################################################################
-
-SysLogFile = /var/log/messages
diff --git a/lib/Plugins/KerneloopsReporter.cpp b/lib/Plugins/KerneloopsReporter.cpp
index 26430be..5cb525b 100644
--- a/lib/Plugins/KerneloopsReporter.cpp
+++ b/lib/Plugins/KerneloopsReporter.cpp
@@ -25,9 +25,9 @@
*/
#include "abrtlib.h"
+#include "abrt_xmlrpc.h" /* for xcurl_easy_init */
#include "KerneloopsReporter.h"
#include "CommLayerInner.h"
-#include <curl/curl.h>
#include "ABRTException.h"
#define FILENAME_KERNELOOPS "kerneloops"
@@ -64,7 +64,7 @@ static int http_post_to_kerneloops_site(const char *url, const char *oopsdata)
struct curl_httppost *post = NULL;
struct curl_httppost *last = NULL;
- handle = curl_easy_init();
+ handle = xcurl_easy_init();
curl_easy_setopt(handle, CURLOPT_URL, url);
curl_formadd(&post, &last,
diff --git a/lib/Plugins/Mailx.cpp b/lib/Plugins/Mailx.cpp
index b06edeb..6904c16 100644
--- a/lib/Plugins/Mailx.cpp
+++ b/lib/Plugins/Mailx.cpp
@@ -163,7 +163,7 @@ std::string CMailx::Report(const map_crash_report_t& pCrashReport,
update_client(_("Sending an email..."));
const char *uid_str = pCrashReport.find(CD_MWUID)->second[CD_CONTENT].c_str();
- exec_and_feed_input(atoi(uid_str), emailBody.c_str(), args);
+ exec_and_feed_input(xatoi_u(uid_str), emailBody.c_str(), args);
while (*args)
{
diff --git a/lib/Plugins/SQLite3.cpp b/lib/Plugins/SQLite3.cpp
index d95c273..1979f24 100644
--- a/lib/Plugins/SQLite3.cpp
+++ b/lib/Plugins/SQLite3.cpp
@@ -198,9 +198,9 @@ static bool check_table(sqlite3 *db)
if (pos != string::npos)
{
string tableVersion = tableName.substr(pos + 2);
- if (atoi(tableVersion.c_str()) < ABRT_TABLE_VERSION)
+ if (xatoi_u(tableVersion.c_str()) < ABRT_TABLE_VERSION)
{
- update_from_old_ver(db, atoi(tableVersion.c_str()));
+ update_from_old_ver(db, xatoi_u(tableVersion.c_str()));
}
return true;
}
@@ -238,7 +238,18 @@ CSQLite3::CSQLite3() :
CSQLite3::~CSQLite3()
{
- DisConnect();
+ /* Paranoia. In C++, destructor will abort() if it was called while unwinding
+ * the stack and it throws an exception.
+ */
+ try
+ {
+ DisConnect();
+ m_sDBPath.clear();
+ }
+ catch (...)
+ {
+ error_msg_and_die("Internal error");
+ }
}
void CSQLite3::DisConnect()
@@ -262,7 +273,7 @@ void CSQLite3::Connect()
{
if (ret != SQLITE_CANTOPEN)
{
- throw CABRTException(EXCEP_PLUGIN, "Can't open database: %s", sqlite3_errmsg(m_pDB));
+ throw CABRTException(EXCEP_PLUGIN, "Can't open database '%s': %s", m_sDBPath.c_str(), sqlite3_errmsg(m_pDB));
}
ret = sqlite3_open_v2(m_sDBPath.c_str(),
@@ -272,7 +283,7 @@ void CSQLite3::Connect()
);
if (ret != SQLITE_OK)
{
- throw CABRTException(EXCEP_PLUGIN, "Can't create database: %s", sqlite3_errmsg(m_pDB));
+ throw CABRTException(EXCEP_PLUGIN, "Can't create database '%s': %s", m_sDBPath.c_str(), sqlite3_errmsg(m_pDB));
}
}
diff --git a/lib/Plugins/TicketUploader.cpp b/lib/Plugins/TicketUploader.cpp
index 06b6cde..a4fe0e8 100644
--- a/lib/Plugins/TicketUploader.cpp
+++ b/lib/Plugins/TicketUploader.cpp
@@ -20,8 +20,8 @@
#include <string>
#include <fstream>
#include <sstream>
-#include <curl/curl.h>
#include "abrtlib.h"
+#include "abrt_xmlrpc.h" /* for xcurl_easy_init */
#include "TicketUploader.h"
#include "DebugDump.h"
#include "ABRTException.h"
@@ -124,11 +124,7 @@ void CTicketUploader::SendFile(const char *pURL, const char *pFilename)
{
throw CABRTException(EXCEP_PLUGIN, "Can't stat archive file '%s'", pFilename);
}
- CURL* curl = curl_easy_init();
- if (!curl)
- {
- throw CABRTException(EXCEP_PLUGIN, "Curl library init error");
- }
+ CURL* curl = xcurl_easy_init();
/* enable uploading */
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
/* specify target */
@@ -394,12 +390,12 @@ void CTicketUploader::SetSettings(const map_plugin_settings_t& pSettings)
it = pSettings.find("RetryCount");
if (it != end)
{
- m_nRetryCount = atoi(it->second.c_str());
+ m_nRetryCount = xatoi_u(it->second.c_str());
}
it = pSettings.find("RetryDelay");
if (it != end)
{
- m_nRetryDelay = atoi(it->second.c_str());
+ m_nRetryDelay = xatoi_u(it->second.c_str());
}
}
diff --git a/lib/Utils/CrashTypesSocket.cpp b/lib/Utils/CrashTypesSocket.cpp
index f16e2a9..3525c6a 100644
--- a/lib/Utils/CrashTypesSocket.cpp
+++ b/lib/Utils/CrashTypesSocket.cpp
@@ -114,7 +114,7 @@ static int get_number_from_string(const std::string& pMessage, int& len)
}
}
len = ii + 1;
- return atoi(sNumber.c_str());
+ return xatoi(sNumber.c_str());
}
//TODO: remove constant 4 and place it in a message
diff --git a/lib/Utils/DebugDump.cpp b/lib/Utils/DebugDump.cpp
index 765b514..b4c3ee4 100644
--- a/lib/Utils/DebugDump.cpp
+++ b/lib/Utils/DebugDump.cpp
@@ -68,6 +68,22 @@ CDebugDump::CDebugDump() :
m_bLocked(false)
{}
+CDebugDump::~CDebugDump()
+{
+ /* Paranoia. In C++, destructor will abort() if it was called while unwinding
+ * the stack and it throws an exception.
+ */
+ try
+ {
+ Close();
+ m_sDebugDumpDir.clear();
+ }
+ catch (...)
+ {
+ error_msg_and_die("Internal error");
+ }
+}
+
void CDebugDump::Open(const char *pDir)
{
if (m_bOpened)
diff --git a/lib/Utils/DebugDump.h b/lib/Utils/DebugDump.h
index 7dfe61e..c59552e 100644
--- a/lib/Utils/DebugDump.h
+++ b/lib/Utils/DebugDump.h
@@ -41,6 +41,8 @@
#define FILENAME_COMMENT "comment"
#define FILENAME_REPRODUCE "reproduce"
#define FILENAME_RATING "rating"
+#define FILENAME_CMDLINE "cmdline"
+
class CDebugDump
{
@@ -57,7 +59,7 @@ class CDebugDump
public:
CDebugDump();
- ~CDebugDump() { Close(); }
+ ~CDebugDump();
void Open(const char *pDir);
void Create(const char *pDir, int64_t uid);
diff --git a/lib/Utils/Makefile.am b/lib/Utils/Makefile.am
index 9618751..d5e9d98 100644
--- a/lib/Utils/Makefile.am
+++ b/lib/Utils/Makefile.am
@@ -13,7 +13,9 @@ libABRTUtils_la_SOURCES = \
read_write.cpp \
logging.cpp \
copyfd.cpp \
+ daemon.cpp \
skip_whitespace.cpp \
+ xatonum.cpp \
popen_and_save_output.cpp \
stringops.cpp \
dirsize.cpp \
diff --git a/lib/Utils/abrt_xmlrpc.cpp b/lib/Utils/abrt_xmlrpc.cpp
index 7205316..ae1d098 100644
--- a/lib/Utils/abrt_xmlrpc.cpp
+++ b/lib/Utils/abrt_xmlrpc.cpp
@@ -5,6 +5,16 @@
#include "abrt_xmlrpc.h"
#include "ABRTException.h"
+CURL* xcurl_easy_init()
+{
+ CURL* curl = curl_easy_init();
+ if (!curl)
+ {
+ error_msg_and_die("Can't create curl handle");
+ }
+ return curl;
+}
+
void throw_if_xml_fault_occurred(xmlrpc_env *env)
{
if (env->fault_occurred)
diff --git a/lib/Utils/abrt_xmlrpc.h b/lib/Utils/abrt_xmlrpc.h
index e67ab19..352e80c 100644
--- a/lib/Utils/abrt_xmlrpc.h
+++ b/lib/Utils/abrt_xmlrpc.h
@@ -1,6 +1,7 @@
#ifndef ABRT_XMLRPC_H_
#define ABRT_XMLRPC_H_ 1
+#include <curl/curl.h>
#include <xmlrpc-c/base.h>
#include <xmlrpc-c/client.h>
@@ -15,13 +16,15 @@ struct abrt_xmlrpc_conn {
xmlrpc_server_info* m_pServer_info;
abrt_xmlrpc_conn(const char* url, bool no_ssl_verify) { new_xmlrpc_client(url, no_ssl_verify); }
+ /* this never throws exceptions - calls C functions only */
~abrt_xmlrpc_conn() { destroy_xmlrpc_client(); }
void new_xmlrpc_client(const char* url, bool no_ssl_verify);
void destroy_xmlrpc_client();
};
-/* Utility function */
+/* Utility functions */
void throw_if_xml_fault_occurred(xmlrpc_env *env);
+CURL* xcurl_easy_init();
#endif
diff --git a/lib/Utils/daemon.cpp b/lib/Utils/daemon.cpp
new file mode 100644
index 0000000..7aa891c
--- /dev/null
+++ b/lib/Utils/daemon.cpp
@@ -0,0 +1,139 @@
+/*
+ Copyright (C) 2009 RedHat inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+#include "abrtlib.h"
+#define FILENAME_CMDLINE "cmdline"
+#define VAR_RUN_PID_FILE VAR_RUN"/abrt.pid"
+
+static char *append_escaped(char *start, const char *s)
+{
+ char hex_char_buf[] = "\\x00";
+
+ *start++ = ' ';
+ char *dst = start;
+ const unsigned char *p = (unsigned char *)s;
+
+ while (1)
+ {
+ const unsigned char *old_p = p;
+ while (*p > ' ' && *p <= 0x7e && *p != '\"' && *p != '\'' && *p != '\\')
+ p++;
+ if (dst == start)
+ {
+ if (p != (unsigned char *)s && *p == '\0')
+ {
+ /* entire word does not need escaping and quoting */
+ strcpy(dst, s);
+ dst += strlen(s);
+ return dst;
+ }
+ *dst++ = '\'';
+ }
+
+ strncpy(dst, s, (p - old_p));
+ dst += (p - old_p);
+
+ if (*p == '\0')
+ {
+ *dst++ = '\'';
+ *dst = '\0';
+ return dst;
+ }
+ const char *a;
+ switch (*p)
+ {
+ case '\r': a = "\\r"; break;
+ case '\n': a = "\\n"; break;
+ case '\t': a = "\\t"; break;
+ case '\'': a = "\\\'"; break;
+ case '\"': a = "\\\""; break;
+ case '\\': a = "\\\\"; break;
+ case ' ': a = " "; break;
+ default:
+ hex_char_buf[2] = "0123456789abcdef"[*p >> 4];
+ hex_char_buf[3] = "0123456789abcdef"[*p & 0xf];
+ a = hex_char_buf;
+ }
+ strcpy(dst, a);
+ dst += strlen(a);
+ p++;
+ }
+}
+
+// taken from kernel
+#define COMMAND_LINE_SIZE 2048
+char* get_cmdline(pid_t pid)
+{
+ char path[sizeof("/proc/%u/cmdline") + sizeof(int)*3];
+ char cmdline[COMMAND_LINE_SIZE];
+ char escaped_cmdline[COMMAND_LINE_SIZE*4 + 4];
+
+ escaped_cmdline[1] = '\0';
+ sprintf(path, "/proc/%u/cmdline", (int)pid);
+ int fd = open(path, O_RDONLY);
+ if (fd >= 0)
+ {
+ int len = read(fd, cmdline, sizeof(cmdline) - 1);
+ close(fd);
+
+ if (len > 0)
+ {
+ cmdline[len] = '\0';
+ char *src = cmdline;
+ char *dst = escaped_cmdline;
+ while ((src - cmdline) < len)
+ {
+ dst = append_escaped(dst, src);
+ src += strlen(src) + 1;
+ }
+ }
+ }
+
+ return xstrdup(escaped_cmdline + 1); /* +1 skips extraneous leading space */
+}
+
+int daemon_is_ok()
+{
+ int fd = open(VAR_RUN_PID_FILE, O_RDONLY);
+ if (fd < 0)
+ {
+ return 0;
+ }
+
+ char pid[sizeof(pid_t)*3 + 2];
+ int len = read(fd, pid, sizeof(pid)-1);
+ close(fd);
+ if (len <= 0)
+ return 0;
+
+ pid[len] = '\0';
+ *strchrnul(pid, '\n') = '\0';
+ /* paranoia: we don't want to check /proc//stat or /proc///stat */
+ if (pid[0] == '\0' || pid[0] == '/')
+ return 0;
+
+ /* TODO: maybe readlink and check that it is "xxx/abrt"? */
+ char path[sizeof("/proc/%s/stat") + sizeof(pid)];
+ sprintf(path, "/proc/%s/stat", pid);
+ struct stat sb;
+ if (stat(path, &sb) == -1)
+ {
+ return 0;
+ }
+
+ return 1;
+}
diff --git a/lib/Utils/xatonum.cpp b/lib/Utils/xatonum.cpp
new file mode 100644
index 0000000..b096ca8
--- /dev/null
+++ b/lib/Utils/xatonum.cpp
@@ -0,0 +1,50 @@
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
+ *
+ * Licensed under GPLv2, see file LICENSE in this tarball for details.
+ */
+#include "abrtlib.h"
+
+unsigned xatou(const char *numstr)
+{
+ unsigned r;
+ int old_errno;
+ char *e;
+
+ if (*numstr < '0' || *numstr > '9')
+ goto inval;
+
+ old_errno = errno;
+ errno = 0;
+ r = strtoul(numstr, &e, 10);
+ if (errno || numstr == e || *e != '\0')
+ goto inval; /* error / no digits / illegal trailing chars */
+ errno = old_errno; /* Ok. So restore errno. */
+ return r;
+
+ inval:
+ error_msg_and_die("invalid number '%s'", numstr);
+}
+
+int xatoi_u(const char *numstr)
+{
+ unsigned r = xatou(numstr);
+ if (r > (unsigned)INT_MAX)
+ error_msg_and_die("invalid number '%s'", numstr);
+ return r;
+}
+
+int xatoi(const char *numstr)
+{
+ unsigned r;
+
+ if (*numstr != '-')
+ return xatoi_u(numstr);
+
+ r = xatou(numstr + 1);
+ if (r > (unsigned)INT_MAX + 1)
+ error_msg_and_die("invalid number '%s'", numstr);
+ return - (int)r;
+}