From deabb987d709ef8512d61d41e44bcb77c3f5bff6 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 9 Dec 2010 14:17:52 +0100 Subject: rename a few more files from .cpp to .c Renamed files: KerneloopsSysLog.c abrt-action-rhtsupport.c abrt-action-upload.c abrt-action-kerneloops.c abrt-action-mailx.c abrt-action-print.c Signed-off-by: Denys Vlasenko --- src/plugins/KerneloopsSysLog.c | 383 +++++++++++++++++++++++++++++++++ src/plugins/KerneloopsSysLog.cpp | 383 --------------------------------- src/plugins/Makefile.am | 17 +- src/plugins/abrt-action-kerneloops.c | 183 ++++++++++++++++ src/plugins/abrt-action-kerneloops.cpp | 183 ---------------- src/plugins/abrt-action-mailx.c | 172 +++++++++++++++ src/plugins/abrt-action-mailx.cpp | 170 --------------- src/plugins/abrt-action-print.c | 96 +++++++++ src/plugins/abrt-action-print.cpp | 96 --------- src/plugins/abrt-action-rhtsupport.c | 321 +++++++++++++++++++++++++++ src/plugins/abrt-action-rhtsupport.cpp | 321 --------------------------- src/plugins/abrt-action-upload.c | 287 ++++++++++++++++++++++++ src/plugins/abrt-action-upload.cpp | 287 ------------------------ 13 files changed, 1452 insertions(+), 1447 deletions(-) create mode 100644 src/plugins/KerneloopsSysLog.c delete mode 100644 src/plugins/KerneloopsSysLog.cpp create mode 100644 src/plugins/abrt-action-kerneloops.c delete mode 100644 src/plugins/abrt-action-kerneloops.cpp create mode 100644 src/plugins/abrt-action-mailx.c delete mode 100644 src/plugins/abrt-action-mailx.cpp create mode 100644 src/plugins/abrt-action-print.c delete mode 100644 src/plugins/abrt-action-print.cpp create mode 100644 src/plugins/abrt-action-rhtsupport.c delete mode 100644 src/plugins/abrt-action-rhtsupport.cpp create mode 100644 src/plugins/abrt-action-upload.c delete mode 100644 src/plugins/abrt-action-upload.cpp (limited to 'src/plugins') diff --git a/src/plugins/KerneloopsSysLog.c b/src/plugins/KerneloopsSysLog.c new file mode 100644 index 00000000..f69503af --- /dev/null +++ b/src/plugins/KerneloopsSysLog.c @@ -0,0 +1,383 @@ +/* + Copyright (C) 2010 ABRT team + Copyright (C) 2010 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. + + Authors: + Anton Arapov + Arjan van de Ven + */ +#include "abrtlib.h" +#include "KerneloopsSysLog.h" +#include + +static void queue_oops(GList **vec, const char *data, const char *version) +{ + char *ver_data = xasprintf("%s\n%s", version, data); + *vec = g_list_append(*vec, ver_data); +} + +/* + * extract_version tries to find the kernel version in given data + */ +static char *extract_version(const char *linepointer) +{ + if (strstr(linepointer, "Pid") + || strstr(linepointer, "comm") + || strstr(linepointer, "CPU") + || strstr(linepointer, "REGS") + || strstr(linepointer, "EFLAGS") + ) { + char* start; + char* end; + + start = strstr((char*)linepointer, "2.6."); + if (start) + { + end = strchr(start, ')'); + if (!end) + end = strchrnul(start, ' '); + return xstrndup(start, end-start); + } + } + + return NULL; +} + +/* + * extract_oops tries to find oops signatures in a log + */ +struct line_info { + char *ptr; + char level; +}; + +static int record_oops(GList **oopses, struct line_info* lines_info, int oopsstart, int oopsend) +{ + int q; + int len; + char *oops; + char *version; + + len = 2; + for (q = oopsstart; q <= oopsend; q++) + len += strlen(lines_info[q].ptr) + 1; + + oops = (char*)xzalloc(len); + + version = NULL; + for (q = oopsstart; q <= oopsend; q++) + { + if (!version) + version = extract_version(lines_info[q].ptr); + + if (lines_info[q].ptr[0]) + { + strcat(oops, lines_info[q].ptr); + strcat(oops, "\n"); + } + } + int rv = 1; + /* too short oopses are invalid */ + if (strlen(oops) > 100) + queue_oops(oopses, oops, version ? version : "undefined"); + else + { + VERB3 log("Dropped oops: too short"); + rv = 0; + } + free(oops); + free(version); + return rv; +} +#define REALLOC_CHUNK 1000 +int extract_oopses(GList **oopses, char *buffer, size_t buflen) +{ + char *c; + int linecount = 0; + int lines_info_alloc = 0; + struct line_info *lines_info = NULL; + + /* Split buffer into lines */ + + if (buflen != 0) + buffer[buflen - 1] = '\n'; /* the buffer usually ends with \n, but let's make sure */ + c = buffer; + while (c < buffer + buflen) + { + char linelevel; + char *c9; + char *colon; + + c9 = (char*)memchr(c, '\n', buffer + buflen - c); /* a \n will always be found */ + assert(c9); + *c9 = '\0'; /* turn the \n into a string termination */ + if (c9 == c) + goto next_line; + + /* Is it a syslog file (/var/log/messages or similar)? + * Even though _usually_ it looks like "Nov 19 12:34:38 localhost kernel: xxx", + * some users run syslog in non-C locale: + * "2010-02-22T09:24:08.156534-08:00 gnu-4 gnome-session[2048]: blah blah" + * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ !!! + * We detect it by checking for N:NN:NN pattern in first 15 chars + * (and this still is not good enough... false positive: "pci 0000:15:00.0: PME# disabled") + */ + colon = strchr(c, ':'); + if (colon && colon > c && colon < c + 15 + && isdigit(colon[-1]) /* N:... */ + && isdigit(colon[1]) /* ...N:NN:... */ + && isdigit(colon[2]) + && colon[3] == ':' + && isdigit(colon[4]) /* ...N:NN:NN... */ + && isdigit(colon[5]) + ) { + /* It's syslog file, not a bare dmesg */ + + /* Skip non-kernel lines */ + char *kernel_str = strstr(c, "kernel: "); + if (kernel_str == NULL) + { + /* if we see our own marker: + * "hostname abrt: Kerneloops: Reported 1 kernel oopses to Abrt" + * we know we submitted everything upto here already */ + if (strstr(c, "abrt:") && strstr(c, "Abrt")) + { + VERB3 log("Found our marker at line %d, restarting line count from 0", linecount); + linecount = 0; + lines_info_alloc = 0; + free(lines_info); + lines_info = NULL; + } + goto next_line; + } + c = kernel_str + sizeof("kernel: ")-1; + } + + linelevel = 0; + /* store and remove kernel log level */ + if (*c == '<' && c[1] && c[2] == '>') + { + linelevel = c[1]; + c += 3; + } + /* remove jiffies time stamp counter if present */ + if (*c == '[') + { + char *c2 = strchr(c, '.'); + char *c3 = strchr(c, ']'); + if (c2 && c3 && (c2 < c3) && (c3-c) < 14 && (c2-c) < 8) + { + c = c3 + 1; + if (*c == ' ') + c++; + } + } + if (linecount >= lines_info_alloc) + { + lines_info_alloc += REALLOC_CHUNK; + lines_info = (struct line_info*)xrealloc(lines_info, + lines_info_alloc * sizeof(lines_info[0])); + } + lines_info[linecount].ptr = c; + lines_info[linecount].level = linelevel; + linecount++; +next_line: + c = c9 + 1; + } + + /* Analyze lines */ + + int i; + char prevlevel = 0; + int oopsstart = -1; + int inbacktrace = 0; + int oopsesfound = 0; + + i = 0; + while (i < linecount) + { + char *curline = lines_info[i].ptr; + + if (curline == NULL) + { + i++; + continue; + } + while (*curline == ' ') + curline++; + + if (oopsstart < 0) + { + /* find start-of-oops markers */ + if (strstr(curline, "general protection fault:")) + oopsstart = i; + else if (strstr(curline, "BUG:")) + oopsstart = i; + else if (strstr(curline, "kernel BUG at")) + oopsstart = i; + else if (strstr(curline, "do_IRQ: stack overflow:")) + oopsstart = i; + else if (strstr(curline, "RTNL: assertion failed")) + oopsstart = i; + else if (strstr(curline, "Eeek! page_mapcount(page) went negative!")) + oopsstart = i; + else if (strstr(curline, "near stack overflow (cur:")) + oopsstart = i; + else if (strstr(curline, "double fault:")) + oopsstart = i; + else if (strstr(curline, "Badness at")) + oopsstart = i; + else if (strstr(curline, "NETDEV WATCHDOG")) + oopsstart = i; + else if (strstr(curline, "WARNING: at ")) /* WARN_ON() generated message */ + oopsstart = i; + else if (strstr(curline, "Unable to handle kernel")) + oopsstart = i; + else if (strstr(curline, "sysctl table check failed")) + oopsstart = i; + else if (strstr(curline, "INFO: possible recursive locking detected")) + oopsstart = i; + // Not needed: "--[ cut here ]--" is always followed + // by "Badness at", "kernel BUG at", or "WARNING: at" string + //else if (strstr(curline, "------------[ cut here ]------------")) + // oopsstart = i; + else if (strstr(curline, "list_del corruption.")) + oopsstart = i; + else if (strstr(curline, "list_add corruption.")) + oopsstart = i; + if (strstr(curline, "Oops:") && i >= 3) + oopsstart = i-3; + + if (oopsstart >= 0) + { + /* debug information */ + VERB3 { + log("Found oops at line %d: '%s'", oopsstart, lines_info[oopsstart].ptr); + if (oopsstart != i) + log("Trigger line is %d: '%s'", i, c); + } + /* try to find the end marker */ + int i2 = i + 1; + while (i2 < linecount && i2 < (i+50)) + { + if (strstr(lines_info[i2].ptr, "---[ end trace")) + { + inbacktrace = 1; + i = i2; + break; + } + i2++; + } + } + } + + /* Are we entering a call trace part? */ + /* a call trace starts with "Call Trace:" or with the " [<.......>] function+0xFF/0xAA" pattern */ + if (oopsstart >= 0 && !inbacktrace) + { + if (strstr(curline, "Call Trace:")) + inbacktrace = 1; + else + if (strnlen(curline, 9) > 8 + && curline[0] == '[' && curline[1] == '<' + && strstr(curline, ">]") + && strstr(curline, "+0x") + && strstr(curline, "/0x") + ) { + inbacktrace = 1; + } + } + + /* Are we at the end of an oops? */ + else if (oopsstart >= 0 && inbacktrace) + { + int oopsend = INT_MAX; + + /* line needs to start with " [" or have "] [" if it is still a call trace */ + /* example: "[] radeon_get_ring_head+0x16/0x41 [radeon]" */ + if (curline[0] != '[' + && !strstr(curline, "] [") + && !strstr(curline, "--- Exception") + && !strstr(curline, "LR =") + && !strstr(curline, "<#DF>") + && !strstr(curline, "") + && !strstr(curline, "") + && !strstr(curline, "<>") + && strncmp(curline, "Code: ", 6) != 0 + && strncmp(curline, "RIP ", 4) != 0 + && strncmp(curline, "RSP ", 4) != 0 + ) { + oopsend = i-1; /* not a call trace line */ + } + /* oops lines are always more than 8 chars long */ + else if (strnlen(curline, 8) < 8) + oopsend = i-1; + /* single oopses are of the same loglevel */ + else if (lines_info[i].level != prevlevel) + oopsend = i-1; + else if (strstr(curline, "Instruction dump:")) + oopsend = i; + /* if a new oops starts, this one has ended */ + else if (strstr(curline, "WARNING: at ") && oopsstart != i) /* WARN_ON() generated message */ + oopsend = i-1; + else if (strstr(curline, "Unable to handle") && oopsstart != i) + oopsend = i-1; + /* kernel end-of-oops marker (not including marker itself) */ + else if (strstr(curline, "---[ end trace")) + oopsend = i-1; + + if (oopsend <= i) + { + VERB3 log("End of oops at line %d (%d): '%s'", oopsend, i, lines_info[oopsend].ptr); + if (record_oops(oopses, lines_info, oopsstart, oopsend)) + oopsesfound++; + oopsstart = -1; + inbacktrace = 0; + } + } + + prevlevel = lines_info[i].level; + i++; + + if (oopsstart >= 0) + { + /* Do we have a suspiciously long oops? Cancel it */ + if (i-oopsstart > 60) + { + inbacktrace = 0; + oopsstart = -1; + VERB3 log("Dropped oops, too long"); + continue; + } + if (!inbacktrace && i-oopsstart > 40) + { + /*inbacktrace = 0; - already is */ + oopsstart = -1; + VERB3 log("Dropped oops, too long"); + continue; + } + } + } /* while (i < linecount) */ + + /* process last oops if we have one */ + if (oopsstart >= 0 && inbacktrace) + { + int oopsend = i-1; + VERB3 log("End of oops at line %d (end of file): '%s'", oopsend, lines_info[oopsend].ptr); + if (record_oops(oopses, lines_info, oopsstart, oopsend)) + oopsesfound++; + } + + free(lines_info); + return oopsesfound; +} diff --git a/src/plugins/KerneloopsSysLog.cpp b/src/plugins/KerneloopsSysLog.cpp deleted file mode 100644 index 68f309bc..00000000 --- a/src/plugins/KerneloopsSysLog.cpp +++ /dev/null @@ -1,383 +0,0 @@ -/* - Copyright (C) 2010 ABRT team - Copyright (C) 2010 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. - - Authors: - Anton Arapov - Arjan van de Ven - */ -#include "abrtlib.h" -#include "KerneloopsSysLog.h" -#include - -static void queue_oops(GList **vec, const char *data, const char *version) -{ - char *ver_data = xasprintf("%s\n%s", version, data); - *vec = g_list_append(*vec, ver_data); -} - -/* - * extract_version tries to find the kernel version in given data - */ -static char *extract_version(const char *linepointer) -{ - if (strstr(linepointer, "Pid") - || strstr(linepointer, "comm") - || strstr(linepointer, "CPU") - || strstr(linepointer, "REGS") - || strstr(linepointer, "EFLAGS") - ) { - char* start; - char* end; - - start = strstr((char*)linepointer, "2.6."); - if (start) - { - end = strchr(start, ')'); - if (!end) - end = strchrnul(start, ' '); - return xstrndup(start, end-start); - } - } - - return NULL; -} - -/* - * extract_oops tries to find oops signatures in a log - */ -struct line_info { - char *ptr; - char level; -}; - -static int record_oops(GList **oopses, struct line_info* lines_info, int oopsstart, int oopsend) -{ - int q; - int len; - char *oops; - char *version; - - len = 2; - for (q = oopsstart; q <= oopsend; q++) - len += strlen(lines_info[q].ptr) + 1; - - oops = (char*)xzalloc(len); - - version = NULL; - for (q = oopsstart; q <= oopsend; q++) - { - if (!version) - version = extract_version(lines_info[q].ptr); - - if (lines_info[q].ptr[0]) - { - strcat(oops, lines_info[q].ptr); - strcat(oops, "\n"); - } - } - int rv = 1; - /* too short oopses are invalid */ - if (strlen(oops) > 100) - queue_oops(oopses, oops, version ? version : "undefined"); - else - { - VERB3 log("Dropped oops: too short"); - rv = 0; - } - free(oops); - free(version); - return rv; -} -#define REALLOC_CHUNK 1000 -int extract_oopses(GList **oopses, char *buffer, size_t buflen) -{ - char *c; - int linecount = 0; - int lines_info_alloc = 0; - struct line_info *lines_info = NULL; - - /* Split buffer into lines */ - - if (buflen != 0) - buffer[buflen - 1] = '\n'; /* the buffer usually ends with \n, but let's make sure */ - c = buffer; - while (c < buffer + buflen) - { - char linelevel; - char *c9; - char *colon; - - c9 = (char*)memchr(c, '\n', buffer + buflen - c); /* a \n will always be found */ - assert(c9); - *c9 = '\0'; /* turn the \n into a string termination */ - if (c9 == c) - goto next_line; - - /* Is it a syslog file (/var/log/messages or similar)? - * Even though _usually_ it looks like "Nov 19 12:34:38 localhost kernel: xxx", - * some users run syslog in non-C locale: - * "2010-02-22T09:24:08.156534-08:00 gnu-4 gnome-session[2048]: blah blah" - * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ !!! - * We detect it by checking for N:NN:NN pattern in first 15 chars - * (and this still is not good enough... false positive: "pci 0000:15:00.0: PME# disabled") - */ - colon = strchr(c, ':'); - if (colon && colon > c && colon < c + 15 - && isdigit(colon[-1]) /* N:... */ - && isdigit(colon[1]) /* ...N:NN:... */ - && isdigit(colon[2]) - && colon[3] == ':' - && isdigit(colon[4]) /* ...N:NN:NN... */ - && isdigit(colon[5]) - ) { - /* It's syslog file, not a bare dmesg */ - - /* Skip non-kernel lines */ - char *kernel_str = strstr(c, "kernel: "); - if (kernel_str == NULL) - { - /* if we see our own marker: - * "hostname abrt: Kerneloops: Reported 1 kernel oopses to Abrt" - * we know we submitted everything upto here already */ - if (strstr(c, "abrt:") && strstr(c, "Abrt")) - { - VERB3 log("Found our marker at line %d, restarting line count from 0", linecount); - linecount = 0; - lines_info_alloc = 0; - free(lines_info); - lines_info = NULL; - } - goto next_line; - } - c = kernel_str + sizeof("kernel: ")-1; - } - - linelevel = 0; - /* store and remove kernel log level */ - if (*c == '<' && c[1] && c[2] == '>') - { - linelevel = c[1]; - c += 3; - } - /* remove jiffies time stamp counter if present */ - if (*c == '[') - { - char *c2 = strchr(c, '.'); - char *c3 = strchr(c, ']'); - if (c2 && c3 && (c2 < c3) && (c3-c) < 14 && (c2-c) < 8) - { - c = c3 + 1; - if (*c == ' ') - c++; - } - } - if (linecount >= lines_info_alloc) - { - lines_info_alloc += REALLOC_CHUNK; - lines_info = (line_info*)xrealloc(lines_info, - lines_info_alloc * sizeof(struct line_info)); - } - lines_info[linecount].ptr = c; - lines_info[linecount].level = linelevel; - linecount++; -next_line: - c = c9 + 1; - } - - /* Analyze lines */ - - int i; - char prevlevel = 0; - int oopsstart = -1; - int inbacktrace = 0; - int oopsesfound = 0; - - i = 0; - while (i < linecount) - { - char *curline = lines_info[i].ptr; - - if (curline == NULL) - { - i++; - continue; - } - while (*curline == ' ') - curline++; - - if (oopsstart < 0) - { - /* find start-of-oops markers */ - if (strstr(curline, "general protection fault:")) - oopsstart = i; - else if (strstr(curline, "BUG:")) - oopsstart = i; - else if (strstr(curline, "kernel BUG at")) - oopsstart = i; - else if (strstr(curline, "do_IRQ: stack overflow:")) - oopsstart = i; - else if (strstr(curline, "RTNL: assertion failed")) - oopsstart = i; - else if (strstr(curline, "Eeek! page_mapcount(page) went negative!")) - oopsstart = i; - else if (strstr(curline, "near stack overflow (cur:")) - oopsstart = i; - else if (strstr(curline, "double fault:")) - oopsstart = i; - else if (strstr(curline, "Badness at")) - oopsstart = i; - else if (strstr(curline, "NETDEV WATCHDOG")) - oopsstart = i; - else if (strstr(curline, "WARNING: at ")) /* WARN_ON() generated message */ - oopsstart = i; - else if (strstr(curline, "Unable to handle kernel")) - oopsstart = i; - else if (strstr(curline, "sysctl table check failed")) - oopsstart = i; - else if (strstr(curline, "INFO: possible recursive locking detected")) - oopsstart = i; - // Not needed: "--[ cut here ]--" is always followed - // by "Badness at", "kernel BUG at", or "WARNING: at" string - //else if (strstr(curline, "------------[ cut here ]------------")) - // oopsstart = i; - else if (strstr(curline, "list_del corruption.")) - oopsstart = i; - else if (strstr(curline, "list_add corruption.")) - oopsstart = i; - if (strstr(curline, "Oops:") && i >= 3) - oopsstart = i-3; - - if (oopsstart >= 0) - { - /* debug information */ - VERB3 { - log("Found oops at line %d: '%s'", oopsstart, lines_info[oopsstart].ptr); - if (oopsstart != i) - log("Trigger line is %d: '%s'", i, c); - } - /* try to find the end marker */ - int i2 = i + 1; - while (i2 < linecount && i2 < (i+50)) - { - if (strstr(lines_info[i2].ptr, "---[ end trace")) - { - inbacktrace = 1; - i = i2; - break; - } - i2++; - } - } - } - - /* Are we entering a call trace part? */ - /* a call trace starts with "Call Trace:" or with the " [<.......>] function+0xFF/0xAA" pattern */ - if (oopsstart >= 0 && !inbacktrace) - { - if (strstr(curline, "Call Trace:")) - inbacktrace = 1; - else - if (strnlen(curline, 9) > 8 - && curline[0] == '[' && curline[1] == '<' - && strstr(curline, ">]") - && strstr(curline, "+0x") - && strstr(curline, "/0x") - ) { - inbacktrace = 1; - } - } - - /* Are we at the end of an oops? */ - else if (oopsstart >= 0 && inbacktrace) - { - int oopsend = INT_MAX; - - /* line needs to start with " [" or have "] [" if it is still a call trace */ - /* example: "[] radeon_get_ring_head+0x16/0x41 [radeon]" */ - if (curline[0] != '[' - && !strstr(curline, "] [") - && !strstr(curline, "--- Exception") - && !strstr(curline, "LR =") - && !strstr(curline, "<#DF>") - && !strstr(curline, "") - && !strstr(curline, "") - && !strstr(curline, "<>") - && strncmp(curline, "Code: ", 6) != 0 - && strncmp(curline, "RIP ", 4) != 0 - && strncmp(curline, "RSP ", 4) != 0 - ) { - oopsend = i-1; /* not a call trace line */ - } - /* oops lines are always more than 8 chars long */ - else if (strnlen(curline, 8) < 8) - oopsend = i-1; - /* single oopses are of the same loglevel */ - else if (lines_info[i].level != prevlevel) - oopsend = i-1; - else if (strstr(curline, "Instruction dump:")) - oopsend = i; - /* if a new oops starts, this one has ended */ - else if (strstr(curline, "WARNING: at ") && oopsstart != i) /* WARN_ON() generated message */ - oopsend = i-1; - else if (strstr(curline, "Unable to handle") && oopsstart != i) - oopsend = i-1; - /* kernel end-of-oops marker (not including marker itself) */ - else if (strstr(curline, "---[ end trace")) - oopsend = i-1; - - if (oopsend <= i) - { - VERB3 log("End of oops at line %d (%d): '%s'", oopsend, i, lines_info[oopsend].ptr); - if (record_oops(oopses, lines_info, oopsstart, oopsend)) - oopsesfound++; - oopsstart = -1; - inbacktrace = 0; - } - } - - prevlevel = lines_info[i].level; - i++; - - if (oopsstart >= 0) - { - /* Do we have a suspiciously long oops? Cancel it */ - if (i-oopsstart > 60) - { - inbacktrace = 0; - oopsstart = -1; - VERB3 log("Dropped oops, too long"); - continue; - } - if (!inbacktrace && i-oopsstart > 40) - { - /*inbacktrace = 0; - already is */ - oopsstart = -1; - VERB3 log("Dropped oops, too long"); - continue; - } - } - } /* while (i < linecount) */ - - /* process last oops if we have one */ - if (oopsstart >= 0 && inbacktrace) - { - int oopsend = i-1; - VERB3 log("End of oops at line %d (end of file): '%s'", oopsend, lines_info[oopsend].ptr); - if (record_oops(oopses, lines_info, oopsstart, oopsend)) - oopsesfound++; - } - - free(lines_info); - return oopsesfound; -} diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am index 52f3e4d1..eee328e0 100644 --- a/src/plugins/Makefile.am +++ b/src/plugins/Makefile.am @@ -57,6 +57,7 @@ libCCpp_la_CPPFLAGS = \ -DDEBUG_DUMPS_DIR=\"$(DEBUG_DUMPS_DIR)\" \ -DLOCALSTATEDIR='"$(localstatedir)"' \ $(GLIB_CFLAGS) \ + -D_GNU_SOURCE \ -Wall -Werror # -DHOSTILE_KERNEL libCCpp_la_LDFLAGS = \ @@ -65,12 +66,14 @@ libCCpp_la_LDFLAGS = \ # KerneloopsScanner libKerneloopsScanner_la_SOURCES = \ KerneloopsScanner.cpp KerneloopsScanner.h \ - KerneloopsSysLog.cpp KerneloopsSysLog.h + KerneloopsSysLog.c KerneloopsSysLog.h libKerneloopsScanner_la_CPPFLAGS = \ -I$(srcdir)/../include/report -I$(srcdir)/../include \ -I$(srcdir)/../lib \ -DDEBUG_DUMPS_DIR=\"$(DEBUG_DUMPS_DIR)\" \ - $(GLIB_CFLAGS) + $(GLIB_CFLAGS) \ + -D_GNU_SOURCE \ + -Wall -Werror libKerneloopsScanner_la_LDFLAGS = \ -avoid-version \ $(GLIB_LIBS) @@ -187,7 +190,7 @@ abrt_action_bugzilla_LDADD = \ abrt_action_rhtsupport_SOURCES = \ abrt_rh_support.h abrt_rh_support.c \ - abrt-action-rhtsupport.cpp + abrt-action-rhtsupport.c abrt_action_rhtsupport_CPPFLAGS = \ -I$(srcdir)/../include/report -I$(srcdir)/../include \ -I$(srcdir)/../lib \ @@ -211,7 +214,7 @@ abrt_action_rhtsupport_LDADD = \ ../lib/libreport.la abrt_action_upload_SOURCES = \ - abrt-action-upload.cpp + abrt-action-upload.c abrt_action_upload_CPPFLAGS = \ -I$(srcdir)/../include/report -I$(srcdir)/../include \ -I$(srcdir)/../lib \ @@ -234,7 +237,7 @@ abrt_action_upload_LDADD = \ ../lib/libreport.la abrt_action_kerneloops_SOURCES = \ - abrt-action-kerneloops.cpp + abrt-action-kerneloops.c abrt_action_kerneloops_CPPFLAGS = \ -I$(srcdir)/../include/report -I$(srcdir)/../include \ -I$(srcdir)/../lib \ @@ -254,7 +257,7 @@ abrt_action_kerneloops_LDADD = \ ../lib/libreport.la abrt_action_mailx_SOURCES = \ - abrt-action-mailx.cpp + abrt-action-mailx.c abrt_action_mailx_CPPFLAGS = \ -I$(srcdir)/../include/report -I$(srcdir)/../include \ -I$(srcdir)/../lib \ @@ -273,7 +276,7 @@ abrt_action_mailx_LDADD = \ ../lib/libreport.la abrt_action_print_SOURCES = \ - abrt-action-print.cpp + abrt-action-print.c abrt_action_print_CPPFLAGS = \ -I$(srcdir)/../include/report -I$(srcdir)/../include \ -I$(srcdir)/../lib \ diff --git a/src/plugins/abrt-action-kerneloops.c b/src/plugins/abrt-action-kerneloops.c new file mode 100644 index 00000000..f3351ccd --- /dev/null +++ b/src/plugins/abrt-action-kerneloops.c @@ -0,0 +1,183 @@ +/* + Copyright (C) 2010 ABRT team + Copyright (C) 2010 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. + + Authors: + Anton Arapov + Arjan van de Ven + */ + +#include +#include "abrtlib.h" +#include "abrt_crash_dump.h" + +#define PROGNAME "abrt-action-kerneloops" + +/* helpers */ +static size_t writefunction(void *ptr, size_t size, size_t nmemb, void *stream) +{ + size *= nmemb; +/* + char *c, *c1, *c2; + + log("received: '%*.*s'\n", (int)size, (int)size, (char*)ptr); + c = (char*)xzalloc(size + 1); + memcpy(c, ptr, size); + c1 = strstr(c, "201 "); + if (c1) + { + c1 += 4; + c2 = strchr(c1, '\n'); + if (c2) + *c2 = 0; + } + free(c); +*/ + + return size; +} + +/* Send oops data to kerneloops.org-style site, using HTTP POST */ +/* Returns 0 on success */ +static CURLcode http_post_to_kerneloops_site(const char *url, const char *oopsdata) +{ + CURLcode ret; + CURL *handle; + struct curl_httppost *post = NULL; + struct curl_httppost *last = NULL; + + handle = curl_easy_init(); + if (!handle) + error_msg_and_die("Can't create curl handle"); + + curl_easy_setopt(handle, CURLOPT_URL, url); + + curl_formadd(&post, &last, + CURLFORM_COPYNAME, "oopsdata", + CURLFORM_COPYCONTENTS, oopsdata, + CURLFORM_END); + curl_formadd(&post, &last, + CURLFORM_COPYNAME, "pass_on_allowed", + CURLFORM_COPYCONTENTS, "yes", + CURLFORM_END); + + curl_easy_setopt(handle, CURLOPT_HTTPPOST, post); + curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, writefunction); + + ret = curl_easy_perform(handle); + + curl_formfree(post); + curl_easy_cleanup(handle); + + return ret; +} + +static void report_to_kerneloops( + const char *dump_dir_name, + map_string_h *settings) +{ + struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0); + if (!dd) + exit(1); /* error msg is already logged */ + + crash_data_t *crash_data = load_crash_data_from_crash_dump_dir(dd); + dd_close(dd); + + const char *backtrace = get_crash_item_content_or_NULL(crash_data, FILENAME_BACKTRACE); + if (!backtrace) + error_msg_and_die("Error sending kernel oops due to missing backtrace"); + + const char *env = getenv("KerneloopsReporter_SubmitURL"); + const char *submitURL = (env ? env : get_map_string_item_or_empty(settings, "SubmitURL")); + if (!submitURL[0]) + submitURL = "http://submit.kerneloops.org/submitoops.php"; + + log(_("Submitting oops report to %s"), submitURL); + + CURLcode ret = http_post_to_kerneloops_site(submitURL, backtrace); + if (ret != CURLE_OK) + error_msg_and_die("Kernel oops has not been sent due to %s", curl_easy_strerror(ret)); + + free_crash_data(crash_data); + + /* Server replies with: + * 200 thank you for submitting the kernel oops information + * RemoteIP: 34192fd15e34bf60fac6a5f01bba04ddbd3f0558 + * - no URL or bug ID apparently... + */ + log("Kernel oops report was uploaded"); +} + +int main(int argc, char **argv) +{ + char *env_verbose = getenv("ABRT_VERBOSE"); + if (env_verbose) + g_verbose = atoi(env_verbose); + + map_string_h *settings = new_map_string(); + const char *dump_dir_name = "."; + enum { + OPT_s = (1 << 0), + }; + int optflags = 0; + int opt; + while ((opt = getopt(argc, argv, "c:d:vs")) != -1) + { + switch (opt) + { + case 'c': + VERB1 log("Loading settings from '%s'", optarg); + load_conf_file(optarg, settings, /*skip key w/o values:*/ true); + VERB3 log("Loaded '%s'", optarg); + break; + case 'd': + dump_dir_name = optarg; + break; + case 'v': + g_verbose++; + break; + case 's': + optflags |= OPT_s; + break; + default: + /* Careful: the string below contains tabs, dont replace with spaces */ + error_msg_and_die( + "Usage: "PROGNAME" -c CONFFILE -d DIR [-vs]" + "\n" + "\nReport a kernel oops to kerneloops.org (or similar) site" + "\n" + "\nOptions:" + "\n -c FILE Configuration file (may be given many times)" + "\n -d DIR Crash dump directory" + "\n -v Verbose" + "\n -s Log to syslog" + ); + } + } + + putenv(xasprintf("ABRT_VERBOSE=%u", g_verbose)); + +//DONT! our stdout/stderr goes directly to daemon, don't want to have prefix there. +// msg_prefix = xasprintf(PROGNAME"[%u]", getpid()); + + if (optflags & OPT_s) + { + openlog(msg_prefix, 0, LOG_DAEMON); + logmode = LOGMODE_SYSLOG; + } + + report_to_kerneloops(dump_dir_name, settings); + + free_map_string(settings); + return 0; +} diff --git a/src/plugins/abrt-action-kerneloops.cpp b/src/plugins/abrt-action-kerneloops.cpp deleted file mode 100644 index f3351ccd..00000000 --- a/src/plugins/abrt-action-kerneloops.cpp +++ /dev/null @@ -1,183 +0,0 @@ -/* - Copyright (C) 2010 ABRT team - Copyright (C) 2010 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. - - Authors: - Anton Arapov - Arjan van de Ven - */ - -#include -#include "abrtlib.h" -#include "abrt_crash_dump.h" - -#define PROGNAME "abrt-action-kerneloops" - -/* helpers */ -static size_t writefunction(void *ptr, size_t size, size_t nmemb, void *stream) -{ - size *= nmemb; -/* - char *c, *c1, *c2; - - log("received: '%*.*s'\n", (int)size, (int)size, (char*)ptr); - c = (char*)xzalloc(size + 1); - memcpy(c, ptr, size); - c1 = strstr(c, "201 "); - if (c1) - { - c1 += 4; - c2 = strchr(c1, '\n'); - if (c2) - *c2 = 0; - } - free(c); -*/ - - return size; -} - -/* Send oops data to kerneloops.org-style site, using HTTP POST */ -/* Returns 0 on success */ -static CURLcode http_post_to_kerneloops_site(const char *url, const char *oopsdata) -{ - CURLcode ret; - CURL *handle; - struct curl_httppost *post = NULL; - struct curl_httppost *last = NULL; - - handle = curl_easy_init(); - if (!handle) - error_msg_and_die("Can't create curl handle"); - - curl_easy_setopt(handle, CURLOPT_URL, url); - - curl_formadd(&post, &last, - CURLFORM_COPYNAME, "oopsdata", - CURLFORM_COPYCONTENTS, oopsdata, - CURLFORM_END); - curl_formadd(&post, &last, - CURLFORM_COPYNAME, "pass_on_allowed", - CURLFORM_COPYCONTENTS, "yes", - CURLFORM_END); - - curl_easy_setopt(handle, CURLOPT_HTTPPOST, post); - curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, writefunction); - - ret = curl_easy_perform(handle); - - curl_formfree(post); - curl_easy_cleanup(handle); - - return ret; -} - -static void report_to_kerneloops( - const char *dump_dir_name, - map_string_h *settings) -{ - struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0); - if (!dd) - exit(1); /* error msg is already logged */ - - crash_data_t *crash_data = load_crash_data_from_crash_dump_dir(dd); - dd_close(dd); - - const char *backtrace = get_crash_item_content_or_NULL(crash_data, FILENAME_BACKTRACE); - if (!backtrace) - error_msg_and_die("Error sending kernel oops due to missing backtrace"); - - const char *env = getenv("KerneloopsReporter_SubmitURL"); - const char *submitURL = (env ? env : get_map_string_item_or_empty(settings, "SubmitURL")); - if (!submitURL[0]) - submitURL = "http://submit.kerneloops.org/submitoops.php"; - - log(_("Submitting oops report to %s"), submitURL); - - CURLcode ret = http_post_to_kerneloops_site(submitURL, backtrace); - if (ret != CURLE_OK) - error_msg_and_die("Kernel oops has not been sent due to %s", curl_easy_strerror(ret)); - - free_crash_data(crash_data); - - /* Server replies with: - * 200 thank you for submitting the kernel oops information - * RemoteIP: 34192fd15e34bf60fac6a5f01bba04ddbd3f0558 - * - no URL or bug ID apparently... - */ - log("Kernel oops report was uploaded"); -} - -int main(int argc, char **argv) -{ - char *env_verbose = getenv("ABRT_VERBOSE"); - if (env_verbose) - g_verbose = atoi(env_verbose); - - map_string_h *settings = new_map_string(); - const char *dump_dir_name = "."; - enum { - OPT_s = (1 << 0), - }; - int optflags = 0; - int opt; - while ((opt = getopt(argc, argv, "c:d:vs")) != -1) - { - switch (opt) - { - case 'c': - VERB1 log("Loading settings from '%s'", optarg); - load_conf_file(optarg, settings, /*skip key w/o values:*/ true); - VERB3 log("Loaded '%s'", optarg); - break; - case 'd': - dump_dir_name = optarg; - break; - case 'v': - g_verbose++; - break; - case 's': - optflags |= OPT_s; - break; - default: - /* Careful: the string below contains tabs, dont replace with spaces */ - error_msg_and_die( - "Usage: "PROGNAME" -c CONFFILE -d DIR [-vs]" - "\n" - "\nReport a kernel oops to kerneloops.org (or similar) site" - "\n" - "\nOptions:" - "\n -c FILE Configuration file (may be given many times)" - "\n -d DIR Crash dump directory" - "\n -v Verbose" - "\n -s Log to syslog" - ); - } - } - - putenv(xasprintf("ABRT_VERBOSE=%u", g_verbose)); - -//DONT! our stdout/stderr goes directly to daemon, don't want to have prefix there. -// msg_prefix = xasprintf(PROGNAME"[%u]", getpid()); - - if (optflags & OPT_s) - { - openlog(msg_prefix, 0, LOG_DAEMON); - logmode = LOGMODE_SYSLOG; - } - - report_to_kerneloops(dump_dir_name, settings); - - free_map_string(settings); - return 0; -} diff --git a/src/plugins/abrt-action-mailx.c b/src/plugins/abrt-action-mailx.c new file mode 100644 index 00000000..ea26b9cb --- /dev/null +++ b/src/plugins/abrt-action-mailx.c @@ -0,0 +1,172 @@ +/* + Mailx.cpp + + Copyright (C) 2009 Zdenek Prikryl (zprikryl@redhat.com) + 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" +#include "parse_options.h" +#include "abrt_crash_dump.h" + +#define PROGNAME "abrt-action-mailx" + +static void exec_and_feed_input(uid_t uid, const char* text, char **args) +{ + int pipein[2]; + + pid_t child = fork_execv_on_steroids( + EXECFLG_INPUT | EXECFLG_QUIET | EXECFLG_SETGUID, + args, + pipein, + /*unsetenv_vec:*/ NULL, + /*dir:*/ NULL, + uid); + + full_write_str(pipein[1], text); + close(pipein[1]); + + int status; + waitpid(child, &status, 0); /* wait for command completion */ + if (status != 0) + error_msg_and_die("Error running '%s'", args[0]); +} + +static char** append_str_to_vector(char **vec, unsigned *size_p, const char *str) +{ + //log("old vec: %p", vec); + unsigned size = *size_p; + vec = (char**) xrealloc(vec, (size+2) * sizeof(vec[0])); + vec[size] = xstrdup(str); + //log("new vec: %p, added [%d] %p", vec, size, vec[size]); + size++; + vec[size] = NULL; + *size_p = size; + return vec; +} + +static void create_and_send_email( + const char *dump_dir_name, + map_string_h *settings) +{ + struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0); + if (!dd) + exit(1); /* error msg is already logged by dd_opendir */ + + crash_data_t *crash_data = load_crash_data_from_crash_dump_dir(dd); + dd_close(dd); + + char* env; + env = getenv("Mailx_Subject"); + const char *subject = (env ? env : get_map_string_item_or_NULL(settings, "Subject") ? : "[abrt] full crash report"); + env = getenv("Mailx_EmailFrom"); + const char *email_from = (env ? env : get_map_string_item_or_NULL(settings, "EmailFrom") ? : "user@localhost"); + env = getenv("Mailx_EmailTo"); + const char *email_to = (env ? env : get_map_string_item_or_NULL(settings, "EmailTo") ? : "root@localhost"); + env = getenv("Mailx_SendBinaryData"); + bool send_binary_data = string_to_bool(env ? env : get_map_string_item_or_empty(settings, "SendBinaryData")); + + char **args = NULL; + unsigned arg_size = 0; + args = append_str_to_vector(args, &arg_size, "/bin/mailx"); + + char *dsc = make_description_mailx(crash_data); + + if (send_binary_data) + { + GHashTableIter iter; + char *name; + struct crash_item *value; + g_hash_table_iter_init(&iter, crash_data); + while (g_hash_table_iter_next(&iter, (void**)&name, (void**)&value)) + { + if (value->flags & CD_FLAG_BIN) + { + args = append_str_to_vector(args, &arg_size, "-a"); + args = append_str_to_vector(args, &arg_size, value->content); + } + } + } + + args = append_str_to_vector(args, &arg_size, "-s"); + args = append_str_to_vector(args, &arg_size, subject); + args = append_str_to_vector(args, &arg_size, "-r"); + args = append_str_to_vector(args, &arg_size, email_from); + args = append_str_to_vector(args, &arg_size, email_to); + + log(_("Sending an email...")); + const char *uid_str = get_crash_item_content_or_NULL(crash_data, FILENAME_UID); + exec_and_feed_input(xatoi_positive(uid_str), dsc, args); + + free(dsc); + + while (*args) + free(*args++); + args -= arg_size; + free(args); + + free_crash_data(crash_data); + + log("Email was sent to: %s", email_to); +} + +int main(int argc, char **argv) +{ + char *env_verbose = getenv("ABRT_VERBOSE"); + if (env_verbose) + g_verbose = atoi(env_verbose); + + const char *dump_dir_name = "."; + const char *conf_file = NULL; + + const char *program_usage = _( + PROGNAME" [-v] -d DIR [-c CONFFILE]\n" + "\n" + "Upload compressed tarball of crash dump" + ); + enum { + OPT_v = 1 << 0, + OPT_d = 1 << 1, + OPT_c = 1 << 2, + }; + /* 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" , _("Crash dump directory")), + OPT_STRING('c', NULL, &conf_file , "CONFFILE", _("Config file")), + OPT_END() + }; + + /*unsigned opts =*/ parse_opts(argc, argv, program_options, program_usage); + + putenv(xasprintf("ABRT_VERBOSE=%u", g_verbose)); + //msg_prefix = PROGNAME; + //if (optflags & OPT_s) + //{ + // openlog(msg_prefix, 0, LOG_DAEMON); + // logmode = LOGMODE_SYSLOG; + //} + + map_string_h *settings = new_map_string(); + if (conf_file) + load_conf_file(conf_file, settings, /*skip key w/o values:*/ true); + + create_and_send_email(dump_dir_name, settings); + + free_map_string(settings); + return 0; +} diff --git a/src/plugins/abrt-action-mailx.cpp b/src/plugins/abrt-action-mailx.cpp deleted file mode 100644 index 8f613047..00000000 --- a/src/plugins/abrt-action-mailx.cpp +++ /dev/null @@ -1,170 +0,0 @@ -/* - Mailx.cpp - - Copyright (C) 2009 Zdenek Prikryl (zprikryl@redhat.com) - 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" -#include "parse_options.h" -#include "abrt_crash_dump.h" - -#define PROGNAME "abrt-action-mailx" - -static void exec_and_feed_input(uid_t uid, const char* text, char **args) -{ - int pipein[2]; - - pid_t child = fork_execv_on_steroids( - EXECFLG_INPUT | EXECFLG_QUIET | EXECFLG_SETGUID, - args, - pipein, - /*unsetenv_vec:*/ NULL, - /*dir:*/ NULL, - uid); - - full_write_str(pipein[1], text); - close(pipein[1]); - - int status; - waitpid(child, &status, 0); /* wait for command completion */ - if (status != 0) - error_msg_and_die("Error running '%s'", args[0]); -} - -static char** append_str_to_vector(char **vec, unsigned &size, const char *str) -{ - //log("old vec: %p", vec); - vec = (char**) xrealloc(vec, (size+2) * sizeof(vec[0])); - vec[size] = xstrdup(str); - //log("new vec: %p, added [%d] %p", vec, size, vec[size]); - size++; - vec[size] = NULL; - return vec; -} - -static void create_and_send_email( - const char *dump_dir_name, - map_string_h *settings) -{ - struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0); - if (!dd) - exit(1); /* error msg is already logged by dd_opendir */ - - crash_data_t *crash_data = load_crash_data_from_crash_dump_dir(dd); - dd_close(dd); - - char* env; - env = getenv("Mailx_Subject"); - const char *subject = (env ? env : get_map_string_item_or_NULL(settings, "Subject") ? : "[abrt] full crash report"); - env = getenv("Mailx_EmailFrom"); - const char *email_from = (env ? env : get_map_string_item_or_NULL(settings, "EmailFrom") ? : "user@localhost"); - env = getenv("Mailx_EmailTo"); - const char *email_to = (env ? env : get_map_string_item_or_NULL(settings, "EmailTo") ? : "root@localhost"); - env = getenv("Mailx_SendBinaryData"); - bool send_binary_data = string_to_bool(env ? env : get_map_string_item_or_empty(settings, "SendBinaryData")); - - char **args = NULL; - unsigned arg_size = 0; - args = append_str_to_vector(args, arg_size, "/bin/mailx"); - - char *dsc = make_description_mailx(crash_data); - - if (send_binary_data) - { - GHashTableIter iter; - char *name; - struct crash_item *value; - g_hash_table_iter_init(&iter, crash_data); - while (g_hash_table_iter_next(&iter, (void**)&name, (void**)&value)) - { - if (value->flags & CD_FLAG_BIN) - { - args = append_str_to_vector(args, arg_size, "-a"); - args = append_str_to_vector(args, arg_size, value->content); - } - } - } - - args = append_str_to_vector(args, arg_size, "-s"); - args = append_str_to_vector(args, arg_size, subject); - args = append_str_to_vector(args, arg_size, "-r"); - args = append_str_to_vector(args, arg_size, email_from); - args = append_str_to_vector(args, arg_size, email_to); - - log(_("Sending an email...")); - const char *uid_str = get_crash_item_content_or_NULL(crash_data, FILENAME_UID); - exec_and_feed_input(xatoi_positive(uid_str), dsc, args); - - free(dsc); - - while (*args) - free(*args++); - args -= arg_size; - free(args); - - free_crash_data(crash_data); - - log("Email was sent to: %s", email_to); -} - -int main(int argc, char **argv) -{ - char *env_verbose = getenv("ABRT_VERBOSE"); - if (env_verbose) - g_verbose = atoi(env_verbose); - - const char *dump_dir_name = "."; - const char *conf_file = NULL; - - const char *program_usage = _( - PROGNAME" [-v] -d DIR [-c CONFFILE]\n" - "\n" - "Upload compressed tarball of crash dump" - ); - enum { - OPT_v = 1 << 0, - OPT_d = 1 << 1, - OPT_c = 1 << 2, - }; - /* 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" , _("Crash dump directory")), - OPT_STRING('c', NULL, &conf_file , "CONFFILE", _("Config file")), - OPT_END() - }; - - /*unsigned opts =*/ parse_opts(argc, argv, program_options, program_usage); - - putenv(xasprintf("ABRT_VERBOSE=%u", g_verbose)); - //msg_prefix = PROGNAME; - //if (optflags & OPT_s) - //{ - // openlog(msg_prefix, 0, LOG_DAEMON); - // logmode = LOGMODE_SYSLOG; - //} - - map_string_h *settings = new_map_string(); - if (conf_file) - load_conf_file(conf_file, settings, /*skip key w/o values:*/ true); - - create_and_send_email(dump_dir_name, settings); - - free_map_string(settings); - return 0; -} diff --git a/src/plugins/abrt-action-print.c b/src/plugins/abrt-action-print.c new file mode 100644 index 00000000..55631c96 --- /dev/null +++ b/src/plugins/abrt-action-print.c @@ -0,0 +1,96 @@ +/* + Write crash dump to stdout in text form. + + Copyright (C) 2009 Zdenek Prikryl (zprikryl@redhat.com) + 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" +#include "parse_options.h" +#include "abrt_crash_dump.h" + +#define PROGNAME "abrt-action-print" + +static const char *dump_dir_name = "."; +static const char *output_file = NULL; +static const char *open_mode = "w"; + +int main(int argc, char **argv) +{ + char *env_verbose = getenv("ABRT_VERBOSE"); + if (env_verbose) + g_verbose = atoi(env_verbose); + + const char *program_usage = _( + PROGNAME" [-v] [-o FILE] -d DIR\n" + "\n" + "Print information about the crash to standard output"); + enum { + OPT_v = 1 << 0, + OPT_d = 1 << 1, + OPT_o = 1 << 2, + }; + /* 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" , _("Crash dump directory")), + OPT_STRING('o', NULL, &output_file , "FILE", _("Output file")), + OPT_END() + }; + + /*unsigned opts =*/ parse_opts(argc, argv, program_options, program_usage); + + putenv(xasprintf("ABRT_VERBOSE=%u", g_verbose)); + //msg_prefix = PROGNAME; + + char *env = getenv("Logger_LogPath"); + VERB3 log("output_file:'%s' Logger_LogPath env:'%s'", output_file, env); + if (env) + output_file = env; + + env = getenv("Logger_AppendLogs"); + VERB3 log("Logger_AppendLogs env:'%s'", env); + if (env && string_to_bool(env)) + open_mode = "a"; + + if (output_file) + { + if (!freopen(output_file, open_mode, stdout)) + { + perror_msg_and_die("Can't open '%s'", output_file); + } + } + + struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0); + if (!dd) + return 1; /* error message is already logged */ + + crash_data_t *crash_data = load_crash_data_from_crash_dump_dir(dd); + dd_close(dd); + + char *dsc = make_description_logger(crash_data); + fputs(dsc, stdout); + free(dsc); + free_crash_data(crash_data); + + if (output_file) + { + const char *format = (open_mode[0] == 'a' ? _("The report was appended to %s") : _("The report was stored to %s")); + log(format, output_file); + } + + return 0; +} diff --git a/src/plugins/abrt-action-print.cpp b/src/plugins/abrt-action-print.cpp deleted file mode 100644 index 55631c96..00000000 --- a/src/plugins/abrt-action-print.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* - Write crash dump to stdout in text form. - - Copyright (C) 2009 Zdenek Prikryl (zprikryl@redhat.com) - 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" -#include "parse_options.h" -#include "abrt_crash_dump.h" - -#define PROGNAME "abrt-action-print" - -static const char *dump_dir_name = "."; -static const char *output_file = NULL; -static const char *open_mode = "w"; - -int main(int argc, char **argv) -{ - char *env_verbose = getenv("ABRT_VERBOSE"); - if (env_verbose) - g_verbose = atoi(env_verbose); - - const char *program_usage = _( - PROGNAME" [-v] [-o FILE] -d DIR\n" - "\n" - "Print information about the crash to standard output"); - enum { - OPT_v = 1 << 0, - OPT_d = 1 << 1, - OPT_o = 1 << 2, - }; - /* 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" , _("Crash dump directory")), - OPT_STRING('o', NULL, &output_file , "FILE", _("Output file")), - OPT_END() - }; - - /*unsigned opts =*/ parse_opts(argc, argv, program_options, program_usage); - - putenv(xasprintf("ABRT_VERBOSE=%u", g_verbose)); - //msg_prefix = PROGNAME; - - char *env = getenv("Logger_LogPath"); - VERB3 log("output_file:'%s' Logger_LogPath env:'%s'", output_file, env); - if (env) - output_file = env; - - env = getenv("Logger_AppendLogs"); - VERB3 log("Logger_AppendLogs env:'%s'", env); - if (env && string_to_bool(env)) - open_mode = "a"; - - if (output_file) - { - if (!freopen(output_file, open_mode, stdout)) - { - perror_msg_and_die("Can't open '%s'", output_file); - } - } - - struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0); - if (!dd) - return 1; /* error message is already logged */ - - crash_data_t *crash_data = load_crash_data_from_crash_dump_dir(dd); - dd_close(dd); - - char *dsc = make_description_logger(crash_data); - fputs(dsc, stdout); - free(dsc); - free_crash_data(crash_data); - - if (output_file) - { - const char *format = (open_mode[0] == 'a' ? _("The report was appended to %s") : _("The report was stored to %s")); - log(format, output_file); - } - - return 0; -} diff --git a/src/plugins/abrt-action-rhtsupport.c b/src/plugins/abrt-action-rhtsupport.c new file mode 100644 index 00000000..024b1efc --- /dev/null +++ b/src/plugins/abrt-action-rhtsupport.c @@ -0,0 +1,321 @@ +/* + Copyright (C) 2010 ABRT team + Copyright (C) 2010 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 +#include "abrtlib.h" +#include "abrt_curl.h" +#include "abrt_xmlrpc.h" +#include "abrt_rh_support.h" +#include "abrt_crash_dump.h" + +#define PROGNAME "abrt-action-rhtsupport" + +static void report_to_rhtsupport( + const char *dump_dir_name, + map_string_h *settings) +{ + struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0); + if (!dd) + exit(1); /* error msg is already logged by dd_opendir */ + + crash_data_t *crash_data = load_crash_data_from_crash_dump_dir(dd); + dd_close(dd); + + /* Gzipping e.g. 0.5gig coredump takes a while. Let client know what we are doing */ + log(_("Compressing data")); + + const char* errmsg = NULL; + TAR* tar = NULL; + pid_t child; + char* tempfile = NULL; + reportfile_t* file = NULL; + char* dsc = NULL; + char* summary = NULL; + const char* function; + 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]) + { + errmsg = _("Empty login or password, please check RHTSupport.conf"); + goto ret; + } + + package = get_crash_item_content_or_NULL(crash_data, FILENAME_PACKAGE); + reason = get_crash_item_content_or_NULL(crash_data, FILENAME_REASON); + function = get_crash_item_content_or_NULL(crash_data, FILENAME_CRASH_FUNCTION); + + { + struct strbuf *buf_summary = strbuf_new(); + strbuf_append_strf(buf_summary, "[abrt] %s", package); + if (function && strlen(function) < 30) + strbuf_append_strf(buf_summary, ": %s", function); + if (reason) + strbuf_append_strf(buf_summary, ": %s", reason); + summary = strbuf_free_nobuf(buf_summary); + + char *bz_dsc = make_description_bz(crash_data); + dsc = xasprintf("abrt version: "VERSION"\n%s", bz_dsc); + free(bz_dsc); + } + + file = new_reportfile(); + + /* SELinux guys are not happy with /tmp, using /var/run/abrt */ + tempfile = xasprintf(LOCALSTATEDIR"/run/abrt/tmp-%lu-%lu.tar.gz", (long)getpid(), (long)time(NULL)); + + int pipe_from_parent_to_child[2]; + xpipe(pipe_from_parent_to_child); + child = fork(); + if (child == 0) + { + /* child */ + close(pipe_from_parent_to_child[1]); + xmove_fd(xopen3(tempfile, O_WRONLY | O_CREAT | O_EXCL, 0600), 1); + xmove_fd(pipe_from_parent_to_child[0], 0); + execlp("gzip", "gzip", NULL); + perror_msg_and_die("can't execute '%s'", "gzip"); + } + close(pipe_from_parent_to_child[0]); + + if (tar_fdopen(&tar, pipe_from_parent_to_child[1], tempfile, + /*fileops:(standard)*/ NULL, O_WRONLY | O_CREAT, 0644, TAR_GNU) != 0) + { + errmsg = "can't create temporary file in "LOCALSTATEDIR"/run/abrt"; + goto ret; + } + + { + GHashTableIter iter; + char *name; + struct crash_item *value; + g_hash_table_iter_init(&iter, crash_data); + while (g_hash_table_iter_next(&iter, (void**)&name, (void**)&value)) + { + if (strcmp(name, FILENAME_COUNT) == 0) continue; + if (strcmp(name, CD_DUMPDIR) == 0) continue; + if (strcmp(name, FILENAME_INFORMALL) == 0) continue; + if (strcmp(name, FILENAME_MESSAGE) == 0) continue; // plugin's status message (if we already reported it yesterday) + if (strcmp(name, FILENAME_DESCRIPTION) == 0) continue; // package description + + const char *content = value->content; + if (value->flags & CD_FLAG_TXT) + { + reportfile_add_binding_from_string(file, name, content); + } + else if (value->flags & CD_FLAG_BIN) + { + const char *basename = strrchr(content, '/'); + if (basename) + basename++; + else + basename = content; + char *xml_name = concat_path_file("content", basename); + reportfile_add_binding_from_namedfile(file, + /*on_disk_filename */ content, + /*binding_name */ name, + /*recorded_filename*/ xml_name, + /*binary */ 1); + if (tar_append_file(tar, (char*)content, xml_name) != 0) + { + errmsg = "can't create temporary file in "LOCALSTATEDIR"/run/abrt"; + free(xml_name); + goto ret; + } + free(xml_name); + } + } + } + + /* Write out content.xml in the tarball's root */ + { + const char *signature = reportfile_as_string(file); + unsigned len = strlen(signature); + unsigned len512 = (len + 511) & ~511; + char *block = (char*)memcpy(xzalloc(len512), signature, len); + th_set_type(tar, S_IFREG | 0644); + th_set_mode(tar, S_IFREG | 0644); + //th_set_link(tar, char *linkname); + //th_set_device(tar, dev_t device); + //th_set_user(tar, uid_t uid); + //th_set_group(tar, gid_t gid); + //th_set_mtime(tar, time_t fmtime); + th_set_path(tar, (char*)"content.xml"); + th_set_size(tar, len); + th_finish(tar); /* caclulate and store th xsum etc */ + if (th_write(tar) != 0 + || full_write(tar_fd(tar), block, len512) != len512 + || tar_close(tar) != 0 + ) { + free(block); + errmsg = "can't create temporary file in "LOCALSTATEDIR"/run/abrt"; + goto ret; + } + tar = NULL; + free(block); + } + + { + log(_("Creating a new case...")); + char* result = send_report_to_new_case(url, + login, + password, + ssl_verify, + summary, + dsc, + package, + tempfile + ); + /* Temporary hackish detection of errors. Ideally, + * send_report_to_new_case needs to have better error reporting. + */ + if (strncasecmp(result, "error", 5) == 0) + { + /* + * result can contain "...server says: 'multi-line text'" + * Replace all '\n' with spaces: + * we want this message to be, logically, one log entry. + * IOW: one line, not many lines. + */ + char *src, *dst; + dst = src = result; + while (1) + { + unsigned char c = *src++; + if (c == '\n') + c = ' '; + *dst++ = c; + if (c == '\0') + break; + } + /* Use sanitized string as error message */ + error_msg_and_die("%s", result); + } + /* No error */ + log("%s", result); + free(result); + } + + ret: + // Damn, selinux does not allow SIGKILLing our own child! wtf?? + //kill(child, SIGKILL); /* just in case */ + waitpid(child, NULL, 0); + if (tar) + tar_close(tar); + //close(pipe_from_parent_to_child[1]); - tar_close() does it itself + unlink(tempfile); + free(tempfile); + reportfile_free(file); + + free(summary); + free(dsc); + + free(url); + free(login); + free(password); + free_crash_data(crash_data); + + if (errmsg) + error_msg_and_die("%s", errmsg); +} + +int main(int argc, char **argv) +{ + char *env_verbose = getenv("ABRT_VERBOSE"); + if (env_verbose) + g_verbose = atoi(env_verbose); + + map_string_h *settings = new_map_string(); + const char *dump_dir_name = "."; + enum { + OPT_s = (1 << 0), + }; + int optflags = 0; + int opt; + while ((opt = getopt(argc, argv, "c:d:vs")) != -1) + { + switch (opt) + { + case 'c': + VERB1 log("Loading settings from '%s'", optarg); + load_conf_file(optarg, settings, /*skip key w/o values:*/ true); + VERB3 log("Loaded '%s'", optarg); + break; + case 'd': + dump_dir_name = optarg; + break; + case 'v': + g_verbose++; + break; + case 's': + optflags |= OPT_s; + break; + default: + /* Careful: the string below contains tabs, dont replace with spaces */ + error_msg_and_die( + "Usage: "PROGNAME" -c CONFFILE -d DIR [-vs]" + "\n" + "\nReport a crash to RHTSupport" + "\n" + "\nOptions:" + "\n -c FILE Configuration file (may be given many times)" + "\n -d DIR Crash dump directory" + "\n -v Verbose" + "\n -s Log to syslog" + ); + } + } + + putenv(xasprintf("ABRT_VERBOSE=%u", g_verbose)); + +//DONT! our stdout/stderr goes directly to daemon, don't want to have prefix there. +// msg_prefix = xasprintf(PROGNAME"[%u]", getpid()); + + if (optflags & OPT_s) + { + openlog(msg_prefix, 0, LOG_DAEMON); + logmode = LOGMODE_SYSLOG; + } + + VERB1 log("Initializing XML-RPC library"); + xmlrpc_env env; + xmlrpc_env_init(&env); + xmlrpc_client_setup_global_const(&env); + if (env.fault_occurred) + 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); + + free_map_string(settings); + return 0; +} diff --git a/src/plugins/abrt-action-rhtsupport.cpp b/src/plugins/abrt-action-rhtsupport.cpp deleted file mode 100644 index 024b1efc..00000000 --- a/src/plugins/abrt-action-rhtsupport.cpp +++ /dev/null @@ -1,321 +0,0 @@ -/* - Copyright (C) 2010 ABRT team - Copyright (C) 2010 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 -#include "abrtlib.h" -#include "abrt_curl.h" -#include "abrt_xmlrpc.h" -#include "abrt_rh_support.h" -#include "abrt_crash_dump.h" - -#define PROGNAME "abrt-action-rhtsupport" - -static void report_to_rhtsupport( - const char *dump_dir_name, - map_string_h *settings) -{ - struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0); - if (!dd) - exit(1); /* error msg is already logged by dd_opendir */ - - crash_data_t *crash_data = load_crash_data_from_crash_dump_dir(dd); - dd_close(dd); - - /* Gzipping e.g. 0.5gig coredump takes a while. Let client know what we are doing */ - log(_("Compressing data")); - - const char* errmsg = NULL; - TAR* tar = NULL; - pid_t child; - char* tempfile = NULL; - reportfile_t* file = NULL; - char* dsc = NULL; - char* summary = NULL; - const char* function; - 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]) - { - errmsg = _("Empty login or password, please check RHTSupport.conf"); - goto ret; - } - - package = get_crash_item_content_or_NULL(crash_data, FILENAME_PACKAGE); - reason = get_crash_item_content_or_NULL(crash_data, FILENAME_REASON); - function = get_crash_item_content_or_NULL(crash_data, FILENAME_CRASH_FUNCTION); - - { - struct strbuf *buf_summary = strbuf_new(); - strbuf_append_strf(buf_summary, "[abrt] %s", package); - if (function && strlen(function) < 30) - strbuf_append_strf(buf_summary, ": %s", function); - if (reason) - strbuf_append_strf(buf_summary, ": %s", reason); - summary = strbuf_free_nobuf(buf_summary); - - char *bz_dsc = make_description_bz(crash_data); - dsc = xasprintf("abrt version: "VERSION"\n%s", bz_dsc); - free(bz_dsc); - } - - file = new_reportfile(); - - /* SELinux guys are not happy with /tmp, using /var/run/abrt */ - tempfile = xasprintf(LOCALSTATEDIR"/run/abrt/tmp-%lu-%lu.tar.gz", (long)getpid(), (long)time(NULL)); - - int pipe_from_parent_to_child[2]; - xpipe(pipe_from_parent_to_child); - child = fork(); - if (child == 0) - { - /* child */ - close(pipe_from_parent_to_child[1]); - xmove_fd(xopen3(tempfile, O_WRONLY | O_CREAT | O_EXCL, 0600), 1); - xmove_fd(pipe_from_parent_to_child[0], 0); - execlp("gzip", "gzip", NULL); - perror_msg_and_die("can't execute '%s'", "gzip"); - } - close(pipe_from_parent_to_child[0]); - - if (tar_fdopen(&tar, pipe_from_parent_to_child[1], tempfile, - /*fileops:(standard)*/ NULL, O_WRONLY | O_CREAT, 0644, TAR_GNU) != 0) - { - errmsg = "can't create temporary file in "LOCALSTATEDIR"/run/abrt"; - goto ret; - } - - { - GHashTableIter iter; - char *name; - struct crash_item *value; - g_hash_table_iter_init(&iter, crash_data); - while (g_hash_table_iter_next(&iter, (void**)&name, (void**)&value)) - { - if (strcmp(name, FILENAME_COUNT) == 0) continue; - if (strcmp(name, CD_DUMPDIR) == 0) continue; - if (strcmp(name, FILENAME_INFORMALL) == 0) continue; - if (strcmp(name, FILENAME_MESSAGE) == 0) continue; // plugin's status message (if we already reported it yesterday) - if (strcmp(name, FILENAME_DESCRIPTION) == 0) continue; // package description - - const char *content = value->content; - if (value->flags & CD_FLAG_TXT) - { - reportfile_add_binding_from_string(file, name, content); - } - else if (value->flags & CD_FLAG_BIN) - { - const char *basename = strrchr(content, '/'); - if (basename) - basename++; - else - basename = content; - char *xml_name = concat_path_file("content", basename); - reportfile_add_binding_from_namedfile(file, - /*on_disk_filename */ content, - /*binding_name */ name, - /*recorded_filename*/ xml_name, - /*binary */ 1); - if (tar_append_file(tar, (char*)content, xml_name) != 0) - { - errmsg = "can't create temporary file in "LOCALSTATEDIR"/run/abrt"; - free(xml_name); - goto ret; - } - free(xml_name); - } - } - } - - /* Write out content.xml in the tarball's root */ - { - const char *signature = reportfile_as_string(file); - unsigned len = strlen(signature); - unsigned len512 = (len + 511) & ~511; - char *block = (char*)memcpy(xzalloc(len512), signature, len); - th_set_type(tar, S_IFREG | 0644); - th_set_mode(tar, S_IFREG | 0644); - //th_set_link(tar, char *linkname); - //th_set_device(tar, dev_t device); - //th_set_user(tar, uid_t uid); - //th_set_group(tar, gid_t gid); - //th_set_mtime(tar, time_t fmtime); - th_set_path(tar, (char*)"content.xml"); - th_set_size(tar, len); - th_finish(tar); /* caclulate and store th xsum etc */ - if (th_write(tar) != 0 - || full_write(tar_fd(tar), block, len512) != len512 - || tar_close(tar) != 0 - ) { - free(block); - errmsg = "can't create temporary file in "LOCALSTATEDIR"/run/abrt"; - goto ret; - } - tar = NULL; - free(block); - } - - { - log(_("Creating a new case...")); - char* result = send_report_to_new_case(url, - login, - password, - ssl_verify, - summary, - dsc, - package, - tempfile - ); - /* Temporary hackish detection of errors. Ideally, - * send_report_to_new_case needs to have better error reporting. - */ - if (strncasecmp(result, "error", 5) == 0) - { - /* - * result can contain "...server says: 'multi-line text'" - * Replace all '\n' with spaces: - * we want this message to be, logically, one log entry. - * IOW: one line, not many lines. - */ - char *src, *dst; - dst = src = result; - while (1) - { - unsigned char c = *src++; - if (c == '\n') - c = ' '; - *dst++ = c; - if (c == '\0') - break; - } - /* Use sanitized string as error message */ - error_msg_and_die("%s", result); - } - /* No error */ - log("%s", result); - free(result); - } - - ret: - // Damn, selinux does not allow SIGKILLing our own child! wtf?? - //kill(child, SIGKILL); /* just in case */ - waitpid(child, NULL, 0); - if (tar) - tar_close(tar); - //close(pipe_from_parent_to_child[1]); - tar_close() does it itself - unlink(tempfile); - free(tempfile); - reportfile_free(file); - - free(summary); - free(dsc); - - free(url); - free(login); - free(password); - free_crash_data(crash_data); - - if (errmsg) - error_msg_and_die("%s", errmsg); -} - -int main(int argc, char **argv) -{ - char *env_verbose = getenv("ABRT_VERBOSE"); - if (env_verbose) - g_verbose = atoi(env_verbose); - - map_string_h *settings = new_map_string(); - const char *dump_dir_name = "."; - enum { - OPT_s = (1 << 0), - }; - int optflags = 0; - int opt; - while ((opt = getopt(argc, argv, "c:d:vs")) != -1) - { - switch (opt) - { - case 'c': - VERB1 log("Loading settings from '%s'", optarg); - load_conf_file(optarg, settings, /*skip key w/o values:*/ true); - VERB3 log("Loaded '%s'", optarg); - break; - case 'd': - dump_dir_name = optarg; - break; - case 'v': - g_verbose++; - break; - case 's': - optflags |= OPT_s; - break; - default: - /* Careful: the string below contains tabs, dont replace with spaces */ - error_msg_and_die( - "Usage: "PROGNAME" -c CONFFILE -d DIR [-vs]" - "\n" - "\nReport a crash to RHTSupport" - "\n" - "\nOptions:" - "\n -c FILE Configuration file (may be given many times)" - "\n -d DIR Crash dump directory" - "\n -v Verbose" - "\n -s Log to syslog" - ); - } - } - - putenv(xasprintf("ABRT_VERBOSE=%u", g_verbose)); - -//DONT! our stdout/stderr goes directly to daemon, don't want to have prefix there. -// msg_prefix = xasprintf(PROGNAME"[%u]", getpid()); - - if (optflags & OPT_s) - { - openlog(msg_prefix, 0, LOG_DAEMON); - logmode = LOGMODE_SYSLOG; - } - - VERB1 log("Initializing XML-RPC library"); - xmlrpc_env env; - xmlrpc_env_init(&env); - xmlrpc_client_setup_global_const(&env); - if (env.fault_occurred) - 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); - - free_map_string(settings); - return 0; -} diff --git a/src/plugins/abrt-action-upload.c b/src/plugins/abrt-action-upload.c new file mode 100644 index 00000000..8789f0e7 --- /dev/null +++ b/src/plugins/abrt-action-upload.c @@ -0,0 +1,287 @@ +/* + Copyright (C) 2010 ABRT team + Copyright (C) 2010 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 +#include +#include "abrtlib.h" +#include "parse_options.h" +#include "abrt_crash_dump.h" + +#define PROGNAME "abrt-action-upload" + +//TODO: use this for better logging +#if 0 +/* "read local data from a file" callback */ +static size_t fread_with_reporting(void *ptr, size_t size, size_t nmemb, void *userdata) +{ + static time_t last_t; // hack + + FILE *fp = (FILE*)userdata; + time_t t = time(NULL); + + // Report current file position every 16 seconds + if (!(t & 0xf) && last_t != t) + { + last_t = t; + off_t cur_pos = ftello(fp); + fseeko(fp, 0, SEEK_END); + off_t sz = ftello(fp); + fseeko(fp, cur_pos, SEEK_SET); + log(_("Uploaded: %llu of %llu kbytes"), + (unsigned long long)cur_pos / 1024, + (unsigned long long)sz / 1024); + } + + return fread(ptr, size, nmemb, fp); +} +#endif + +static int send_file(const char *url, const char *filename) +{ + FILE *fp = fopen(filename, "r"); + if (!fp) + { + perror_msg("Can't open '%s'", filename); + return 1; + } + + log(_("Sending %s to %s"), filename, url); + + struct stat stbuf; + fstat(fileno(fp), &stbuf); /* never fails */ + char *whole_url = concat_path_file(url, strrchr(filename, '/') ? : filename); + + CURL *curl = curl_easy_init(); + if (!curl) + { + error_msg_and_die("Can't create curl handle"); + } + /* Buffer[CURL_ERROR_SIZE] curl stores human readable error messages in. + * This may be more helpful than just return code from curl_easy_perform. + * curl will need it until curl_easy_cleanup. */ + char curl_err_msg[CURL_ERROR_SIZE]; + curl_err_msg[0] = '\0'; + curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_err_msg); + /* enable uploading */ + curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); + /* specify target */ + curl_easy_setopt(curl, CURLOPT_URL, whole_url); + /* FILE handle: passed to the default callback, it will fread() it */ + curl_easy_setopt(curl, CURLOPT_READDATA, fp); + curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)stbuf.st_size); + + /* everything is done here; result 0 means success */ + CURLcode result = curl_easy_perform(curl); + free(whole_url); + fclose(fp); + if (result != 0) + error_msg("Error while uploading: '%s'", curl_easy_strerror(result)); + else + /* This ends up a "reporting status message" in abrtd */ + log(_("Successfully sent %s to %s"), filename, url); + + curl_easy_cleanup(curl); + + return result; +} + +static int create_and_upload_archive( + const char *dump_dir_name, + map_string_h *settings) +{ + int result = 0; + + pid_t child; + TAR* tar = NULL; + const char* errmsg = NULL; + char* tempfile = NULL; + + struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0); + if (!dd) + exit(1); /* error msg is already logged by dd_opendir */ + + /* Gzipping e.g. 0.5gig coredump takes a while. Let client know what we are doing */ + log(_("Compressing data")); + +//TODO: +//Encrypt = yes +//ArchiveType = .tar.bz2 +//ExcludeFiles = foo,bar*,b*z + char* env; + env = getenv("Upload_URL"); + const char *url = (env ? env : get_map_string_item_or_empty(settings, "URL")); + + /* Create a child gzip which will compress the data */ + /* SELinux guys are not happy with /tmp, using /var/run/abrt */ + tempfile = xasprintf(LOCALSTATEDIR"/run/abrt/tmp-%lu-%lu.tar.gz", (long)getpid(), (long)time(NULL)); + int pipe_from_parent_to_child[2]; + xpipe(pipe_from_parent_to_child); + child = fork(); + if (child == 0) + { + /* child */ + close(pipe_from_parent_to_child[1]); + xmove_fd(pipe_from_parent_to_child[0], 0); + xmove_fd(xopen3(tempfile, O_WRONLY | O_CREAT | O_EXCL, 0600), 1); + execlp("gzip", "gzip", NULL); + perror_msg_and_die("can't execute '%s'", "gzip"); + } + close(pipe_from_parent_to_child[0]); + + /* Create tar writer object */ + if (tar_fdopen(&tar, pipe_from_parent_to_child[1], tempfile, + /*fileops:(standard)*/ NULL, O_WRONLY | O_CREAT, 0644, TAR_GNU) != 0) + { + errmsg = "Can't create temporary file in "LOCALSTATEDIR"/run/abrt"; + goto ret; + } + + /* Write data to the tarball */ + { + dd_init_next_file(dd); + char *short_name, *full_name; + while (dd_get_next_file(dd, &short_name, &full_name)) + { + if (strcmp(short_name, FILENAME_COUNT) == 0) goto next; + if (strcmp(short_name, CD_DUMPDIR) == 0) goto next; + if (strcmp(short_name, FILENAME_INFORMALL) == 0) goto next; + if (strcmp(short_name, FILENAME_MESSAGE) == 0) goto next; // plugin's status message (if we already reported it yesterday) + if (strcmp(short_name, FILENAME_DESCRIPTION) == 0) goto next; // package description + // dd_get_next_file guarantees this: + //struct stat stbuf; + //if (stat(full_name, &stbuf) != 0) + // || !S_ISREG(stbuf.st_mode) + //) { + // goto next; + //} + if (tar_append_file(tar, full_name, short_name) != 0) + { + errmsg = "Can't create temporary file in "LOCALSTATEDIR"/run/abrt"; + free(short_name); + free(full_name); + goto ret; + } + next: + free(short_name); + free(full_name); + } + } + dd_close(dd); + dd = NULL; + + /* Close tar writer... */ + if (tar_append_eof(tar) != 0 || tar_close(tar) != 0) + { + errmsg = "Can't create temporary file in "LOCALSTATEDIR"/run/abrt"; + goto ret; + } + tar = NULL; + /* ...and check that gzip child finished successfully */ + int status; + waitpid(child, &status, 0); + child = -1; + if (status != 0) + { + /* We assume the error was out-of-disk-space or out-of-quota */ + errmsg = "Can't create temporary file in "LOCALSTATEDIR"/run/abrt"; + goto ret; + } + + /* Upload the tarball */ + if (url && url[0]) + { + result = send_file(url, tempfile); + /* cleanup code will delete tempfile */ + } + else + { + log(_("Archive is created: '%s'"), tempfile); + free(tempfile); + tempfile = NULL; + } + + ret: + dd_close(dd); + if (tar) + tar_close(tar); + /* close(pipe_from_parent_to_child[1]); - tar_close() does it itself */ + if (child > 0) + waitpid(child, NULL, 0); + if (tempfile) + { + unlink(tempfile); + free(tempfile); + } + if (errmsg) + error_msg_and_die("%s", errmsg); + + return result; +} + +int main(int argc, char **argv) +{ + char *env_verbose = getenv("ABRT_VERBOSE"); + if (env_verbose) + g_verbose = atoi(env_verbose); + + const char *dump_dir_name = "."; + const char *conf_file = NULL; + const char *url = NULL; + + const char *program_usage = _( + PROGNAME" [-v] -d DIR [-c CONFFILE] [-u URL]\n" + "\n" + "Upload compressed tarball of crash dump" + ); + enum { + OPT_v = 1 << 0, + OPT_d = 1 << 1, + OPT_c = 1 << 2, + OPT_u = 1 << 3, + }; + /* 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" , _("Crash dump directory")), + OPT_STRING('c', NULL, &conf_file , "CONFFILE", _("Config file")), + OPT_STRING('u', NULL, &url , "URL" , _("Base URL to upload to")), + OPT_END() + }; + + /*unsigned opts =*/ parse_opts(argc, argv, program_options, program_usage); + + putenv(xasprintf("ABRT_VERBOSE=%u", g_verbose)); + //msg_prefix = PROGNAME; + //if (optflags & OPT_s) + //{ + // openlog(msg_prefix, 0, LOG_DAEMON); + // logmode = LOGMODE_SYSLOG; + //} + + map_string_h *settings = new_map_string(); + if (url) + g_hash_table_replace(settings, xstrdup("URL"), xstrdup(url)); + if (conf_file) + load_conf_file(conf_file, settings, /*skip key w/o values:*/ true); + + int result = create_and_upload_archive(dump_dir_name, settings); + + free_map_string(settings); + return result; +} diff --git a/src/plugins/abrt-action-upload.cpp b/src/plugins/abrt-action-upload.cpp deleted file mode 100644 index 8789f0e7..00000000 --- a/src/plugins/abrt-action-upload.cpp +++ /dev/null @@ -1,287 +0,0 @@ -/* - Copyright (C) 2010 ABRT team - Copyright (C) 2010 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 -#include -#include "abrtlib.h" -#include "parse_options.h" -#include "abrt_crash_dump.h" - -#define PROGNAME "abrt-action-upload" - -//TODO: use this for better logging -#if 0 -/* "read local data from a file" callback */ -static size_t fread_with_reporting(void *ptr, size_t size, size_t nmemb, void *userdata) -{ - static time_t last_t; // hack - - FILE *fp = (FILE*)userdata; - time_t t = time(NULL); - - // Report current file position every 16 seconds - if (!(t & 0xf) && last_t != t) - { - last_t = t; - off_t cur_pos = ftello(fp); - fseeko(fp, 0, SEEK_END); - off_t sz = ftello(fp); - fseeko(fp, cur_pos, SEEK_SET); - log(_("Uploaded: %llu of %llu kbytes"), - (unsigned long long)cur_pos / 1024, - (unsigned long long)sz / 1024); - } - - return fread(ptr, size, nmemb, fp); -} -#endif - -static int send_file(const char *url, const char *filename) -{ - FILE *fp = fopen(filename, "r"); - if (!fp) - { - perror_msg("Can't open '%s'", filename); - return 1; - } - - log(_("Sending %s to %s"), filename, url); - - struct stat stbuf; - fstat(fileno(fp), &stbuf); /* never fails */ - char *whole_url = concat_path_file(url, strrchr(filename, '/') ? : filename); - - CURL *curl = curl_easy_init(); - if (!curl) - { - error_msg_and_die("Can't create curl handle"); - } - /* Buffer[CURL_ERROR_SIZE] curl stores human readable error messages in. - * This may be more helpful than just return code from curl_easy_perform. - * curl will need it until curl_easy_cleanup. */ - char curl_err_msg[CURL_ERROR_SIZE]; - curl_err_msg[0] = '\0'; - curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_err_msg); - /* enable uploading */ - curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); - /* specify target */ - curl_easy_setopt(curl, CURLOPT_URL, whole_url); - /* FILE handle: passed to the default callback, it will fread() it */ - curl_easy_setopt(curl, CURLOPT_READDATA, fp); - curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)stbuf.st_size); - - /* everything is done here; result 0 means success */ - CURLcode result = curl_easy_perform(curl); - free(whole_url); - fclose(fp); - if (result != 0) - error_msg("Error while uploading: '%s'", curl_easy_strerror(result)); - else - /* This ends up a "reporting status message" in abrtd */ - log(_("Successfully sent %s to %s"), filename, url); - - curl_easy_cleanup(curl); - - return result; -} - -static int create_and_upload_archive( - const char *dump_dir_name, - map_string_h *settings) -{ - int result = 0; - - pid_t child; - TAR* tar = NULL; - const char* errmsg = NULL; - char* tempfile = NULL; - - struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0); - if (!dd) - exit(1); /* error msg is already logged by dd_opendir */ - - /* Gzipping e.g. 0.5gig coredump takes a while. Let client know what we are doing */ - log(_("Compressing data")); - -//TODO: -//Encrypt = yes -//ArchiveType = .tar.bz2 -//ExcludeFiles = foo,bar*,b*z - char* env; - env = getenv("Upload_URL"); - const char *url = (env ? env : get_map_string_item_or_empty(settings, "URL")); - - /* Create a child gzip which will compress the data */ - /* SELinux guys are not happy with /tmp, using /var/run/abrt */ - tempfile = xasprintf(LOCALSTATEDIR"/run/abrt/tmp-%lu-%lu.tar.gz", (long)getpid(), (long)time(NULL)); - int pipe_from_parent_to_child[2]; - xpipe(pipe_from_parent_to_child); - child = fork(); - if (child == 0) - { - /* child */ - close(pipe_from_parent_to_child[1]); - xmove_fd(pipe_from_parent_to_child[0], 0); - xmove_fd(xopen3(tempfile, O_WRONLY | O_CREAT | O_EXCL, 0600), 1); - execlp("gzip", "gzip", NULL); - perror_msg_and_die("can't execute '%s'", "gzip"); - } - close(pipe_from_parent_to_child[0]); - - /* Create tar writer object */ - if (tar_fdopen(&tar, pipe_from_parent_to_child[1], tempfile, - /*fileops:(standard)*/ NULL, O_WRONLY | O_CREAT, 0644, TAR_GNU) != 0) - { - errmsg = "Can't create temporary file in "LOCALSTATEDIR"/run/abrt"; - goto ret; - } - - /* Write data to the tarball */ - { - dd_init_next_file(dd); - char *short_name, *full_name; - while (dd_get_next_file(dd, &short_name, &full_name)) - { - if (strcmp(short_name, FILENAME_COUNT) == 0) goto next; - if (strcmp(short_name, CD_DUMPDIR) == 0) goto next; - if (strcmp(short_name, FILENAME_INFORMALL) == 0) goto next; - if (strcmp(short_name, FILENAME_MESSAGE) == 0) goto next; // plugin's status message (if we already reported it yesterday) - if (strcmp(short_name, FILENAME_DESCRIPTION) == 0) goto next; // package description - // dd_get_next_file guarantees this: - //struct stat stbuf; - //if (stat(full_name, &stbuf) != 0) - // || !S_ISREG(stbuf.st_mode) - //) { - // goto next; - //} - if (tar_append_file(tar, full_name, short_name) != 0) - { - errmsg = "Can't create temporary file in "LOCALSTATEDIR"/run/abrt"; - free(short_name); - free(full_name); - goto ret; - } - next: - free(short_name); - free(full_name); - } - } - dd_close(dd); - dd = NULL; - - /* Close tar writer... */ - if (tar_append_eof(tar) != 0 || tar_close(tar) != 0) - { - errmsg = "Can't create temporary file in "LOCALSTATEDIR"/run/abrt"; - goto ret; - } - tar = NULL; - /* ...and check that gzip child finished successfully */ - int status; - waitpid(child, &status, 0); - child = -1; - if (status != 0) - { - /* We assume the error was out-of-disk-space or out-of-quota */ - errmsg = "Can't create temporary file in "LOCALSTATEDIR"/run/abrt"; - goto ret; - } - - /* Upload the tarball */ - if (url && url[0]) - { - result = send_file(url, tempfile); - /* cleanup code will delete tempfile */ - } - else - { - log(_("Archive is created: '%s'"), tempfile); - free(tempfile); - tempfile = NULL; - } - - ret: - dd_close(dd); - if (tar) - tar_close(tar); - /* close(pipe_from_parent_to_child[1]); - tar_close() does it itself */ - if (child > 0) - waitpid(child, NULL, 0); - if (tempfile) - { - unlink(tempfile); - free(tempfile); - } - if (errmsg) - error_msg_and_die("%s", errmsg); - - return result; -} - -int main(int argc, char **argv) -{ - char *env_verbose = getenv("ABRT_VERBOSE"); - if (env_verbose) - g_verbose = atoi(env_verbose); - - const char *dump_dir_name = "."; - const char *conf_file = NULL; - const char *url = NULL; - - const char *program_usage = _( - PROGNAME" [-v] -d DIR [-c CONFFILE] [-u URL]\n" - "\n" - "Upload compressed tarball of crash dump" - ); - enum { - OPT_v = 1 << 0, - OPT_d = 1 << 1, - OPT_c = 1 << 2, - OPT_u = 1 << 3, - }; - /* 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" , _("Crash dump directory")), - OPT_STRING('c', NULL, &conf_file , "CONFFILE", _("Config file")), - OPT_STRING('u', NULL, &url , "URL" , _("Base URL to upload to")), - OPT_END() - }; - - /*unsigned opts =*/ parse_opts(argc, argv, program_options, program_usage); - - putenv(xasprintf("ABRT_VERBOSE=%u", g_verbose)); - //msg_prefix = PROGNAME; - //if (optflags & OPT_s) - //{ - // openlog(msg_prefix, 0, LOG_DAEMON); - // logmode = LOGMODE_SYSLOG; - //} - - map_string_h *settings = new_map_string(); - if (url) - g_hash_table_replace(settings, xstrdup("URL"), xstrdup(url)); - if (conf_file) - load_conf_file(conf_file, settings, /*skip key w/o values:*/ true); - - int result = create_and_upload_archive(dump_dir_name, settings); - - free_map_string(settings); - return result; -} -- cgit