--- src/daemon/abrt-server.c | 149 ++++++++++++++-------------------------------- 1 files changed, 46 insertions(+), 103 deletions(-)
diff --git a/src/daemon/abrt-server.c b/src/daemon/abrt-server.c index 15f3370..43c6389 100644 --- a/src/daemon/abrt-server.c +++ b/src/daemon/abrt-server.c @@ -77,29 +77,21 @@ static unsigned total_bytes_read = 0; static uid_t client_uid = (uid_t)-1L;
static int pid; -static char *executable; -static char *backtrace; -/* "python", "ruby" etc. */ -static char *analyzer; -/* Directory base name: "pyhook", "ruby" etc. */ -static char *dir_basename; -/* Crash reason. - * Python example: - * "CCMainWindow.py:1:<module>:ZeroDivisionError: integer division or modulo by zero" - */ -static char *reason; -
/* Create a new debug dump from client session. * Caller must ensure that all fields in struct client * are properly filled. */ -static int create_debug_dump() +static int create_debug_dump(GHashTable *problem_info) { /* Create temp directory with the debug dump. This directory is renamed to final directory name after all files have been stored into it. */ + gchar *dir_basename = g_hash_table_lookup(problem_info, "basename"); + GHashTableIter iter; + gpointer gpkey, gpvalue; + char *path = xasprintf("%s/%s-%s-%u.new", g_settings_dump_location, dir_basename, @@ -115,15 +107,17 @@ static int create_debug_dump() } dd_create_basic_files(dd, client_uid);
- dd_save_text(dd, FILENAME_ANALYZER, analyzer); - dd_save_text(dd, FILENAME_EXECUTABLE, executable); - dd_save_text(dd, FILENAME_BACKTRACE, backtrace); - dd_save_text(dd, FILENAME_REASON, reason); - - /* Obtain and save the command line. */ - char *cmdline = get_cmdline(pid); - dd_save_text(dd, FILENAME_CMDLINE, cmdline ? : ""); - free(cmdline); + gpkey = g_hash_table_lookup(problem_info, FILENAME_CMDLINE); + if (!gpkey) + { + /* Obtain and save the command line. */ + char *cmdline = get_cmdline(pid); + if (cmdline) + { + dd_save_text(dd, FILENAME_CMDLINE, cmdline); + free(cmdline); + } + }
/* Store id of the user whose application crashed. */ char uid_str[sizeof(long) * 3 + 2]; @@ -132,6 +126,12 @@ static int create_debug_dump()
dd_save_text(dd, "abrt_version", VERSION);
+ g_hash_table_iter_init(&iter, problem_info); + while (g_hash_table_iter_next(&iter, &gpkey, &gpvalue)) + { + dd_save_text(dd, (gchar *) gpkey, (gchar *) gpvalue); + } + dd_close(dd);
/* Move the completely created debug dump to @@ -141,7 +141,7 @@ static int create_debug_dump() strcpy(path, newpath); free(newpath);
- log("Saved %s crash dump of pid %u to %s", analyzer, pid, path); + log("Saved crash dump of pid %u to %s", pid, path);
/* Trim old crash dumps if necessary */ load_abrt_conf(); @@ -227,87 +227,34 @@ static bool printable_str(const char *str) return true; }
-/* @returns - * Caller is responsible to call free() on the returned - * pointer. - * If NULL is returned, string extraction failed. - */ -static char *try_to_get_string(const char *message, - const char *tag, - size_t max_len, - bool printable, - bool allow_slashes) -{ - if (!starts_with(message, tag)) - return NULL; - - const char *contents = message + strlen(tag); - if ((printable && !printable_str(contents)) - || (!allow_slashes && strchr(contents, '/')) - ) { - error_msg("Received %s contains invalid characters, skipping", tag); - return NULL; - } - - if (strlen(contents) > max_len) - { - error_msg("Received %s too long, trimming to %lu", tag, (long)max_len); - } - - return xstrndup(contents, max_len); -} - /* Handles a message received from client over socket. */ -static void process_message(const char *message) +static void process_message(GHashTable *problem_info, char *message) { -/* @param tag - * The message identifier. Message starting with it - * is handled by this macro. - * @param field - * Member in struct client, which should be filled by - * the field contents. - * @param max_len - * Maximum length of the field in bytes. - * Exceeding bytes are trimmed. - * @param printable - * Whether to limit the field contents to ASCII only. - * @param allow_slashes - * Whether to allow slashes to be a part of input. - */ -#define HANDLE_INCOMING_STRING(tag, field, max_len, printable, allow_slashes) \ -{ \ - char *s = try_to_get_string(message, tag, max_len, printable, allow_slashes); \ - if (s) \ - { \ - free(field); \ - field = s; \ - VERB3 log("Saved %s%s", tag, s); \ - return; \ - } \ -} + gchar *position; + gchar *key, *value;
- HANDLE_INCOMING_STRING("EXECUTABLE=", executable, PATH_MAX, true, true); - HANDLE_INCOMING_STRING("BACKTRACE=", backtrace, MAX_BACKTRACE_SIZE, false, true); - HANDLE_INCOMING_STRING("BASENAME=", dir_basename, 100, true, false); - HANDLE_INCOMING_STRING("ANALYZER=", analyzer, 100, true, true); - HANDLE_INCOMING_STRING("REASON=", reason, 512, false, true); - -#undef HANDLE_INCOMING_STRING + position = strchr(message, '='); + if (position) + { + key = g_ascii_strdown(message, position - message);
- /* PID is not handled as a string, we convert it to pid_t. */ - if (starts_with(message, "PID=")) + position++; + value = xstrndup(position, strlen(position)); + g_hash_table_insert(problem_info, key, value); + } + else { - pid = xatou(message + strlen("PID=")); - if (pid < 1) - /* pid == 0 is error, the lowest PID is 1. */ - error_msg_and_die("Malformed or out-of-range number: '%s'", message + strlen("PID=")); - VERB3 log("Saved PID %u", pid); - return; + error_msg("Invalid message format: '%s'", message); } }
static int perform_http_xact(void) { + /* use free instead of g_free so that we can use xstr* functions from + * libreport/lib/xfuncs.c + */ + GHashTable *problem_info = g_hash_table_new_full(g_str_hash, g_str_equal, + free, free); /* Read header */ char *body_start = NULL; char *messagebuf_data = NULL; @@ -404,7 +351,7 @@ static int perform_http_xact(void) if (len >= messagebuf_len) break; /* messagebuf has at least one NUL - process the line */ - process_message(messagebuf_data); + process_message(problem_info, messagebuf_data); messagebuf_len -= (len + 1); memmove(messagebuf_data, messagebuf_data + len + 1, messagebuf_len); } @@ -427,16 +374,12 @@ static int perform_http_xact(void) error_msg_and_die("Message is too long, aborting"); }
- /* Creates debug dump if all fields were already provided. */ - if (!pid || !backtrace || !executable - || !analyzer || !dir_basename || !reason - ) { - error_msg_and_die("Some data are missing. Aborting"); - } - /* Write out the crash dump. Don't let alarm to interrupt here */ alarm(0); - return create_debug_dump(); + int ret = create_debug_dump(problem_info); + + g_hash_table_destroy(problem_info); + return ret; }
static void dummy_handler(int sig_unused) {}