summaryrefslogtreecommitdiffstats
path: root/src/lib
diff options
context:
space:
mode:
authorJiri Moskovcak <jmoskovc@redhat.com>2011-05-18 16:55:40 +0200
committerJiri Moskovcak <jmoskovc@redhat.com>2011-05-18 16:55:40 +0200
commitbccd10f39589870673ffd09de6bc09d6e00fab72 (patch)
tree43d0f2e39cb62718ff44522ca6ddca389ac84a81 /src/lib
parent826900355023fcfef39cc91721e681cf558a11f6 (diff)
downloadabrt-bccd10f39589870673ffd09de6bc09d6e00fab72.tar.gz
abrt-bccd10f39589870673ffd09de6bc09d6e00fab72.tar.xz
abrt-bccd10f39589870673ffd09de6bc09d6e00fab72.zip
report C API improvements
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/problem_data.c32
-rw-r--r--src/lib/report.c162
2 files changed, 164 insertions, 30 deletions
diff --git a/src/lib/problem_data.c b/src/lib/problem_data.c
index 42dc770d..657044bb 100644
--- a/src/lib/problem_data.c
+++ b/src/lib/problem_data.c
@@ -57,6 +57,38 @@ problem_data_t *new_problem_data(void)
free, free_problem_item);
}
+void add_basics_to_problem_data(problem_data_t *pd)
+{
+ const char *analyzer = get_problem_item_content_or_NULL(pd, FILENAME_ANALYZER);
+ if (analyzer == NULL)
+ add_to_problem_data(pd, "analyzer", "libreport");
+
+ pid_t pid = getpid();
+ if (pid > 0)
+ {
+ char buf[PATH_MAX+1];
+ char *exe = xasprintf("/proc/%u/exe", pid);
+ ssize_t read = readlink(exe, buf, PATH_MAX);
+ if (read > 0)
+ {
+ buf[read] = 0;
+ VERB2 log("reporting initiated from: %s\n", buf);
+ add_to_problem_data(pd, FILENAME_EXECUTABLE, buf);
+ }
+ free(exe);
+
+//#ifdef WITH_RPM
+ /* FIXME: component should be taken from rpm using
+ * rpm -qf executable
+ */
+ /* Fedora/RHEL rpm specific piece of code */
+ const char *component = get_problem_item_content_or_NULL(pd, FILENAME_ANALYZER);
+ if(component == NULL) // application didn't specify component
+ add_to_problem_data(pd, FILENAME_COMPONENT, "abrt");
+//#endif
+ }
+}
+
void add_to_problem_data_ext(problem_data_t *problem_data,
const char *name,
const char *content,
diff --git a/src/lib/report.c b/src/lib/report.c
index a3ba6e96..1a0125ec 100644
--- a/src/lib/report.c
+++ b/src/lib/report.c
@@ -18,12 +18,46 @@
*/
#include "abrtlib.h"
+#include "report.h"
-int analyze_and_report_dir(const char* dirname)
+static void create_hash(char hash_str[SHA1_RESULT_LEN*2 + 1], const char *pInput)
{
+ unsigned char hash_bytes[SHA1_RESULT_LEN];
+ sha1_ctx_t sha1ctx;
+ sha1_begin(&sha1ctx);
+ sha1_hash(&sha1ctx, pInput, strlen(pInput));
+ sha1_end(&sha1ctx, hash_bytes);
+
+ unsigned len = SHA1_RESULT_LEN;
+ unsigned char *s = hash_bytes;
+ char *d = hash_str;
+ while (len)
+ {
+ *d++ = "0123456789abcdef"[*s >> 4];
+ *d++ = "0123456789abcdef"[*s & 0xf];
+ s++;
+ len--;
+ }
+ *d = '\0';
+ //log("hash:%s str:'%s'", hash_str, pInput);
+}
+
+static void generate_hash_for_all(gpointer key, gpointer value, gpointer user_data)
+{
+ problem_item *pi = (problem_item *)value;
+ char *hash_str = (char *)user_data;
+ create_hash(hash_str, pi->content);
+}
+
+static int run_reporter_ui(char **args, int flags)
+{
+ char path[PATH_MAX+1];
/*
- if is isatty -> run cli reporter
+ if is isatty
+ -> run cli reporter
+ path = "cli"
*/
+
pid_t pid = vfork();
if (pid == 0)
{
@@ -34,66 +68,135 @@ int analyze_and_report_dir(const char* dirname)
* Note that we do it in the child, so the parent is never affected.
*/
signal(SIGCHLD, SIG_DFL); // applet still set it to SIG_IGN
- VERB1 log("Executing: %s %s", "bug-reporting-wizard", dirname);
- execl(BIN_DIR"/bug-reporting-wizard", "bug-reporting-wizard", "--", dirname, NULL);
- // note the -o in options which means --report-only
+ strncpy(path, BIN_DIR"/bug-reporting-wizard", PATH_MAX);
+ path[PATH_MAX] = 0;
+ VERB1 log("Executing: %s", path);
+ execv(path, args);
/* Did not find abrt-gui in installation directory. Oh well */
/* Trying to find it in PATH */
- execlp("bug-reporting-wizard", "bug-reporting-wizard", "--", dirname, NULL);
+ strncpy(path, "bug-reporting-wizard", PATH_MAX);
+ execvp(path, args);
perror_msg_and_die("Can't execute %s", "bug-reporting-wizard");
}
+ else if(pid > 0)
+ {
+ if (flags & WAIT)
+ {
+ int status = 0;
+ pid_t p = waitpid(pid, &status, WUNTRACED);
+ if(p == -1)
+ {
+ error_msg("can't waitpid");
+ return EXIT_FAILURE;
+ }
+ if (WIFEXITED(status))
+ {
+ VERB2 log("reporting finished with exitcode: status=%d\n", WEXITSTATUS(status));
+ return WEXITSTATUS(status);
+ }
+ else if (WIFSIGNALED(status))
+ {
+ VERB2 log("reporting killed by signal %d\n", WTERMSIG(status));
+ }
+ else if (WIFSTOPPED(status))
+ {
+ /* should parent continue when the reporting is stopped??*/
+ VERB2 log("reporting stopped by signal %d\n", WSTOPSIG(status));
+ }
+ else if (WIFCONTINUED(status))
+ {
+ VERB2 log("continued\n");
+ }
+ }
+ }
+ return 0;
+}
+
+int analyze_and_report_dir(const char* dirname, int flags)
+{
+ char *args[4];
+
+ args[0] = (char *)"bug-reporting-wizard";
+ args[1] = (char *)"--";
+ args[2] = (char *)dirname;
+ args[3] = NULL;
+
+ run_reporter_ui(args, flags);
return 0;
}
/* analyzes AND reports a problem saved on disk
* - takes user through all the steps in reporting wizard
*/
-int analyze_and_report(problem_data_t *pd)
+int analyze_and_report(problem_data_t *pd, int flags)
{
+ int result = 0;
struct dump_dir *dd = create_dump_dir_from_problem_data(pd, "/tmp"/* /var/tmp ?? */);
if (!dd)
return -1;
char *dir_name = strdup(dd->dd_dirname);
dd_close(dd);
VERB2 log("Temp problem dir: '%s'\n", dir_name);
- analyze_and_report_dir(dir_name);
+ result = analyze_and_report_dir(dir_name, flags);
+
+ /* if we wait for reporter to finish, we can try to clean the tmp dir */
+ if (flags & WAIT)
+ {
+ dd = dd_opendir(dir_name, 0);
+ if (dd)
+ {
+ if (dd_delete(dd) != 0)
+ {
+ error_msg("Can't remove tmp dir: %s", dd->dd_dirname);
+ }
+ }
+ }
free(dir_name);
- return 0;
+ return result;
}
+/* report() and report_dir() don't take flags, because in all known use-cases
+ * it doesn't make sense to not wait for the result
+ *
+*/
+
/* reports a problem saved on disk
* - shows only reporter selector and progress
*/
int report_dir(const char* dirname)
{
- pid_t pid = vfork();
- if (pid == 0)
- {
- /* Some callers set SIGCHLD to SIG_IGN.
- * However, reporting spawns chils processes.
- * Suppressing chil death notification terribly confuses some of them.
- * Just in case, undo it.
- * Note that we do it in the child, so the parent is never affected.
- */
- signal(SIGCHLD, SIG_DFL); // applet still set it to SIG_IGN
- VERB1 log("Executing: %s %s", "bug-reporting-wizard", dirname);
- execl(BIN_DIR"/bug-reporting-wizard", "bug-reporting-wizard",
- "-o", "--", dirname, NULL);
- // note the -o in options which means --report-only
- /* Did not find abrt-gui in installation directory. Oh well */
- /* Trying to find it in PATH */
- execlp("bug-reporting-wizard", "bug-reporting-wizard",
- "-o", "--", dirname, NULL);
- perror_msg_and_die("Can't execute %s", "bug-reporting-wizard");
- }
+ char *args[5];
+
+ args[0] = (char *)"bug-reporting-wizard";
+ args[1] = (char *)"--report-only";
+ args[2] = (char *)"--";
+ args[3] = (char *)dirname;
+ args[4] = NULL;
+
+ int flags = WAIT;
+ run_reporter_ui(args, flags);
return 0;
}
int report(problem_data_t *pd)
{
+ /* create hash from all components, so we at least eliminate the exact same
+ * reports
+ */
+ char hash_str[SHA1_RESULT_LEN*2 + 1];
+ g_hash_table_foreach(pd, &generate_hash, hash_str);
+ add_to_problem_data(pd, FILENAME_DUPHASH, hash_str);
+
+ /* adds:
+ * analyzer:libreport
+ * executable:readlink(/proc/<pid>/exe)
+ * tries to guess component
+ */
+ add_basics_to_problem_data(pd);
struct dump_dir *dd = create_dump_dir_from_problem_data(pd, "/tmp"/* /var/tmp ?? */);
if (!dd)
return -1;
+ dd_create_basic_files(dd, getuid());
char *dir_name = xstrdup(dd->dd_dirname);
dd_close(dd);
VERB2 log("Temp problem dir: '%s'\n", dir_name);
@@ -102,4 +205,3 @@ int report(problem_data_t *pd)
return 0;
}
-