X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fcommon.c;h=c6a651dc56248050ccc0b7a50c7aca68e4f2c3f9;hb=902f7621661d97dac0c7bc83f39acbf76a3b947b;hp=b654719b6b94194644f328c6a0a318006222240e;hpb=6e419a825c50f9c97471aba7d50521bfc7e19828;p=collectd.git diff --git a/src/common.c b/src/common.c index b654719b..c6a651dc 100644 --- a/src/common.c +++ b/src/common.c @@ -1,6 +1,6 @@ /** * collectd - src/common.c - * Copyright (C) 2005-2008 Florian octo Forster + * Copyright (C) 2005-2009 Florian octo Forster * * 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 @@ -43,6 +43,15 @@ # include #endif +/* for getaddrinfo */ +#include +#include +#include + +#if HAVE_NETINET_IN_H +# include +#endif + #ifdef HAVE_LIBKSTAT extern kstat_ctl_t *kc; #endif @@ -253,7 +262,7 @@ int strsplit (char *string, char **fields, size_t size) break; } - return (i); + return ((int) i); } int strjoin (char *dst, size_t dst_len, @@ -317,6 +326,40 @@ int strsubstitute (char *str, char c_from, char c_to) return (ret); } /* int strsubstitute */ +int strunescape (char *buf, size_t buf_len) +{ + size_t i; + + for (i = 0; (i < buf_len) && (buf[i] != '\0'); ++i) + { + if (buf[i] != '\\') + continue; + + if ((i >= buf_len) || (buf[i + 1] == '\0')) { + ERROR ("string unescape: backslash found at end of string."); + return (-1); + } + + switch (buf[i + 1]) { + case 't': + buf[i] = '\t'; + break; + case 'n': + buf[i] = '\n'; + break; + case 'r': + buf[i] = '\r'; + break; + default: + buf[i] = buf[i + 1]; + break; + } + + memmove (buf + i + 1, buf + i + 2, buf_len - i - 2); + } + return (0); +} /* int strunescape */ + int escape_slashes (char *buf, int buf_len) { int i; @@ -349,6 +392,19 @@ int escape_slashes (char *buf, int buf_len) return (0); } /* int escape_slashes */ +void replace_special (char *buffer, size_t buffer_size) +{ + size_t i; + + for (i = 0; i < buffer_size; i++) + { + if (buffer[i] == 0) + return; + if ((!isalnum ((int) buffer[i])) && (buffer[i] != '-')) + buffer[i] = '_'; + } +} /* void replace_special */ + int timeval_cmp (struct timeval tv0, struct timeval tv1, struct timeval *delta) { struct timeval *larger; @@ -531,26 +587,26 @@ int check_create_dir (const char *file_orig) int get_kstat (kstat_t **ksp_ptr, char *module, int instance, char *name) { char ident[128]; + + *ksp_ptr = NULL; if (kc == NULL) return (-1); ssnprintf (ident, sizeof (ident), "%s,%i,%s", module, instance, name); + *ksp_ptr = kstat_lookup (kc, module, instance, name); if (*ksp_ptr == NULL) { - if ((*ksp_ptr = kstat_lookup (kc, module, instance, name)) == NULL) - { - ERROR ("Cound not find kstat %s", ident); - return (-1); - } + ERROR ("get_kstat: Cound not find kstat %s", ident); + return (-1); + } - if ((*ksp_ptr)->ks_type != KSTAT_TYPE_NAMED) - { - WARNING ("kstat %s has wrong type", ident); - *ksp_ptr = NULL; - return (-1); - } + if ((*ksp_ptr)->ks_type != KSTAT_TYPE_NAMED) + { + ERROR ("get_kstat: kstat %s has wrong type", ident); + *ksp_ptr = NULL; + return (-1); } #ifdef assert @@ -560,13 +616,13 @@ int get_kstat (kstat_t **ksp_ptr, char *module, int instance, char *name) if (kstat_read (kc, *ksp_ptr, NULL) == -1) { - WARNING ("kstat %s could not be read", ident); + ERROR ("get_kstat: kstat %s could not be read", ident); return (-1); } if ((*ksp_ptr)->ks_type != KSTAT_TYPE_NAMED) { - WARNING ("kstat %s has wrong type", ident); + ERROR ("get_kstat: kstat %s has wrong type", ident); return (-1); } @@ -790,6 +846,43 @@ int parse_identifier (char *str, char **ret_host, return (0); } /* int parse_identifier */ +int parse_value (const char *value, value_t *ret_value, int ds_type) +{ + char *endptr = NULL; + + switch (ds_type) + { + case DS_TYPE_COUNTER: + ret_value->counter = (counter_t) strtoull (value, &endptr, 0); + break; + + case DS_TYPE_GAUGE: + ret_value->gauge = (gauge_t) strtod (value, &endptr); + break; + + case DS_TYPE_DERIVE: + ret_value->counter = (derive_t) strtoll (value, &endptr, 0); + break; + + case DS_TYPE_ABSOLUTE: + ret_value->counter = (absolute_t) strtoull (value, &endptr, 0); + break; + + default: + ERROR ("parse_value: Invalid data source type: %i.", ds_type); + return -1; + } + + if (value == endptr) { + ERROR ("parse_value: Failed to parse string as number: %s.", value); + return -1; + } + else if ((NULL != endptr) && ('\0' != *endptr)) + WARNING ("parse_value: Ignoring trailing garbage after number: %s.", + endptr); + return 0; +} /* int parse_value */ + int parse_values (char *buffer, value_list_t *vl, const data_set_t *ds) { int i; @@ -805,7 +898,11 @@ int parse_values (char *buffer, value_list_t *vl, const data_set_t *ds) dummy = NULL; if (i >= vl->values_len) + { + /* Make sure i is invalid. */ + i = vl->values_len + 1; break; + } if (i == -1) { @@ -816,12 +913,10 @@ int parse_values (char *buffer, value_list_t *vl, const data_set_t *ds) } else { - if (strcmp ("U", ptr) == 0) + if ((strcmp ("U", ptr) == 0) && (ds->ds[i].type == DS_TYPE_GAUGE)) vl->values[i].gauge = NAN; - else if (ds->ds[i].type == DS_TYPE_COUNTER) - vl->values[i].counter = atoll (ptr); - else if (ds->ds[i].type == DS_TYPE_GAUGE) - vl->values[i].gauge = atof (ptr); + else if (0 != parse_value (ptr, &vl->values[i], ds->ds[i].type)) + return -1; } i++; @@ -985,3 +1080,56 @@ counter_t counter_diff (counter_t old_value, counter_t new_value) return (diff); } /* counter_t counter_to_gauge */ + +int service_name_to_port_number (const char *service_name) +{ + struct addrinfo *ai_list; + struct addrinfo *ai_ptr; + struct addrinfo ai_hints; + int status; + int service_number; + + if (service_name == NULL) + return (-1); + + ai_list = NULL; + memset (&ai_hints, 0, sizeof (ai_hints)); + ai_hints.ai_family = AF_UNSPEC; + + status = getaddrinfo (/* node = */ NULL, service_name, + &ai_hints, &ai_list); + if (status != 0) + { + ERROR ("service_name_to_port_number: getaddrinfo failed: %s", + gai_strerror (status)); + return (-1); + } + + service_number = -1; + for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) + { + if (ai_ptr->ai_family == AF_INET) + { + struct sockaddr_in *sa; + + sa = (void *) ai_ptr->ai_addr; + service_number = (int) ntohs (sa->sin_port); + } + else if (ai_ptr->ai_family == AF_INET6) + { + struct sockaddr_in6 *sa; + + sa = (void *) ai_ptr->ai_addr; + service_number = (int) ntohs (sa->sin6_port); + } + + if ((service_number > 0) && (service_number <= 65535)) + break; + } + + freeaddrinfo (ai_list); + + if ((service_number > 0) && (service_number <= 65535)) + return (service_number); + return (-1); +} /* int service_name_to_port_number */