[PATCH] teach dump-oops to read DumpLocation from abrt.conf
by Nikola Pajkovsky
Signed-off-by: Nikola Pajkovsky <npajkovs(a)redhat.com>
---
abrt-oops.init | 2 +-
src/plugins/Makefile.am | 3 ++-
src/plugins/abrt-dump-oops.c | 17 ++++++++++++++++-
src/plugins/abrt-oops.service | 2 +-
4 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/abrt-oops.init b/abrt-oops.init
index cb64dac..a9934a9 100644
--- a/abrt-oops.init
+++ b/abrt-oops.init
@@ -34,7 +34,7 @@ check() {
start() {
check
killall abrt-dump-oops 2>/dev/null
- setsid abrt-dump-oops -d /var/spool/abrt -rwx /var/log/messages </dev/null >/dev/null 2>&1 &
+ setsid abrt-dump-oops -rwxD /var/log/messages </dev/null >/dev/null 2>&1 &
$dry_run || touch -- "$LOCK"
return $RETVAL
}
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index 660a38a..11b3bf1 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -111,7 +111,8 @@ abrt_dump_oops_CPPFLAGS = \
-Wall -Wwrite-strings -Werror
abrt_dump_oops_LDADD = \
$(GLIB_LIBS) \
- $(LIBREPORT_LIBS)
+ $(LIBREPORT_LIBS) \
+ ../lib/libabrt.la
abrt_action_analyze_c_SOURCES = \
abrt-action-analyze-c.c
diff --git a/src/plugins/abrt-dump-oops.c b/src/plugins/abrt-dump-oops.c
index b43d507..67cb610 100644
--- a/src/plugins/abrt-dump-oops.c
+++ b/src/plugins/abrt-dump-oops.c
@@ -576,6 +576,7 @@ int main(int argc, char **argv)
/* Can't keep these strings/structs static: _() doesn't support that */
const char *program_usage_string = _(
"\b [-vsrowx] [-d DIR] FILE\n"
+ " or: \b [-vsrowx] -D file\n"
"\n"
"Extract oops from syslog/dmesg file"
);
@@ -587,6 +588,7 @@ int main(int argc, char **argv)
OPT_w = 1 << 4,
OPT_d = 1 << 5,
OPT_x = 1 << 6,
+ OPT_D = 1 << 7,
};
/* Keep enum above and order of options below in sync! */
struct options program_options[] = {
@@ -600,10 +602,14 @@ int main(int argc, char **argv)
*/
OPT_STRING('d', NULL, &debug_dumps_dir, "DIR", _("Create ABRT dump in DIR for every oops found")),
OPT_BOOL( 'x', NULL, NULL, _("Make the dump directory world readable")),
+ OPT_BOOL( 'D', NULL, NULL, _("Load dynamically DUMP_DIR location from abrt.conf")),
OPT_END()
};
unsigned opts = parse_opts(argc, argv, program_options, program_usage_string);
+ if ((opts & OPT_d) && (opts & OPT_D))
+ show_usage_and_die(program_usage_string, program_options);
+
export_abrt_envvars(0);
msg_prefix = g_progname;
@@ -713,8 +719,14 @@ int main(int argc, char **argv)
while (i < oops_cnt)
printf("\nVersion: %s", (char*)g_list_nth_data(oops_list, i++));
}
- if (opts & OPT_d)
+ if ((opts & OPT_d) || (opts & OPT_D))
{
+ if (opts & OPT_D)
+ {
+ load_abrt_conf();
+ debug_dumps_dir = g_settings_dump_location;
+ }
+
log("Creating dump directories");
errors += save_oops_to_dump_dir(oops_list, oops_cnt);
if (errors > 0)
@@ -729,6 +741,9 @@ int main(int argc, char **argv)
"Reported %u kernel oopses to Abrt",
oops_cnt
);
+
+ if (opts & OPT_D)
+ free_abrt_conf_data();
}
}
list_free_with_free(oops_list);
diff --git a/src/plugins/abrt-oops.service b/src/plugins/abrt-oops.service
index 4911e2b..b21e1f0 100644
--- a/src/plugins/abrt-oops.service
+++ b/src/plugins/abrt-oops.service
@@ -3,7 +3,7 @@ Description=ABRT kernel log watcher
After=syslog.target
[Service]
-ExecStart=/usr/bin/abrt-dump-oops -d /var/spool/abrt -rwx /var/log/messages
+ExecStart=/usr/bin/abrt-dump-oops -rwxD /var/log/messages
[Install]
WantedBy=multi-user.target
--
1.7.6.345.g5c2f8
12 years, 9 months
[PATCH] teach dump-oops to read DumpLocation from abrt.conf
by Nikola Pajkovsky
Signed-off-by: Nikola Pajkovsky <npajkovs(a)redhat.com>
---
abrt-oops.init | 2 +-
src/plugins/Makefile.am | 3 ++-
src/plugins/abrt-dump-oops.c | 35 +++++++++++++++++++----------------
src/plugins/abrt-oops.service | 2 +-
4 files changed, 23 insertions(+), 19 deletions(-)
diff --git a/abrt-oops.init b/abrt-oops.init
index cb64dac..b959fa8 100644
--- a/abrt-oops.init
+++ b/abrt-oops.init
@@ -34,7 +34,7 @@ check() {
start() {
check
killall abrt-dump-oops 2>/dev/null
- setsid abrt-dump-oops -d /var/spool/abrt -rwx /var/log/messages </dev/null >/dev/null 2>&1 &
+ setsid abrt-dump-oops -rwx /var/log/messages </dev/null >/dev/null 2>&1 &
$dry_run || touch -- "$LOCK"
return $RETVAL
}
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index 660a38a..11b3bf1 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -111,7 +111,8 @@ abrt_dump_oops_CPPFLAGS = \
-Wall -Wwrite-strings -Werror
abrt_dump_oops_LDADD = \
$(GLIB_LIBS) \
- $(LIBREPORT_LIBS)
+ $(LIBREPORT_LIBS) \
+ ../lib/libabrt.la
abrt_action_analyze_c_SOURCES = \
abrt-action-analyze-c.c
diff --git a/src/plugins/abrt-dump-oops.c b/src/plugins/abrt-dump-oops.c
index b43d507..059bdfc 100644
--- a/src/plugins/abrt-dump-oops.c
+++ b/src/plugins/abrt-dump-oops.c
@@ -713,23 +713,26 @@ int main(int argc, char **argv)
while (i < oops_cnt)
printf("\nVersion: %s", (char*)g_list_nth_data(oops_list, i++));
}
- if (opts & OPT_d)
- {
- log("Creating dump directories");
- errors += save_oops_to_dump_dir(oops_list, oops_cnt);
- if (errors > 0)
- log("%d errors while dumping oopses", errors);
- /*
- * This marker in syslog file prevents us from
- * re-parsing old oopses. The only problem is that we
- * can't be sure here that the file we are watching
- * is the same file where syslog(xxx) stuff ends up.
- */
- syslog(LOG_WARNING,
- "Reported %u kernel oopses to Abrt",
- oops_cnt
+
+ load_abrt_conf();
+ if (!(opts & OPT_d))
+ debug_dumps_dir = g_settings_dump_location;
+
+ log("Creating dump directories");
+ errors += save_oops_to_dump_dir(oops_list, oops_cnt);
+ if (errors > 0)
+ log("%d errors while dumping oopses", errors);
+ /*
+ * This marker in syslog file prevents us from
+ * re-parsing old oopses. The only problem is that we
+ * can't be sure here that the file we are watching
+ * is the same file where syslog(xxx) stuff ends up.
+ */
+ syslog(LOG_WARNING,
+ "Reported %u kernel oopses to Abrt",
+ oops_cnt
);
- }
+ free_abrt_conf_data();
}
list_free_with_free(oops_list);
oops_list = NULL;
diff --git a/src/plugins/abrt-oops.service b/src/plugins/abrt-oops.service
index 4911e2b..261e6a4 100644
--- a/src/plugins/abrt-oops.service
+++ b/src/plugins/abrt-oops.service
@@ -3,7 +3,7 @@ Description=ABRT kernel log watcher
After=syslog.target
[Service]
-ExecStart=/usr/bin/abrt-dump-oops -d /var/spool/abrt -rwx /var/log/messages
+ExecStart=/usr/bin/abrt-dump-oops -rwx /var/log/messages
[Install]
WantedBy=multi-user.target
--
1.7.6.345.g5c2f8
12 years, 9 months
[PATCH 1/3] add string_iso_date()
by Miroslav Lichvar
---
src/include/internal_libreport.h | 4 +++-
src/lib/iso_date_string.c | 10 +++++++++-
2 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/src/include/internal_libreport.h b/src/include/internal_libreport.h
index d7b3257..616ea0d 100644
--- a/src/include/internal_libreport.h
+++ b/src/include/internal_libreport.h
@@ -533,7 +533,9 @@ char* get_environ(pid_t pid);
* Returns "YYYY-MM-DD-hh:mm:ss" string.
*/
#define iso_date_string libreport_iso_date_string
-char *iso_date_string(time_t *pt);
+char *iso_date_string(const time_t *pt);
+#define string_iso_date libreport_string_iso_date
+time_t string_iso_date(const char *date);
enum {
MAKEDESC_SHOW_FILES = (1 << 0),
diff --git a/src/lib/iso_date_string.c b/src/lib/iso_date_string.c
index e7d01cd..012ded3 100644
--- a/src/lib/iso_date_string.c
+++ b/src/lib/iso_date_string.c
@@ -19,7 +19,7 @@
#include "internal_libreport.h"
-char *iso_date_string(time_t *pt)
+char *iso_date_string(const time_t *pt)
{
static char buf[sizeof("YYYY-MM-DD-HH:MM:SS") + 4];
@@ -29,3 +29,11 @@ char *iso_date_string(time_t *pt)
return buf;
}
+
+time_t string_iso_date(const char *date)
+{
+ struct tm tm;
+ strptime(date, "%Y-%m-%d-%H:%M:%S", &tm);
+
+ return mktime(&tm);
+}
--
1.7.6
12 years, 9 months
[PATCHv2] attach file to bugzilla ticket
by Nikola Pajkovsky
Signed-off-by: Nikola Pajkovsky <npajkovs(a)redhat.com>
---
src/plugins/reporter-bugzilla.c | 123 ++++++++++++++++++++++++++++++--------
1 files changed, 97 insertions(+), 26 deletions(-)
diff --git a/src/plugins/reporter-bugzilla.c b/src/plugins/reporter-bugzilla.c
index 5b58a29..c668395 100644
--- a/src/plugins/reporter-bugzilla.c
+++ b/src/plugins/reporter-bugzilla.c
@@ -22,35 +22,14 @@
#define XML_RPC_SUFFIX "/xmlrpc.cgi"
-static void report_to_bugzilla(const char *dump_dir_name, map_string_h *settings)
+static void report_to_bugzilla(const char *dump_dir_name, const char *login,
+ const char *password, const char *bugzilla_xmlrpc,
+ const char *bugzilla_url, int ssl_verify)
{
problem_data_t *problem_data = create_problem_data_for_reporting(dump_dir_name);
if (!problem_data)
xfunc_die(); /* create_problem_data_for_reporting already emitted error msg */
- const char *env;
- const char *login;
- const char *password;
- const char *bugzilla_xmlrpc;
- const char *bugzilla_url;
- bool ssl_verify;
-
- env = getenv("Bugzilla_Login");
- login = env ? env : get_map_string_item_or_empty(settings, "Login");
- env = getenv("Bugzilla_Password");
- password = env ? env : get_map_string_item_or_empty(settings, "Password");
- if (!login[0] || !password[0])
- error_msg_and_die(_("Empty login or password, please check your configuration"));
-
- env = getenv("Bugzilla_BugzillaURL");
- bugzilla_url = env ? env : get_map_string_item_or_empty(settings, "BugzillaURL");
- if (!bugzilla_url[0])
- bugzilla_url = "https://bugzilla.redhat.com";
- bugzilla_xmlrpc = xasprintf("%s"XML_RPC_SUFFIX, bugzilla_url);
-
- env = getenv("Bugzilla_SSLVerify");
- ssl_verify = string_to_bool(env ? env : get_map_string_item_or_empty(settings, "SSLVerify"));
-
const char *component = get_problem_item_content_or_NULL(problem_data, FILENAME_COMPONENT);
const char *duphash = get_problem_item_content_or_NULL(problem_data, FILENAME_DUPHASH);
//COMPAT, remove after 2.1 release
@@ -234,6 +213,7 @@ int main(int argc, char **argv)
/* Can't keep these strings/structs static: _() doesn't support that */
const char *program_usage_string = _(
"\b [-v] [-c CONFFILE] -d DIR\n"
+ " or: \b [-v] --ticket NUM <file> [<file>...]\n"
"\n"
"Reports problem to Bugzilla.\n"
"\n"
@@ -260,15 +240,19 @@ int main(int argc, char **argv)
OPT_v = 1 << 0,
OPT_d = 1 << 1,
OPT_c = 1 << 2,
+ OPT_t = 1 << 3,
};
+
+ static int ticket_no;
/* Keep enum above and order of options below in sync! */
struct options program_options[] = {
OPT__VERBOSE(&g_verbose),
OPT_STRING('d', NULL, &dump_dir_name, "DIR" , _("Dump directory")),
OPT_LIST( 'c', NULL, &conf_file , "FILE", _("Configuration file (may be given many times)")),
+ OPT_INTEGER('t', "ticket", &ticket_no, _("Attach file to a bugzilla ticket")),
OPT_END()
};
- /*unsigned opts =*/ parse_opts(argc, argv, program_options, program_usage_string);
+ unsigned opts = parse_opts(argc, argv, program_options, program_usage_string);
export_abrt_envvars(0);
@@ -289,7 +273,94 @@ int main(int argc, char **argv)
error_msg_and_die("XML-RPC Fault: %s(%d)", env.fault_string, env.fault_code);
xmlrpc_env_clean(&env);
- report_to_bugzilla(dump_dir_name, settings);
+ const char *environ;
+ const char *login;
+ const char *password;
+ const char *bugzilla_xmlrpc;
+ const char *bugzilla_url;
+ bool ssl_verify;
+
+ environ = getenv("Bugzilla_Login");
+ login = environ ? environ : get_map_string_item_or_empty(settings, "Login");
+ environ = getenv("Bugzilla_Password");
+ password = environ ? environ : get_map_string_item_or_empty(settings, "Password");
+ if (!login[0] || !password[0])
+ error_msg_and_die(_("Empty login or password, please check your configuration"));
+
+ environ = getenv("Bugzilla_BugzillaURL");
+ bugzilla_url = environ ? environ : get_map_string_item_or_empty(settings, "BugzillaURL");
+ if (!bugzilla_url[0])
+ bugzilla_url = "https://bugzilla.redhat.com";
+ bugzilla_xmlrpc = xasprintf("%s"XML_RPC_SUFFIX, bugzilla_url);
+
+ environ = getenv("Bugzilla_SSLVerify");
+ ssl_verify = string_to_bool(environ ? environ : get_map_string_item_or_empty(settings, "SSLVerify"));
+
+ if (opts & OPT_t)
+ {
+ if (!argv[optind])
+ show_usage_and_die(program_usage_string, program_options);
+
+ struct abrt_xmlrpc *client = abrt_xmlrpc_new_client(bugzilla_xmlrpc, ssl_verify);
+
+ log(_("Logging into Bugzilla at %s"), bugzilla_url);
+ rhbz_login(client, login, password);
+
+ while (argv[optind])
+ {
+ const char *filename = argv[optind++];
+ VERB1 log("Attaching file '%s' to bugticket %i", filename, ticket_no);
+
+ int fd = open(filename, O_RDONLY);
+ if (fd < 0)
+ {
+ perror_msg("Can't open: '%s'", filename);
+ continue;
+ }
+
+ struct stat st;
+ if (fstat(fd, &st) != 0 || !S_ISREG(st.st_mode))
+ {
+ error_msg("Can't open: '%s': not a regular file", filename);
+ close(fd);
+ continue;
+ }
+
+ off_t size = lseek(fd, 0, SEEK_END);
+ if (size < 0)
+ {
+ close(fd);
+ perror_msg("Can't lseek: '%s'", filename);
+ continue;
+ }
+ lseek(fd, 0, SEEK_SET);
+
+ char *data = xmalloc(size + 1);
+ ssize_t r = full_read(fd, data, size);
+ if (r < 0)
+ {
+ free(data);
+ perror_msg("Can't read: '%s'", filename);
+ close(fd);
+ continue;
+ }
+ close(fd);
+
+ char *ticket_no_str = xasprintf("%i", ticket_no);
+ rhbz_attachment(client, filename, ticket_no_str, data, /*flags*/ 0);
+ free(ticket_no_str);
+ free(data);
+ }
+
+ log(_("Logging out"));
+ rhbz_logout(client);
+ abrt_xmlrpc_free_client(client);
+ }
+ else
+ {
+ report_to_bugzilla(dump_dir_name, login, password, bugzilla_xmlrpc,
+ bugzilla_url, ssl_verify);
+ }
free_map_string(settings);
return 0;
--
1.7.6.345.g5c2f8
12 years, 9 months
Re: repoted_to API brainstorm
by Denys Vlasenko
On Wed, 2011-08-03 at 11:02 +0200, Denys Vlasenko wrote:
> I need to parse reported_to for "attach a file to existing RHTS report"
> functionality. (BZ will need the same soon). I need the latest
> (most recent) reported_to line for a specific prefix.
>
> Jiri needs to parse reported_to in order to display it in GUI.
> He needs all lines parsed.
>
> For this, I also needed to improve RHTS reported_to generation -
> "MSG=Case created: https://api.access.redhat.com/rs/cases/00512471"
> is not parseable. So I changed it into
> "URL=https://api.access.redhat.com/rs/cases/00512471 MSG=Case created".
>
...
> I propose the following API instead:
>
> struct report_result {
> time_t timestamp;
> char *url;
> char *msg;
> char *email;
> ...
> };
> /* Find latest "PFX: ...", parse and return it. If not found, return NULL */
> report_result_t *find_reported_to(struct dump_dir *dd, const char *prefix);
> /* Load, parse and return all lines as list of report_result_t's */
> GList *parse_reported_to(struct dump_dir *dd);
>
> find_reported_to() is for my needs, and parse_reported_to() is for Jiri.
>
> Formatting of reported_to lines, IMO, is handled by xasprintf()
> well enough already. I tried to imagine useful helper function API
> but so far I have nothing.
Here is the proposed patch.
struct report_result is changed, find_in_reported_to() is implemented
and used in rhts plugin (ignore most of changes there, just find
- report_to_rhtsupport(dump_dir_name, settings);
+ if (file_name)
...
part and see how find_in_reported_to() is used there).
Jiri's needs are partially addressed by parse_reported_line().
So far it is a static function which parses one line.
For Jiri, it will be used by a new, rather simple function
which reads reported_to line-by-line, calls parse_reported_line()
on each line, and returns the list of results.
As an immediate next step, I propose nuking src/lib/report_result.c
and moving the lone remaining function, free_report_result(),
to dump_dir.c. Perhaps report_result-related function decls
should be moved to dump_dir.h too.
--
vda
diff -x '*.po' -d -urpN libreport.5/src/include/internal_libreport.h libreport.6/src/include/internal_libreport.h
--- libreport.5/src/include/internal_libreport.h 2011-08-02 11:00:46.000000000 +0200
+++ libreport.6/src/include/internal_libreport.h 2011-08-03 15:54:00.741079803 +0200
@@ -534,8 +534,6 @@ char* get_environ(pid_t pid);
*/
#define iso_date_string libreport_iso_date_string
char *iso_date_string(const time_t *pt);
-#define string_iso_date libreport_string_iso_date
-time_t string_iso_date(const char *date);
enum {
MAKEDESC_SHOW_FILES = (1 << 0),
@@ -654,29 +652,23 @@ enum {
EVENT_LOG_LOW_WATERMARK = 20 * 1024,
};
-enum report_result_type {
- REPORT_RESULT_TYPE_URL,
- REPORT_RESULT_TYPE_MESSAGE
-};
-
struct report_result {
- char *event;
- char *data;
- enum report_result_type type;
- time_t timestamp;
+ char *url;
+ char *msg;
+ /* char *whole_line; */
+ /* time_t timestamp; */
+ /* ^^^ if you add more fields, don't forget to update free_report_result() */
};
+typedef struct report_result report_result_t;
+
+#define free_report_result libreport_free_report_result
+void free_report_result(struct report_result *result);
#define add_reported_to libreport_add_reported_to
void add_reported_to(struct dump_dir *dd, const char *line);
-#define new_report_result libreport_new_report_result
-struct report_result *new_report_result(enum report_result_type type, char *data);
-#define format_report_result libreport_format_report_result
-char *format_report_result(const struct report_result *result);
-#define parse_report_result libreport_parse_report_result
-struct report_result *parse_report_result(const char *text);
-#define free_report_result libreport_free_report_result
-void free_report_result(struct report_result *result);
+#define find_in_reported_to libreport_find_in_reported_to
+report_result_t *find_in_reported_to(struct dump_dir *dd, const char *prefix);
#define log_problem_data libreport_log_problem_data
void log_problem_data(problem_data_t *problem_data, const char *pfx);
diff -x '*.po' -d -urpN libreport.5/src/lib/dump_dir.c libreport.6/src/lib/dump_dir.c
--- libreport.5/src/lib/dump_dir.c 2011-07-29 11:08:13.000000000 +0200
+++ libreport.6/src/lib/dump_dir.c 2011-08-03 14:25:45.609075779 +0200
@@ -798,6 +798,72 @@ void add_reported_to(struct dump_dir *dd
free(reported_to);
}
+static report_result_t *parse_reported_line(const char *line)
+{
+ report_result_t *result = xzalloc(sizeof(*result));
+
+ //result->whole_line = xstrdup(line);
+ for (;;)
+ {
+ line = skip_whitespace(line);
+ if (!*line)
+ break;
+ const char *end = skip_non_whitespace(line);
+ if (strncmp(line, "MSG=", 4) == 0)
+ {
+ result->msg = xstrdup(line + 4);
+ /* MSG=... eats entire line: exiting the loop */
+ break;
+ }
+ if (strncmp(line, "URL=", 4) == 0)
+ {
+ free(result->url);
+ result->url = xstrndup(line + 4, end - (line + 4));
+ }
+ //else
+ //if (strncmp(line, "TIME=", 5) == 0)
+ //{
+ // free(result->time);
+ // result->time = foo(line + 5, end - (line + 5));
+ //}
+ //...
+ line = end;
+ continue;
+ }
+
+ return result;
+}
+
+report_result_t *find_in_reported_to(struct dump_dir *dd, const char *prefix)
+{
+ char *reported_to = dd_load_text_ext(dd, FILENAME_REPORTED_TO, DD_FAIL_QUIETLY_ENOENT | DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE);
+ if (!reported_to)
+ return NULL;
+
+ /* Find *last* (most recent) line with this prefix */
+ unsigned prefix_len = strlen(prefix);
+ char *found = NULL;
+ char *p = reported_to;
+ while (*p)
+ {
+ if (strncmp(p, prefix, prefix_len) == 0)
+ found = p + prefix_len;
+ p = strchrnul(p, '\n');
+ if (*p)
+ {
+ *p = '\0'; /* EOL marker for parse_reported_line() below */
+ p++;
+ }
+ }
+
+ report_result_t *result = NULL;
+ if (found)
+ result = parse_reported_line(found);
+
+ free(reported_to);
+ return result;
+}
+
DIR *dd_init_next_file(struct dump_dir *dd)
{
// if (!dd->locked)
diff -x '*.po' -d -urpN libreport.5/src/lib/iso_date_string.c libreport.6/src/lib/iso_date_string.c
--- libreport.5/src/lib/iso_date_string.c 2011-07-25 10:57:18.000000000 +0200
+++ libreport.6/src/lib/iso_date_string.c 2011-08-03 16:01:53.628409453 +0200
@@ -29,11 +29,3 @@ char *iso_date_string(const time_t *pt)
return buf;
}
-
-time_t string_iso_date(const char *date)
-{
- struct tm tm;
- strptime(date, "%Y-%m-%d-%H:%M:%S", &tm);
-
- return mktime(&tm);
-}
diff -x '*.po' -d -urpN libreport.5/src/lib/report_result.c libreport.6/src/lib/report_result.c
--- libreport.5/src/lib/report_result.c 2011-08-02 15:36:52.144860418 +0200
+++ libreport.6/src/lib/report_result.c 2011-08-03 15:49:37.056299891 +0200
@@ -18,84 +18,11 @@
*/
#include "internal_libreport.h"
-struct report_result *new_report_result(enum report_result_type type, char *data)
-{
- struct report_result *res;
- const char *event;
-
- event = getenv("EVENT");
- if (!event)
- event = "unknown";
-
- res = xmalloc(sizeof (*res));
- res->event = xstrdup(event);
- res->data = data;
- res->type = type;
- res->timestamp = time(NULL);
-
- return res;
-}
-
-char *format_report_result(const struct report_result *result)
-{
- const char *type_string;
-
- switch (result->type)
- {
- case REPORT_RESULT_TYPE_URL:
- type_string = "URL";
- break;
- case REPORT_RESULT_TYPE_MESSAGE:
- type_string = "MSG";
- break;
- default:
- assert(0);
- }
- return xasprintf("%s: TIME=%s %s=%s", result->event,
- iso_date_string(&result->timestamp), type_string, result->data);
-}
-
-struct report_result *parse_report_result(const char *text)
-{
- struct report_result *res;
- enum report_result_type type;
- time_t ts;
- int event_len, event_ts_len;
- char event[256], timestamp[256], *data;
-
- if (sscanf(text, "%s%n %s%n", event, &event_len, timestamp, &event_ts_len) != 2)
- return NULL;
-
- data = skip_whitespace(text + event_ts_len);
- if (!strncmp(data, "URL=", 4))
- {
- data += 4;
- type = REPORT_RESULT_TYPE_URL;
- }
- else if (!strncmp(data, "MSG=", 4))
- {
- data += 4;
- type = REPORT_RESULT_TYPE_MESSAGE;
- }
- else
- return NULL;
-
- if (strncmp(timestamp, "TIME=", 5))
- return NULL;
- ts = string_iso_date(timestamp + 5);
-
- res = xmalloc(sizeof (*res));
- res->event = xstrndup(event, event_len - 1);
- res->data = xstrdup(data);
- res->type = type;
- res->timestamp = ts;
-
- return res;
-}
-
void free_report_result(struct report_result *result)
{
- free(result->event);
- free(result->data);
+ if (!result)
+ return;
+ free(result->url);
+ free(result->msg);
free(result);
}
diff -x '*.po' -d -urpN libreport.5/src/plugins/abrt_rh_support.c libreport.6/src/plugins/abrt_rh_support.c
--- libreport.5/src/plugins/abrt_rh_support.c 2011-08-02 16:28:01.750516487 +0200
+++ libreport.6/src/plugins/abrt_rh_support.c 2011-08-03 15:13:01.204392942 +0200
@@ -395,7 +395,7 @@ send_report_to_new_case(const char* base
break;
}
- char *atch_url = concat_path_file(case_location, "/attachments");
+ char *atch_url = concat_path_file(case_location, "attachments");
abrt_post_state_t *atch_state;
redirect_attach:
atch_state = new_abrt_post_state(0
@@ -410,16 +410,18 @@ send_report_to_new_case(const char* base
abrt_post_file_as_form(atch_state, atch_url, "application/binary", headers,
report_file_name);
- char *atch_location = find_header_in_abrt_post_state(atch_state, "Location:");
switch (atch_state->http_resp_code)
{
case 305: /* "305 Use Proxy" */
- if (++redirect_count < 10 && atch_location)
{
- free(atch_url);
- atch_url = xstrdup(atch_location);
- free_abrt_post_state(atch_state);
- goto redirect_attach;
+ char *atch_location = find_header_in_abrt_post_state(atch_state, "Location:");
+ if (++redirect_count < 10 && atch_location)
+ {
+ free(atch_url);
+ atch_url = xstrdup(atch_location);
+ free_abrt_post_state(atch_state);
+ goto redirect_attach;
+ }
}
/* fall through */
diff -x '*.po' -d -urpN libreport.5/src/plugins/reporter-rhtsupport.c libreport.6/src/plugins/reporter-rhtsupport.c
--- libreport.5/src/plugins/reporter-rhtsupport.c 2011-08-02 16:37:06.398115806 +0200
+++ libreport.6/src/plugins/reporter-rhtsupport.c 2011-08-03 15:47:55.429991436 +0200
@@ -22,9 +22,12 @@
#include "abrt_xmlrpc.h"
#include "abrt_rh_support.h"
-static void report_to_rhtsupport(
- const char *dump_dir_name,
- map_string_h *settings)
+static char *url;
+static char *login;
+static char *password;
+static bool ssl_verify;
+
+static void report_to_rhtsupport(const char *dump_dir_name)
{
problem_data_t *problem_data = create_problem_data_for_reporting(dump_dir_name);
if (!problem_data)
@@ -45,24 +48,6 @@ static void report_to_rhtsupport(
const char* reason;
const char* package;
- char* env;
- env = getenv("RHTSupport_URL");
- char *url = xstrdup(env ? env : (get_map_string_item_or_NULL(settings, "URL") ? : "https://api.access.redhat.com/rs"));
-
- env = getenv("RHTSupport_Login");
- char *login = xstrdup(env ? env : get_map_string_item_or_empty(settings, "Login"));
-
- env = getenv("RHTSupport_Password");
- char *password = xstrdup(env ? env : get_map_string_item_or_empty(settings, "Password"));
-
- env = getenv("RHTSupport_SSLVerify");
- bool ssl_verify = string_to_bool(env ? env : get_map_string_item_or_empty(settings, "SSLVerify"));
-
- if (!login[0] || !password[0])
- {
- error_msg_and_die(_("Empty RHTS login or password"));
- }
-
package = get_problem_item_content_or_NULL(problem_data, FILENAME_PACKAGE);
reason = get_problem_item_content_or_NULL(problem_data, FILENAME_REASON);
function = get_problem_item_content_or_NULL(problem_data, FILENAME_CRASH_FUNCTION);
@@ -292,41 +277,130 @@ static void report_to_rhtsupport(
free_problem_data(problem_data);
}
+static void attach_to_rhtsupport(const char *file_name)
+{
+ log(_("Attaching '%s' to case '%s'"), file_name, url);
+
+ static const char *headers[] = {
+ "Accept: text/plain",
+ NULL
+ };
+
+ int redirect_count = 0;
+ char *atch_url = concat_path_file(url, "attachments");
+ abrt_post_state_t *atch_state;
+
+ redirect_attach:
+ atch_state = new_abrt_post_state(0
+ + ABRT_POST_WANT_HEADERS
+ + ABRT_POST_WANT_BODY
+ + ABRT_POST_WANT_ERROR_MSG
+ + (ssl_verify ? ABRT_POST_WANT_SSL_VERIFY : 0)
+ );
+ atch_state->username = login;
+ atch_state->password = password;
+ abrt_post_file_as_form(atch_state,
+ atch_url,
+ "application/binary",
+ headers,
+ file_name
+ );
+ free(atch_url);
+
+ char *atch_location = find_header_in_abrt_post_state(atch_state, "Location:");
+ switch (atch_state->http_resp_code)
+ {
+ case 305: /* "305 Use Proxy" */
+ if (++redirect_count < 10 && atch_location)
+ {
+ atch_url = xstrdup(atch_location);
+ free_abrt_post_state(atch_state);
+ goto redirect_attach;
+ }
+ /* fall through */
+
+ default:
+ /* Error */
+ {
+ const char *errmsg = atch_state->curl_error_msg;
+ if (atch_state->body && atch_state->body[0])
+ {
+ if (errmsg && errmsg[0]
+ && strcmp(errmsg, atch_state->body) != 0
+ ) /* both strata/curl error and body are present (and aren't the same) */
+ errmsg = xasprintf("%s. %s",
+ atch_state->body,
+ errmsg);
+ else /* only body exists */
+ errmsg = atch_state->body;
+ }
+ error_msg_and_die("Can't attach. HTTP code %d%s%s",
+ atch_state->http_resp_code,
+ errmsg ? ". " : "",
+ errmsg ? errmsg : ""
+ );
+ }
+ break;
+
+ case 200:
+ case 201:
+ log("Attachment URL:%s", atch_location);
+ log("File attached successfully");
+ } /* switch */
+
+ free_abrt_post_state(atch_state);
+}
+
int main(int argc, char **argv)
{
abrt_init(argv);
- map_string_h *settings = new_map_string();
const char *dump_dir_name = ".";
+ const char *file_name = NULL;
+ const char *ticket_no = NULL;
GList *conf_file = NULL;
/* Can't keep these strings/structs static: _() doesn't support that */
const char *program_usage_string = _(
- "\b [-v] -c CONFFILE -d DIR\n"
+ "\b [-v] -c CONFFILE -d DIR [-f FILE [-t URL_SFX]]\n"
"\n"
"Reports a problem to RHTSupport.\n"
"\n"
"CONFFILE lines should have 'PARAM = VALUE' format.\n"
"Recognized string parameters: URL, Login, Password.\n"
"Recognized boolean parameter (VALUE should be 1/0, yes/no): SSLVerify.\n"
- "Parameters can be overridden via $RHTSupport_PARAM environment variables."
+ "Parameters can be overridden via $RHTSupport_PARAM environment variables.\n"
+ "\n"
+ "-f FILE uploads FILE to the already created case on RHTSupport site.\n"
+ "The location of report is retrieved from directory specified by -d DIR.\n"
+ "If problem data in DIR was never reported to RHTSupport, upload will fail.\n"
+ "\n"
+ "-f FILE -t SFX uploads FILE to an arbitrary case on RHTSupport site.\n"
+ "In this case -d DIR is ignored. The address of the case to which FILE\n"
+ "is to be uploaded is URL/SFX."
);
enum {
OPT_v = 1 << 0,
OPT_d = 1 << 1,
OPT_c = 1 << 2,
+ OPT_f = 1 << 3,
+ OPT_t = 1 << 4,
};
/* Keep enum above and order of options below in sync! */
struct options program_options[] = {
OPT__VERBOSE(&g_verbose),
OPT_STRING('d', NULL, &dump_dir_name, "DIR" , _("Dump directory")),
OPT_LIST( 'c', NULL, &conf_file , "FILE", _("Configuration file (may be given many times)")),
+ OPT_STRING('f', NULL, &file_name , "FILE", _("File to upload (attach to a case)")),
+ OPT_STRING('t', NULL, &ticket_no , "SFX" , _("URL suffix, usually it has form 'cases/123456'")),
OPT_END()
};
/*unsigned opts =*/ parse_opts(argc, argv, program_options, program_usage_string);
export_abrt_envvars(0);
+ /* Parse config, extract necessary params */
+ map_string_h *settings = new_map_string();
while (conf_file)
{
char *fn = (char *)conf_file->data;
@@ -335,6 +409,20 @@ int main(int argc, char **argv)
VERB3 log("Loaded '%s'", fn);
conf_file = g_list_remove(conf_file, fn);
}
+ char* envvar;
+ envvar = getenv("RHTSupport_URL");
+ url = xstrdup(envvar ? envvar : (get_map_string_item_or_NULL(settings, "URL") ? : "https://api.access.redhat.com/rs"));
+ envvar = getenv("RHTSupport_Login");
+ login = xstrdup(envvar ? envvar : get_map_string_item_or_empty(settings, "Login"));
+ envvar = getenv("RHTSupport_Password");
+ password = xstrdup(envvar ? envvar : get_map_string_item_or_empty(settings, "Password"));
+ envvar = getenv("RHTSupport_SSLVerify");
+ ssl_verify = string_to_bool(envvar ? envvar : get_map_string_item_or_empty(settings, "SSLVerify"));
+ if (!login[0] || !password[0])
+ {
+ error_msg_and_die(_("Empty RHTS login or password"));
+ }
+ free_map_string(settings);
VERB1 log("Initializing XML-RPC library");
xmlrpc_env env;
@@ -344,8 +432,38 @@ int main(int argc, char **argv)
error_msg_and_die("XML-RPC Fault: %s(%d)", env.fault_string, env.fault_code);
xmlrpc_env_clean(&env);
- report_to_rhtsupport(dump_dir_name, settings);
+ if (file_name)
+ {
+ if (!ticket_no)
+ {
+ struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
+ if (!dd)
+ xfunc_die();
+ report_result_t *reported_to = find_in_reported_to(dd, "RHTSupport:");
+ dd_close(dd);
+
+ if (!reported_to || !reported_to->url)
+ error_msg_and_die("Can't attach: problem data in '%s' "
+ "was not reported to RHTSupport and therefore has no URL",
+ dump_dir_name);
+
+ //log("URL:'%s'", reported_to->url);
+ //log("MSG:'%s'", reported_to->msg);
+ free(url);
+ url = reported_to->url;
+ reported_to->url = NULL;
+ free_report_result(reported_to);
+ }
+ else
+ {
+ char *url1 = concat_path_file(url, ticket_no);
+ free(url);
+ url = url1;
+ }
+ attach_to_rhtsupport(file_name);
+ }
+ else
+ report_to_rhtsupport(dump_dir_name);
- free_map_string(settings);
return 0;
}
12 years, 9 months
[PATCH] attach file to bugzilla ticket
by Nikola Pajkovsky
Signed-off-by: Nikola Pajkovsky <npajkovs(a)redhat.com>
---
src/plugins/reporter-bugzilla.c | 113 ++++++++++++++++++++++++++++++---------
1 files changed, 87 insertions(+), 26 deletions(-)
diff --git a/src/plugins/reporter-bugzilla.c b/src/plugins/reporter-bugzilla.c
index 5b58a29..4571e6d 100644
--- a/src/plugins/reporter-bugzilla.c
+++ b/src/plugins/reporter-bugzilla.c
@@ -22,35 +22,14 @@
#define XML_RPC_SUFFIX "/xmlrpc.cgi"
-static void report_to_bugzilla(const char *dump_dir_name, map_string_h *settings)
+static void report_to_bugzilla(const char *dump_dir_name, const char *login,
+ const char *password, const char *bugzilla_xmlrpc,
+ const char *bugzilla_url, int ssl_verify)
{
problem_data_t *problem_data = create_problem_data_for_reporting(dump_dir_name);
if (!problem_data)
xfunc_die(); /* create_problem_data_for_reporting already emitted error msg */
- const char *env;
- const char *login;
- const char *password;
- const char *bugzilla_xmlrpc;
- const char *bugzilla_url;
- bool ssl_verify;
-
- env = getenv("Bugzilla_Login");
- login = env ? env : get_map_string_item_or_empty(settings, "Login");
- env = getenv("Bugzilla_Password");
- password = env ? env : get_map_string_item_or_empty(settings, "Password");
- if (!login[0] || !password[0])
- error_msg_and_die(_("Empty login or password, please check your configuration"));
-
- env = getenv("Bugzilla_BugzillaURL");
- bugzilla_url = env ? env : get_map_string_item_or_empty(settings, "BugzillaURL");
- if (!bugzilla_url[0])
- bugzilla_url = "https://bugzilla.redhat.com";
- bugzilla_xmlrpc = xasprintf("%s"XML_RPC_SUFFIX, bugzilla_url);
-
- env = getenv("Bugzilla_SSLVerify");
- ssl_verify = string_to_bool(env ? env : get_map_string_item_or_empty(settings, "SSLVerify"));
-
const char *component = get_problem_item_content_or_NULL(problem_data, FILENAME_COMPONENT);
const char *duphash = get_problem_item_content_or_NULL(problem_data, FILENAME_DUPHASH);
//COMPAT, remove after 2.1 release
@@ -234,6 +213,7 @@ int main(int argc, char **argv)
/* Can't keep these strings/structs static: _() doesn't support that */
const char *program_usage_string = _(
"\b [-v] [-c CONFFILE] -d DIR\n"
+ " or: \b [-v] --ticket NUM <file> [<file>...]\n"
"\n"
"Reports problem to Bugzilla.\n"
"\n"
@@ -260,15 +240,19 @@ int main(int argc, char **argv)
OPT_v = 1 << 0,
OPT_d = 1 << 1,
OPT_c = 1 << 2,
+ OPT_t = 1 << 3,
};
+
+ static int ticket_no;
/* Keep enum above and order of options below in sync! */
struct options program_options[] = {
OPT__VERBOSE(&g_verbose),
OPT_STRING('d', NULL, &dump_dir_name, "DIR" , _("Dump directory")),
OPT_LIST( 'c', NULL, &conf_file , "FILE", _("Configuration file (may be given many times)")),
+ OPT_INTEGER('t', "ticket", &ticket_no, _("Attach file to a bugzilla ticket")),
OPT_END()
};
- /*unsigned opts =*/ parse_opts(argc, argv, program_options, program_usage_string);
+ unsigned opts = parse_opts(argc, argv, program_options, program_usage_string);
export_abrt_envvars(0);
@@ -289,7 +273,84 @@ int main(int argc, char **argv)
error_msg_and_die("XML-RPC Fault: %s(%d)", env.fault_string, env.fault_code);
xmlrpc_env_clean(&env);
- report_to_bugzilla(dump_dir_name, settings);
+ const char *environ;
+ const char *login;
+ const char *password;
+ const char *bugzilla_xmlrpc;
+ const char *bugzilla_url;
+ bool ssl_verify;
+
+ environ = getenv("Bugzilla_Login");
+ login = environ ? environ : get_map_string_item_or_empty(settings, "Login");
+ environ = getenv("Bugzilla_Password");
+ password = environ ? environ : get_map_string_item_or_empty(settings, "Password");
+ if (!login[0] || !password[0])
+ error_msg_and_die(_("Empty login or password, please check your configuration"));
+
+ environ = getenv("Bugzilla_BugzillaURL");
+ bugzilla_url = environ ? environ : get_map_string_item_or_empty(settings, "BugzillaURL");
+ if (!bugzilla_url[0])
+ bugzilla_url = "https://bugzilla.redhat.com";
+ bugzilla_xmlrpc = xasprintf("%s"XML_RPC_SUFFIX, bugzilla_url);
+
+ environ = getenv("Bugzilla_SSLVerify");
+ ssl_verify = string_to_bool(environ ? environ : get_map_string_item_or_empty(settings, "SSLVerify"));
+
+ if (opts & OPT_t)
+ {
+ if (!argv[optind])
+ show_usage_and_die(program_usage_string, program_options);
+
+ struct abrt_xmlrpc *client = abrt_xmlrpc_new_client(bugzilla_xmlrpc, ssl_verify);
+
+ log(_("Logging into Bugzilla at %s"), bugzilla_url);
+ rhbz_login(client, login, password);
+
+ while (1)
+ {
+ if (!argv[optind])
+ break;
+
+ const char *filename = argv[optind++];
+ VERB1 log("Attaching file '%s' to bugticket %i", filename, ticket_no);
+
+ FILE *fp = fopen(filename, "r");
+ char *data = NULL;
+ struct stat st;
+ if (fp)
+ {
+ if (fstat(fileno(fp), &st) != -1 && S_ISREG(st.st_mode))
+ data = xmalloc_fgets(fp);
+ else
+ {
+ error_msg("fopen: '%s': not a regular file", filename);
+ fclose(fp);
+ continue;
+ }
+
+ fclose(fp);
+ }
+ else
+ {
+ perror_msg("fopen: '%s'", filename);
+ continue;
+ }
+
+ char *ticket_no_str = xasprintf("%i", ticket_no);
+ rhbz_attachment(client, filename, ticket_no_str, data, /*flags*/ 0);
+ free(ticket_no_str);
+ free(data);
+ }
+
+ log(_("Logging out"));
+ rhbz_logout(client);
+ abrt_xmlrpc_free_client(client);
+ }
+ else
+ {
+ report_to_bugzilla(dump_dir_name, login, password, bugzilla_xmlrpc,
+ bugzilla_url, ssl_verify);
+ }
free_map_string(settings);
return 0;
--
1.7.6.345.g5c2f8
12 years, 9 months
repoted_to API brainstorm
by Denys Vlasenko
I need to parse reported_to for "attach a file to existing RHTS report"
functionality. (BZ will need the same soon). I need the latest
(most recent) reported_to line for a specific prefix.
Jiri needs to parse reported_to in order to display it in GUI.
He needs all lines parsed.
For this, I also needed to improve RHTS reported_to generation -
"MSG=Case created: https://api.access.redhat.com/rs/cases/00512471"
is not parseable. So I changed it into
"URL=https://api.access.redhat.com/rs/cases/00512471 MSG=Case created".
Unfortunately, current API:
struct report_result {
char *event;
char *data;
enum report_result_type type;
time_t timestamp;
};
char *format_report_result(const struct report_result *result);
struct report_result *parse_report_result(const char *text);
is not well-suited for either of these purposes:
it does not allow to have both URL and MSG,
and struct report_result has no provisions to contain both.
Note that we also will need EMAIL=... and also might want
to combine it with URL, MSG etc.
I propose the following API instead:
struct report_result {
time_t timestamp;
char *url;
char *msg;
char *email;
...
};
/* Find latest "PFX: ...", parse and return it. If not found, return NULL */
report_result_t *find_reported_to(struct dump_dir *dd, const char *prefix);
/* Load, parse and return all lines as list of report_result_t's */
GList *parse_reported_to(struct dump_dir *dd);
find_reported_to() is for my needs, and parse_reported_to() is for Jiri.
Formatting of reported_to lines, IMO, is handled by xasprintf()
well enough already. I tried to imagine useful helper function API
but so far I have nothing.
Please let me know what you think.
--
vda
12 years, 9 months
[PATCH] attach file to bugzilla ticket
by Nikola Pajkovsky
Signed-off-by: Nikola Pajkovsky <npajkovs(a)redhat.com>
---
src/plugins/reporter-bugzilla.c | 102 +++++++++++++++++++++++++++++----------
1 files changed, 76 insertions(+), 26 deletions(-)
diff --git a/src/plugins/reporter-bugzilla.c b/src/plugins/reporter-bugzilla.c
index 5b58a29..672380e 100644
--- a/src/plugins/reporter-bugzilla.c
+++ b/src/plugins/reporter-bugzilla.c
@@ -22,35 +22,14 @@
#define XML_RPC_SUFFIX "/xmlrpc.cgi"
-static void report_to_bugzilla(const char *dump_dir_name, map_string_h *settings)
+static void report_to_bugzilla(const char *dump_dir_name, const char *login,
+ const char *password, const char *bugzilla_xmlrpc,
+ const char *bugzilla_url, int ssl_verify)
{
problem_data_t *problem_data = create_problem_data_for_reporting(dump_dir_name);
if (!problem_data)
xfunc_die(); /* create_problem_data_for_reporting already emitted error msg */
- const char *env;
- const char *login;
- const char *password;
- const char *bugzilla_xmlrpc;
- const char *bugzilla_url;
- bool ssl_verify;
-
- env = getenv("Bugzilla_Login");
- login = env ? env : get_map_string_item_or_empty(settings, "Login");
- env = getenv("Bugzilla_Password");
- password = env ? env : get_map_string_item_or_empty(settings, "Password");
- if (!login[0] || !password[0])
- error_msg_and_die(_("Empty login or password, please check your configuration"));
-
- env = getenv("Bugzilla_BugzillaURL");
- bugzilla_url = env ? env : get_map_string_item_or_empty(settings, "BugzillaURL");
- if (!bugzilla_url[0])
- bugzilla_url = "https://bugzilla.redhat.com";
- bugzilla_xmlrpc = xasprintf("%s"XML_RPC_SUFFIX, bugzilla_url);
-
- env = getenv("Bugzilla_SSLVerify");
- ssl_verify = string_to_bool(env ? env : get_map_string_item_or_empty(settings, "SSLVerify"));
-
const char *component = get_problem_item_content_or_NULL(problem_data, FILENAME_COMPONENT);
const char *duphash = get_problem_item_content_or_NULL(problem_data, FILENAME_DUPHASH);
//COMPAT, remove after 2.1 release
@@ -234,6 +213,7 @@ int main(int argc, char **argv)
/* Can't keep these strings/structs static: _() doesn't support that */
const char *program_usage_string = _(
"\b [-v] [-c CONFFILE] -d DIR\n"
+ " or: \b [-v] --ticket NUM <file> [<file>...]\n"
"\n"
"Reports problem to Bugzilla.\n"
"\n"
@@ -260,15 +240,19 @@ int main(int argc, char **argv)
OPT_v = 1 << 0,
OPT_d = 1 << 1,
OPT_c = 1 << 2,
+ OPT_t = 1 << 3,
};
+
+ static int ticket_no;
/* Keep enum above and order of options below in sync! */
struct options program_options[] = {
OPT__VERBOSE(&g_verbose),
OPT_STRING('d', NULL, &dump_dir_name, "DIR" , _("Dump directory")),
OPT_LIST( 'c', NULL, &conf_file , "FILE", _("Configuration file (may be given many times)")),
+ OPT_INTEGER('t', "ticket", &ticket_no, _("Attach file to a bugzilla ticket")),
OPT_END()
};
- /*unsigned opts =*/ parse_opts(argc, argv, program_options, program_usage_string);
+ unsigned opts = parse_opts(argc, argv, program_options, program_usage_string);
export_abrt_envvars(0);
@@ -289,7 +273,73 @@ int main(int argc, char **argv)
error_msg_and_die("XML-RPC Fault: %s(%d)", env.fault_string, env.fault_code);
xmlrpc_env_clean(&env);
- report_to_bugzilla(dump_dir_name, settings);
+ const char *environ;
+ const char *login;
+ const char *password;
+ const char *bugzilla_xmlrpc;
+ const char *bugzilla_url;
+ bool ssl_verify;
+
+ environ = getenv("Bugzilla_Login");
+ login = environ ? environ : get_map_string_item_or_empty(settings, "Login");
+ environ = getenv("Bugzilla_Password");
+ password = environ ? environ : get_map_string_item_or_empty(settings, "Password");
+ if (!login[0] || !password[0])
+ error_msg_and_die(_("Empty login or password, please check your configuration"));
+
+ environ = getenv("Bugzilla_BugzillaURL");
+ bugzilla_url = environ ? environ : get_map_string_item_or_empty(settings, "BugzillaURL");
+ if (!bugzilla_url[0])
+ bugzilla_url = "https://bugzilla.redhat.com";
+ bugzilla_xmlrpc = xasprintf("%s"XML_RPC_SUFFIX, bugzilla_url);
+
+ environ = getenv("Bugzilla_SSLVerify");
+ ssl_verify = string_to_bool(environ ? environ : get_map_string_item_or_empty(settings, "SSLVerify"));
+
+ if (opts & OPT_t)
+ {
+ if (!argv[optind])
+ show_usage_and_die(program_usage_string, program_options);
+
+ struct abrt_xmlrpc *client = abrt_xmlrpc_new_client(bugzilla_xmlrpc, ssl_verify);
+
+ log(_("Logging into Bugzilla at %s"), bugzilla_url);
+ rhbz_login(client, login, password);
+
+ while (1)
+ {
+ if (!argv[optind])
+ break;
+
+ const char *filename = argv[optind++];
+ VERB1 log("Attaching file '%s' to bugticket %i", filename, ticket_no);
+
+ FILE *fp = fopen(filename, "r");
+ if (!fp)
+ {
+ perror_msg("fopen: '%s'", filename);
+ continue;
+ }
+
+ char *data = xmalloc_fgets(fp);
+
+ char *ticket_no_str = xasprintf("%i", ticket_no);
+ rhbz_attachment(client, filename, ticket_no_str, data, /*flags*/ 0);
+ free(ticket_no_str);
+ free(data);
+
+ fclose(fp);
+ }
+
+ log(_("Logging out"));
+ rhbz_logout(client);
+ abrt_xmlrpc_free_client(client);
+ }
+ else
+ {
+ report_to_bugzilla(dump_dir_name, login, password, bugzilla_xmlrpc,
+ bugzilla_url, ssl_verify);
+ }
free_map_string(settings);
return 0;
--
1.7.6.345.g5c2f8
12 years, 9 months
[PATCH] [abrt] abrt-cli report @0
by Nikola Pajkovsky
abrt-cli can report problems by specifying number of crash instead of
long path name.
Signed-off-by: Nikola Pajkovsky <npajkovs(a)redhat.com>
---
src/cli/Makefile.am | 3 +-
src/cli/abrt-cli-core.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++
src/cli/abrt-cli-core.h | 32 ++++++++++++++++
src/cli/list.c | 85 ++++-------------------------------------
src/cli/report.c | 36 +++++++++++++++++-
5 files changed, 173 insertions(+), 78 deletions(-)
create mode 100644 src/cli/abrt-cli-core.c
create mode 100644 src/cli/abrt-cli-core.h
diff --git a/src/cli/Makefile.am b/src/cli/Makefile.am
index bbd1402..3839e3c 100644
--- a/src/cli/Makefile.am
+++ b/src/cli/Makefile.am
@@ -4,13 +4,14 @@ bin_PROGRAMS = abrt-cli
CLI_C =
CLI_C += abrt-cli.c
+CLI_C += abrt-cli-core.c
BUILTIN_C =
BUILTIN_C += list.c
BUILTIN_C += rm.c
BUILTIN_C += report.c
-abrt_cli_SOURCES = $(CLI_C) $(BUILTIN_C) builtin-cmd.h
+abrt_cli_SOURCES = $(CLI_C) $(BUILTIN_C) builtin-cmd.h abrt-cli-core.h
abrt_cli_CFLAGS = \
-I$(srcdir)/../include \
diff --git a/src/cli/abrt-cli-core.c b/src/cli/abrt-cli-core.c
new file mode 100644
index 0000000..0221f03
--- /dev/null
+++ b/src/cli/abrt-cli-core.c
@@ -0,0 +1,95 @@
+/*
+ Copyright (C) 2011 ABRT Team
+ Copyright (C) 2011 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"
+#include "abrt-cli-core.h"
+
+/* Vector of problems: */
+/* problem_data_vector[i] = { "name" = { "content", CD_FLAG_foo_bits } } */
+
+inline problem_data_t *get_problem_data(vector_of_problem_data_t *vector, unsigned i)
+{
+ return (problem_data_t *)g_ptr_array_index(vector, i);
+}
+
+void free_vector_of_problem_data(vector_of_problem_data_t *vector)
+{
+ if (vector)
+ g_ptr_array_free(vector, TRUE);
+}
+
+vector_of_problem_data_t *new_vector_of_problem_data(void)
+{
+ return g_ptr_array_new_with_free_func((void (*)(void*)) &free_problem_data);
+}
+
+problem_data_t *fill_crash_info(const char *dump_dir_name)
+{
+ int sv_logmode = logmode;
+ logmode = 0; /* suppress EPERM/EACCES errors in opendir */
+ struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ DD_OPEN_READONLY);
+ logmode = sv_logmode;
+
+ if (!dd)
+ return NULL;
+
+ problem_data_t *problem_data = create_problem_data_from_dump_dir(dd);
+ dd_close(dd);
+ add_to_problem_data_ext(problem_data, CD_DUMPDIR, dump_dir_name,
+ CD_FLAG_TXT + CD_FLAG_ISNOTEDITABLE + CD_FLAG_LIST);
+
+ return problem_data;
+}
+
+vector_of_problem_data_t *fetch_crash_infos(GList *dir_list)
+{
+ vector_of_problem_data_t *ci = new_vector_of_problem_data();
+ for (GList *li = dir_list; li; li = li->next)
+ {
+ char *dir_name = (char *)li->data;
+ VERB1 log("Loading dumps from '%s'", dir_name);
+
+ DIR *dir = opendir(dir_name);
+ if (dir != NULL)
+ {
+ struct dirent *dent;
+ while ((dent = readdir(dir)) != NULL)
+ {
+ if (dot_or_dotdot(dent->d_name))
+ continue; /* skip "." and ".." */
+
+ char *dump_dir_name = concat_path_file(dir_name, dent->d_name);
+
+ struct stat statbuf;
+ if (stat(dump_dir_name, &statbuf) == 0
+ && S_ISDIR(statbuf.st_mode))
+ {
+ problem_data_t *problem_data = fill_crash_info(dump_dir_name);
+ if (problem_data)
+ g_ptr_array_add(ci, problem_data);
+ }
+ free(dump_dir_name);
+ }
+ closedir(dir);
+ }
+ }
+
+ return ci;
+}
+
diff --git a/src/cli/abrt-cli-core.h b/src/cli/abrt-cli-core.h
new file mode 100644
index 0000000..55a307b
--- /dev/null
+++ b/src/cli/abrt-cli-core.h
@@ -0,0 +1,32 @@
+/*
+ Copyright (C) 2011 ABRT Team
+ Copyright (C) 2011 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.
+*/
+
+#ifndef ABRT_CLI_CORE_H_
+#define ABRT_CLI_CORE_H_
+
+typedef GPtrArray vector_of_problem_data_t;
+
+problem_data_t *get_problem_data(vector_of_problem_data_t *vector, unsigned i);
+
+void free_vector_of_problem_data(vector_of_problem_data_t *vector);
+vector_of_problem_data_t *new_vector_of_problem_data(void);
+problem_data_t *fill_crash_info(const char *dump_dir_name);
+vector_of_problem_data_t *fetch_crash_infos(GList *dir_list);
+
+#endif /* ABRT_CLI_CORE_H_ */
diff --git a/src/cli/list.c b/src/cli/list.c
index e4f30fe..131111a 100644
--- a/src/cli/list.c
+++ b/src/cli/list.c
@@ -18,6 +18,8 @@
*/
#include "abrtlib.h"
+
+#include "abrt-cli-core.h"
#include "builtin-cmd.h"
/* TODO: npajkovs
@@ -30,73 +32,6 @@
* ~/.abrt/spool and /var/spool/abrt? needs more _meditation_.
*/
-/* Vector of problems: */
-/* problem_data_vector[i] = { "name" = { "content", CD_FLAG_foo_bits } } */
-typedef GPtrArray vector_of_problem_data_t;
-
-static inline problem_data_t *get_problem_data(vector_of_problem_data_t *vector, unsigned i)
-{
- return (problem_data_t *)g_ptr_array_index(vector, i);
-}
-
-static void free_vector_of_problem_data(vector_of_problem_data_t *vector)
-{
- if (vector)
- g_ptr_array_free(vector, TRUE);
-}
-
-static vector_of_problem_data_t *new_vector_of_problem_data(void)
-{
- return g_ptr_array_new_with_free_func((void (*)(void*)) &free_problem_data);
-}
-
-static problem_data_t *fill_crash_info(const char *dump_dir_name)
-{
- int sv_logmode = logmode;
- logmode = 0; /* suppress EPERM/EACCES errors in opendir */
- struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ DD_OPEN_READONLY);
- logmode = sv_logmode;
-
- if (!dd)
- return NULL;
-
- problem_data_t *problem_data = create_problem_data_from_dump_dir(dd);
- dd_close(dd);
- add_to_problem_data_ext(problem_data, CD_DUMPDIR, dump_dir_name,
- CD_FLAG_TXT + CD_FLAG_ISNOTEDITABLE + CD_FLAG_LIST);
-
- return problem_data;
-}
-
-static void get_all_crash_infos(vector_of_problem_data_t *retval, const char *dir_name)
-{
- VERB1 log("Loading dumps from '%s'", dir_name);
-
- DIR *dir = opendir(dir_name);
- if (dir != NULL)
- {
- struct dirent *dent;
- while ((dent = readdir(dir)) != NULL)
- {
- if (dot_or_dotdot(dent->d_name))
- continue; /* skip "." and ".." */
-
- char *dump_dir_name = concat_path_file(dir_name, dent->d_name);
-
- struct stat statbuf;
- if (stat(dump_dir_name, &statbuf) == 0
- && S_ISDIR(statbuf.st_mode))
- {
- problem_data_t *problem_data = fill_crash_info(dump_dir_name);
- if (problem_data)
- g_ptr_array_add(retval, problem_data);
- }
- free(dump_dir_name);
- }
- closedir(dir);
- }
-}
-
/** Prints basic information about a crash to stdout. */
static void print_crash(problem_data_t *problem_data, int detailed)
{
@@ -141,6 +76,8 @@ static void print_crash_list(vector_of_problem_data_t *crash_list, int include_r
if (msg)
continue;
}
+
+ printf("@%i\n", i);
print_crash(crash, detailed);
if (i != crash_list->len - 1)
printf("\n");
@@ -187,17 +124,13 @@ int cmd_list(int argc, const char **argv)
log("\t %s", (char *) li->data);
}
- vector_of_problem_data_t *ci = new_vector_of_problem_data();
- while (D_list)
- {
- char *dir = (char *)D_list->data;
- get_all_crash_infos(ci, dir);
- D_list = g_list_remove(D_list, dir);
- free(dir);
- }
+ vector_of_problem_data_t *ci = fetch_crash_infos(D_list);
+
+ g_ptr_array_sort_with_data(ci, &cmp_problem_data, (char *) FILENAME_TIME);
+
print_crash_list(ci, opt_full, opt_detailed);
free_vector_of_problem_data(ci);
- g_list_free(D_list);
+ list_free_with_free(D_list);
return 0;
}
diff --git a/src/cli/report.c b/src/cli/report.c
index ce22456..770468a 100644
--- a/src/cli/report.c
+++ b/src/cli/report.c
@@ -18,6 +18,8 @@
*/
#include "abrtlib.h"
+
+#include "abrt-cli-core.h"
#include "builtin-cmd.h"
int cmd_report(int argc, const char **argv)
@@ -32,14 +34,46 @@ int cmd_report(int argc, const char **argv)
};
parse_opts(argc, (char **)argv, program_options, program_usage_string);
+
+ load_abrt_conf();
+ char *home = getenv("HOME");
+ GList *D_list = NULL;
+ if (home)
+ D_list = g_list_append(D_list, concat_path_file(home, ".abrt/spool"));
+ D_list = g_list_append(D_list, xstrdup(g_settings_dump_location));
+ free_abrt_conf_data();
+
if (optind < argc)
{
while (optind < argc)
{
- int status = report_problem_in_dir(argv[optind++],
+ const char *dir_name = argv[optind++];
+
+ vector_of_problem_data_t *ci = NULL;
+ if (*dir_name == '@')
+ {
+ dir_name++;
+ char *end;
+ errno = 0;
+ unsigned long at = strtoul(dir_name, &end, 10);
+ if (errno || end == dir_name || *end != '\0')
+ error_msg_and_die("error: not a number '%s'", dir_name);
+
+ ci = fetch_crash_infos(D_list);
+ if (at >= ci->len)
+ error_msg_and_die("error: number is out of range '%s'", dir_name);
+
+ g_ptr_array_sort_with_data(ci, &cmp_problem_data, (char *) FILENAME_TIME);
+ problem_data_t *pd = get_problem_data(ci, at);
+
+ dir_name = get_problem_item_content_or_NULL(pd, CD_DUMPDIR);
+ }
+
+ int status = report_problem_in_dir(dir_name,
LIBREPORT_ANALYZE
| LIBREPORT_WAIT
| LIBREPORT_RUN_CLI);
+ free_vector_of_problem_data(ci);
if (status)
exit(status);
}
--
1.7.6.345.g5c2f8
12 years, 9 months