bool sr_operating_system_parse_etc_system_release(const char *etc_system_release, char **name, char **version) { const char *release = strstr(etc_system_release, " release "); if (!release) return false; /* Normal form of Red Hat Enterprise Linux's name is "rhel" */ if (strncasecmp("Red Hat Enterprise Linux", etc_system_release, strlen("Red Hat Enterprise Linux")) == 0) *name = sr_strndup("rhel", strlen("rhel")); else { *name = sr_strndup(etc_system_release, release - etc_system_release); if (0 == strlen(*name)) return false; /* make the name all lower case */ char *a = *name; while (*a) { *a = tolower(*a); a++; } } const char *version_begin = release + strlen(" release "); const char *version_end = version_begin; while (isdigit(*version_end) || *version_end == '.') ++version_end; // Fallback when parsing of version fails. ptrdiff_t version_len = version_end - version_begin; if (0 == version_len) version_end = version_begin + strlen(version_begin); *version = sr_strndup(version_begin, version_end - version_begin); return true; }
struct sr_rpm_package * sr_abrt_parse_dso_list(const char *text) { struct sr_rpm_package *packages = NULL; const char *pos = text; while (pos && *pos) { // Skip dynamic library name. pos = strchr(pos, ' '); if (!pos) continue; // Skip the space. ++pos; // Find the package NEVRA. char *end = strchr(pos, ' '); if (!end || end - pos <= 1) { pos = strchr(pos, '\n'); continue; } // Parse the package NEVRA. char *nevra = sr_strndup(pos, end - pos); struct sr_rpm_package *dso_package = sr_rpm_package_new(); bool success = sr_rpm_package_parse_nevra(nevra, &dso_package->name, &dso_package->epoch, &dso_package->version, &dso_package->release, &dso_package->architecture); free(nevra); // If parsing failed, move to the next line. if (!success) { sr_rpm_package_free(dso_package, true); pos = strchr(pos, '\n'); continue; } // Find the package install time. char *eol = strchr(pos, '\n'); if (!eol) { sr_rpm_package_free(dso_package, true); break; } char *line = sr_strndup(pos, eol - pos); pos = strrchr(line, ' '); if (!pos) { pos = eol; sr_rpm_package_free(dso_package, true); free(line); continue; } ++pos; // Parse the package install time. int len = sr_parse_uint64((const char**)&pos, &dso_package->install_time); free(line); if (len <= 0) { pos = eol; sr_rpm_package_free(dso_package, true); continue; } // Append the package to the list. packages = sr_rpm_package_append(packages, dso_package); pos = eol; } return packages; }
struct sr_java_frame * sr_java_frame_parse(const char **input, struct sr_location *location) { const char *mark = *input; int lines, columns; /* at SimpleTest.throwNullPointerException(SimpleTest.java:36) [file:/usr/lib/java/foo.class] */ const char *cursor = sr_strstr_location(mark, "at", &lines, &columns); if (!cursor) { location->message = "Frame expected"; return NULL; } /* SimpleTest.throwNullPointerException(SimpleTest.java:36) [file:/usr/lib/java/foo.class] */ cursor = mark = cursor + 2; sr_location_add(location, lines, columns + 2); /* SimpleTest.throwNullPointerException(SimpleTest.java:36) [file:/usr/lib/java/foo.class] */ cursor = sr_skip_whitespace(cursor); sr_location_add(location, 0, cursor - mark); mark = cursor; sr_location_add(location, 0, sr_skip_char_cspan(&cursor, "(\n")); struct sr_java_frame *frame = sr_java_frame_new(); if (cursor != mark) frame->name = sr_strndup(mark, cursor - mark); /* (SimpleTest.java:36) [file:/usr/lib/java/foo.class] */ if (*cursor == '(') { ++cursor; sr_location_add(location, 0, 1); mark = cursor; sr_location_add(location, 0, sr_skip_char_cspan(&cursor, ":)\n")); if (mark != cursor) { if (sr_java_frame_parse_is_native_method(mark)) frame->is_native = true; else if (!sr_java_frame_parse_is_unknown_source(mark)) { /* DO NOT set file_name if input says that source isn't known */ frame->file_name = sr_strndup(mark, cursor - mark); frame->file_name = anonymize_path(frame->file_name); } } if (*cursor == ':') { ++cursor; sr_location_add(location, 0, 1); mark = cursor; sr_parse_uint32(&cursor, &(frame->file_line)); sr_location_add(location, 0, cursor - mark); } } /* [file:/usr/lib/java/foo.class] */ mark = sr_java_frame_parse_frame_url(frame, cursor, location); cursor = strchrnul(mark, '\n'); if (*cursor == '\n') { *input = cursor + 1; sr_location_add(location, 2, 0); } else { *input = cursor; /* don't take \0 Byte into account */ sr_location_add(location, 0, (cursor - mark) - 1); } return frame; }
/* [jar:http://locahost/usr/lib/java/foo.jar!/Foo.class] */ static const char *sr_java_frame_parse_frame_url(struct sr_java_frame *frame, const char *mark, struct sr_location *location) { const char *cursor = mark; sr_location_add(location, 0, sr_skip_char_cspan(&cursor, "[\n")); if (*cursor != '[') return cursor; ++cursor; sr_location_add(location, 0, 1); mark = cursor; sr_location_add(location, 0, sr_skip_char_cspan(&cursor, ":\n")); if (*cursor == ':') { const char *path_stop = "]\n"; if (strncmp("jar:", mark, strlen("jar:")) == 0) { /* From jar:file:/usr/lib/java/foo.jar!/Foo.class] */ /* ^ */ ++cursor; sr_location_add(location, 0, 1); mark = cursor; sr_location_add(location, 0, sr_skip_char_cspan(&cursor, ":\n")); path_stop = "!\n"; /* To file:/usr/lib/java/foo.jar!/Foo.class] */ /* ^ */ if (*cursor != ':') return cursor; } if (strncmp("file:", mark, strlen("file:")) != 0) { /* move cursor back in case of http: ... */ sr_location_add(location, 0, -(cursor - mark)); cursor = mark; } else { ++cursor; sr_location_add(location, 0, 1); mark = cursor; } sr_location_add(location, 0, sr_skip_char_cspan(&cursor, path_stop)); if (mark != cursor) { frame->class_path = sr_strndup(mark, cursor - mark); frame->class_path = anonymize_path(frame->class_path); } } if (*cursor != ']' && *cursor != '\n') sr_location_add(location, 0, sr_skip_char_cspan(&cursor, "]\n")); return cursor; }
struct sr_java_frame * sr_java_frame_parse_exception(const char **input, struct sr_location *location) { /* java.lang.NullPointerException: foo */ const char *cursor = sr_skip_whitespace(*input); sr_location_add(location, 0, cursor - *input); const char *mark = cursor; sr_location_add(location, 0, sr_skip_char_cspan(&cursor, ": \t\n")); if (mark == cursor) { location->message = "Expected exception name"; return NULL; } struct sr_java_frame *exception = sr_java_frame_new_exception(); exception->name = sr_strndup(mark, cursor - mark); /* : foo */ if (*cursor == ':') { ++cursor; sr_location_add(location, 0, 1); mark = cursor; /* foo */ cursor = sr_skip_whitespace(mark); sr_location_add(location, 0, cursor - mark); mark = cursor; sr_location_add(location, 0, sr_skip_char_cspan(&cursor, "\n")); if (mark != cursor) exception->message = sr_strndup(mark, cursor - mark); } else { /* just to be sure, that we skip white space behind exception name */ sr_location_add(location, 0, sr_skip_char_cspan(&cursor, "\n")); } if (*cursor == '\n') { ++cursor; /* this adds one line */ sr_location_add(location, 2, 0); } /* else *cursor == '\0' */ mark = cursor; struct sr_java_frame *frame = NULL; /* iterate line by line best effort - continue on error */ while (*cursor != '\0') { cursor = sr_skip_whitespace(mark); sr_location_add(location, 0, cursor - mark); /* Each inner exception has '...' at its end */ if (strncmp("... ", cursor, strlen("... ")) == 0) goto current_exception_done; /* Suppressed exceptions follow after the end of current exception */ if (strncmp("Suppressed: ", cursor, strlen("Suppressed: ")) == 0) goto current_exception_done; /* The top most exception does not have '...' at its end */ if (strncmp("Caused by: ", cursor, strlen("Caused by: ")) == 0) goto parse_inner_exception; struct sr_java_frame *parsed = sr_java_frame_parse(&cursor, location); if (parsed == NULL) { sr_java_frame_free(exception); return NULL; } mark = cursor; if (exception->next == NULL) exception->next = parsed; else { assert(frame); frame->next = parsed; } frame = parsed; } /* We are done with the top most exception without inner exceptions */ /* because of no 'Caused by:' and no '...' */ goto exception_parsing_successful; current_exception_done: sr_skip_to_next_line_location(&cursor, &location->line, &location->column); mark = cursor; cursor = sr_skip_whitespace(mark); sr_location_add(location, 0, cursor - mark); if (strncmp("Suppressed: ", cursor, strlen("Suppressed: ")) == 0) { /* Skip all lines related to the suppressed exception. We can do * this by skipping all lines that begin with a whitespace - the * main exception chain always begins without preceding whitespace. */ sr_skip_to_next_line_location(&cursor, &location->line, &location->column); while (cursor && isspace(*cursor)) sr_skip_to_next_line_location(&cursor, &location->line, &location->column); } if (strncmp("Caused by: ", cursor, strlen("Caused by: ")) == 0) { parse_inner_exception: cursor += strlen("Caused by: "); sr_location_add(location, 0, strlen("Caused by: ")); struct sr_java_frame *inner = sr_java_frame_parse_exception(&cursor, location); if (inner == NULL) { sr_java_frame_free(exception); return NULL; } struct sr_java_frame *last_inner = sr_java_frame_get_last(inner); last_inner->next = exception; exception = inner; } exception_parsing_successful: *input = cursor; return exception; }