diff options
author | Joshua Tolley | 2010-11-26 17:22:01 +0000 |
---|---|---|
committer | Joshua Tolley | 2010-11-26 17:22:01 +0000 |
commit | fe9d8f21bbdfb442b8233b4627a0c67dc458a8bd (patch) | |
tree | a88daa49fc47e64777af3d331cf142e0604c2d48 /query_reader.c |
Diffstat (limited to 'query_reader.c')
-rw-r--r-- | query_reader.c | 333 |
1 files changed, 333 insertions, 0 deletions
diff --git a/query_reader.c b/query_reader.c new file mode 100644 index 0000000..6067ccb --- /dev/null +++ b/query_reader.c @@ -0,0 +1,333 @@ +#include <yaml.h> +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <unistd.h> +#include "query_reader.h" + +/* TODO: Return value checking of strdup, etc. is fairly haphazard. */ + +void print_error(yaml_parser_t *parser); + +typedef enum query_reader_state_s { + INIT, + READ_QUERY, + NAME_VALUE, + QUERY_VALUE, + OID_VALUE, + INDEXES_VALUE, + MINCOL_VALUE, + TYPES_VALUE, + TYPE_MAPPING_VALUE +} query_reader_state_t; + +typedef struct string_to_int_struct { + char *name; + int value; +} string_to_int; + +char *yaml_get_event_type(yaml_event_type_t t); + +char * +yaml_get_event_type (yaml_event_type_t t) { + switch (t) { + case YAML_NO_EVENT: + return "YAML_NO_EVENT"; + case YAML_STREAM_START_EVENT: + return "YAML_STREAM_START_EVENT"; + case YAML_STREAM_END_EVENT: + return "YAML_STREAM_END_EVENT"; + case YAML_DOCUMENT_START_EVENT: + return "YAML_DOCUMENT_START_EVENT"; + case YAML_DOCUMENT_END_EVENT: + return "YAML_DOCUMENT_END_EVENT"; + case YAML_ALIAS_EVENT: + return "YAML_ALIAS_EVENT"; + case YAML_SCALAR_EVENT: + return "YAML_SCALAR_EVENT"; + case YAML_SEQUENCE_START_EVENT: + return "YAML_SEQUENCE_START_EVENT"; + case YAML_SEQUENCE_END_EVENT: + return "YAML_SEQUENCE_END_EVENT"; + case YAML_MAPPING_START_EVENT: + return "YAML_MAPPING_START_EVENT"; + case YAML_MAPPING_END_EVENT: + return "YAML_MAPPING_END_EVENT"; + default: + return "Unknown yaml event type"; + }; +} + +pgsnmpd_query * +parse_config(const char *filename) { + FILE *inputfile; + u_char *types; + yaml_parser_t parser; + yaml_event_t event; + int done = 0, i, error = 0, found = 0; + pgsnmpd_query *head = NULL, *cur, *newquery; + query_reader_state_t st = INIT; + char *name_str = NULL, *query_str = NULL, *oid_str = NULL; + int indexes_val, mincol_val, query_count = 0; + oid *oid_arr; + int oid_len = 1, typecol, typeslen; + int yaml_type_map_len = 6; + string_to_int yaml_type_map[6] = { + { "name", NAME_VALUE }, + { "query", QUERY_VALUE }, + { "oid", OID_VALUE }, + { "indexes", INDEXES_VALUE }, + { "min_column", MINCOL_VALUE }, + { "types", TYPES_VALUE } + }; + + int snmp_type_map_len = 5; + string_to_int snmp_type_map[5] = { + { "ASN_INTEGER", ASN_INTEGER }, + { "ASN_FLOAT", ASN_FLOAT }, + { "ASN_BOOLEAN", ASN_BOOLEAN }, + { "ASN_OBJECT_ID", ASN_OBJECT_ID }, + { "ASN_OCTET_STR", ASN_OCTET_STR }, + }; + + yaml_parser_initialize(&parser); + inputfile = fopen(filename, "rb"); + if (inputfile == NULL) { + snmp_log(LOG_ERR, "Problem opening input file \"%s\": %s\n", filename, strerror(errno)); + return 0; + } + yaml_parser_set_input_file(&parser, inputfile); + + while (!done) { + if (!yaml_parser_parse(&parser, &event)) { + error = 1; + break; + } + done = (event.type == YAML_STREAM_END_EVENT); + /*snmp_log(LOG_INFO, "Found a %s value\n", yaml_get_event_type(event.type));*/ + /* head = process_event(&event); */ + switch (st) { + case INIT: + if (event.type == YAML_SCALAR_EVENT && + strcmp((char *)event.data.scalar.value, "queries") == 0) { + st = READ_QUERY; + if (name_str != NULL) free(name_str); + if (query_str != NULL) free(query_str); + if (oid_str != NULL) free(oid_str); + + name_str = NULL; + query_str = NULL; + oid_str = NULL; + + indexes_val = -1; + mincol_val = -1; + } + query_count++; + break; + case READ_QUERY: + if (event.type == YAML_SCALAR_EVENT) { + typeslen = -1; + types = NULL; + found = 0; + for (i = 0; i < yaml_type_map_len; i++) { + if (strcmp(yaml_type_map[i].name, (char*) event.data.scalar.value) == 0) { + st = yaml_type_map[i].value; + found = 1; + break; + } + } + if (found != 1) { + snmp_log(LOG_ERR, "Unexpected data object reading query %d: %s\n", query_count, (char *) event.data.scalar.value); + return NULL; + } + } + else if (event.type == YAML_MAPPING_END_EVENT) { + if (indexes_val == -1 || + mincol_val == -1 || + name_str == NULL || + oid_str == NULL || + query_str == NULL) { + snmp_log(LOG_ERR, "Error reading query %d (%s): %s%s%s%s%s\n", + query_count, + name_str == NULL ? "Name Unknown" : name_str, + name_str == NULL ? "Name not specified" : "", + oid_str == NULL ? "OID not specified" : "", + query_str == NULL ? "Query not specified" : "", + indexes_val == -1 ? "Indexes not specified" : "", + mincol_val == -1 ? "Min column not specified" : ""); + return NULL; + } + + oid_arr = parse_oid(oid_str, &oid_len); + + newquery = alloc_custom_query(name_str, query_str, oid_arr, oid_len); + newquery->num_indexes = indexes_val; + newquery->min_colnum = mincol_val; + newquery->types = types; + newquery->typeslen = typeslen; + + if (head == NULL) { + head = newquery; + cur = head; + } + else { + cur->next = newquery; + cur = newquery; + } + } + else if (event.type == YAML_SEQUENCE_END_EVENT) + st = INIT; + break; + case NAME_VALUE: + if (event.type == YAML_SCALAR_EVENT) { + name_str = strdup((char *)event.data.scalar.value); + st = READ_QUERY; + } + else { + snmp_log(LOG_ERR, "Unexpected YAML event trying to read name of query %d\n", query_count); + return NULL; + } + break; + case QUERY_VALUE: + if (event.type == YAML_SCALAR_EVENT) { + query_str = strdup((char *)event.data.scalar.value); + st = READ_QUERY; + } + else { + snmp_log(LOG_ERR,"Unexpected YAML event trying to read query string of query %d\n", query_count); + return NULL; + } + break; + case OID_VALUE: + if (event.type == YAML_SCALAR_EVENT) { + oid_str = strdup((char *)event.data.scalar.value); + st = READ_QUERY; + } + else { + snmp_log(LOG_ERR, "Unexpected YAML event trying to read OID of query %d\n", query_count); + return NULL; + } + break; + case INDEXES_VALUE: + if (event.type == YAML_SCALAR_EVENT) { + indexes_val = atoi((char *)event.data.scalar.value); + st = READ_QUERY; + } + else { + snmp_log(LOG_ERR, "Unexpected YAML event trying to read indexes of query %d\n", query_count); + return NULL; + } + break; + case MINCOL_VALUE: + if (event.type == YAML_SCALAR_EVENT) { + mincol_val = atoi((char *)event.data.scalar.value); + st = READ_QUERY; + } + else { + snmp_log(LOG_ERR, "Unexpected YAML event trying to read min_column of query %d\n", query_count); + return NULL; + } + break; + case TYPES_VALUE: + if (event.type == YAML_SCALAR_EVENT) { + typecol = atoi((char *)event.data.scalar.value); + if (typecol < 1) + /* LOG_CRIT or higher? */ + snmp_log(LOG_ERR, "Invalid column number (must be > 0): %d\n", typecol); + st = TYPE_MAPPING_VALUE; + } + else if (event.type == YAML_SEQUENCE_END_EVENT) + st = READ_QUERY; + break; + case TYPE_MAPPING_VALUE: + st = TYPES_VALUE; + if (typeslen < typecol) { + types = realloc(types, sizeof(u_char *) * typecol); + if (types == NULL) { + /* Perhaps LOG_CRIT or higher? */ + snmp_log(LOG_ERR, "Couldn't allocate enough memory for column types\n"); + } + else { + init_types_array(types, typeslen, typecol); + if (typeslen != -1) + for (i = typeslen; i < typecol; i++) + types[i] = (u_char) 255; + typeslen = typecol; + } + } + types[typecol-1] = 255; + for (i = 0; i < snmp_type_map_len; i++) { + if (strcmp((char *) event.data.scalar.value, snmp_type_map[i].name) == 0) + types[typecol-1] = (u_char) snmp_type_map[i].value; + } + if (types[typecol-1] == 255) + snmp_log(LOG_ERR, "Couldn't understand SNMP type \"%s\"\n", (char *) event.data.scalar.value); + break; + } + yaml_event_delete(&event); + } + + if (error) + print_error(&parser); + + yaml_parser_delete(&parser); + fclose(inputfile); + + + + /* Print out results + cur = head; + while (cur != NULL) { + printf("Query:\n\tname: %s\n\tquery: %s\n\toid len: %d\n\tindexes: %d\n\tmin_col: %d\n", + cur->table_name, + cur->query_text, + cur->oid_len, + cur->num_indexes, + cur->min_colnum); + printf("\tOID: "); + done = 0; + while (done < cur->oid_len) + printf(".%u", (u_int) cur->table_oid[done++]); + printf("\n"); + cur = cur->next; + } + */ + return head; +} + +void print_error(yaml_parser_t *parser) { + snmp_log(LOG_ERR, "YAML parse error: %s at offset %d, value %d, context \"%s\"\n", + parser->problem, parser->problem_offset, parser->problem_value, parser->context); + + snmp_log(LOG_ERR, "Problem mark: index %d, line %d, column %d\n", + parser->problem_mark.index, parser->problem_mark.line, parser->problem_mark.column); + snmp_log(LOG_ERR, "Context marK: index %d, line %d, column %d\n", + parser->context_mark.index, parser->context_mark.line, parser->context_mark.column); + + switch (parser->error) { + case YAML_NO_ERROR: + snmp_log(LOG_ERR, "\tYAML_NO_ERROR\n"); + break; + case YAML_MEMORY_ERROR: + snmp_log(LOG_ERR, "\tYAML_MEMORY_ERROR\n"); + break; + case YAML_READER_ERROR: + snmp_log(LOG_ERR, "\tYAML_READER_ERROR\n"); + break; + case YAML_SCANNER_ERROR: + snmp_log(LOG_ERR, "\tYAML_SCANNER_ERROR\n"); + break; + case YAML_PARSER_ERROR: + snmp_log(LOG_ERR, "\tYAML_PARSER_ERROR\n"); + break; + case YAML_COMPOSER_ERROR: + snmp_log(LOG_ERR, "\tYAML_COMPOSER_ERROR\n"); + break; + case YAML_WRITER_ERROR: + snmp_log(LOG_ERR, "\tYAML_WRITER_ERROR\n"); + break; + case YAML_EMITTER_ERROR: + snmp_log(LOG_ERR, "\tYAML_EMITTER_ERROR\n"); + break; + } +} |