X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Flibcollectdclient%2Fclient.c;h=63d4e9d7cd75bf9d6a7652d7241559183fa98e39;hb=633c3966f770e4d46651a2fe219a18d8a9907a9f;hp=684fa39baabc8afb5069cb2616eea26bdefcc2c5;hpb=3f391479bfc45d0ff6e0c7b87c899e41a192f392;p=collectd.git diff --git a/src/libcollectdclient/client.c b/src/libcollectdclient/client.c index 684fa39b..20015be9 100644 --- a/src/libcollectdclient/client.c +++ b/src/libcollectdclient/client.c @@ -1,58 +1,38 @@ /** * libcollectdclient - src/libcollectdclient/client.c - * Copyright (C) 2008 Florian octo Forster + * Copyright (C) 2008-2012 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 - * Free Software Foundation; only version 2 of the License is applicable. + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: * - * 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. + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. * - * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. * * Authors: - * Florian octo Forster + * Florian octo Forster **/ -/* Set to C99 and POSIX code */ -#ifndef _ISOC99_SOURCE -# define _ISOC99_SOURCE -#endif -#ifndef _POSIX_SOURCE -# define _POSIX_SOURCE -#endif -#ifndef _POSIX_C_SOURCE -# define _POSIX_C_SOURCE 200112L -#endif -#ifndef _REENTRANT -# define _REENTRANT -#endif - -/* Disable non-standard extensions */ -#ifdef _BSD_SOURCE -# undef _BSD_SOURCE -#endif -#ifdef _SVID_SOURCE -# undef _SVID_SOURCE -#endif -#ifdef _GNU_SOURCE -# undef _GNU_SOURCE +#if HAVE_CONFIG_H +# include "config.h" #endif #if !defined(__GNUC__) || !__GNUC__ # define __attribute__(x) /**/ #endif -#if HAVE_CONFIG_H -# include "config.h" -#endif - -#include "lcc_features.h" +#include "collectd/lcc_features.h" #include #include @@ -66,7 +46,7 @@ #include #include -#include "client.h" +#include "collectd/client.h" /* NI_MAXHOST has been obsoleted by RFC 3493 which is a reason for SunOS 5.11 * to no longer define it. We'll use the old, RFC 2553 value here. */ @@ -74,6 +54,15 @@ # define NI_MAXHOST 1025 #endif +/* OpenBSD doesn't have EPROTO, FreeBSD doesn't have EILSEQ. Oh what joy! */ +#ifndef EILSEQ +# ifdef EPROTO +# define EILSEQ EPROTO +# else +# define EILSEQ EINVAL +# endif +#endif + /* Secure/static macros. They work like `strcpy' and `strcat', but assure null * termination. They work for static buffers only, because they use `sizeof'. * The `SSTRCATF' combines the functionality of `snprintf' and `strcat' which @@ -95,7 +84,7 @@ _b[sizeof (_b) - 1] = 0; \ SSTRCAT ((d), _b); \ } while (0) - + #define LCC_SET_ERRSTR(c, ...) do { \ snprintf ((c)->errbuf, sizeof ((c)->errbuf), __VA_ARGS__); \ @@ -129,38 +118,65 @@ typedef struct lcc_response_s lcc_response_t; /* * Private functions */ +/* Even though Posix requires "strerror_r" to return an "int", + * some systems (e.g. the GNU libc) return a "char *" _and_ + * ignore the second argument ... -tokkee */ +static char *sstrerror (int errnum, char *buf, size_t buflen) +{ + buf[0] = 0; + +#if !HAVE_STRERROR_R + snprintf (buf, buflen, "Error #%i; strerror_r is not available.", errnum); +/* #endif !HAVE_STRERROR_R */ + +#elif STRERROR_R_CHAR_P + { + char *temp; + temp = strerror_r (errnum, buf, buflen); + if (buf[0] == 0) + { + if ((temp != NULL) && (temp != buf) && (temp[0] != 0)) + strncpy (buf, temp, buflen); + else + strncpy (buf, "strerror_r did not return " + "an error message", buflen); + } + } +/* #endif STRERROR_R_CHAR_P */ + +#else + if (strerror_r (errnum, buf, buflen) != 0) + { + snprintf (buf, buflen, "Error #%i; " + "Additionally, strerror_r failed.", + errnum); + } +#endif /* STRERROR_R_CHAR_P */ + + buf[buflen - 1] = 0; + + return (buf); +} /* char *sstrerror */ + static int lcc_set_errno (lcc_connection_t *c, int err) /* {{{ */ { if (c == NULL) return (-1); - strerror_r (err, c->errbuf, sizeof (c->errbuf)); + sstrerror (err, c->errbuf, sizeof (c->errbuf)); c->errbuf[sizeof (c->errbuf) - 1] = 0; return (0); } /* }}} int lcc_set_errno */ -/* lcc_strdup: Since `strdup' is an XSI extension, we provide our own version - * here. */ -__attribute__((malloc, nonnull (1))) -static char *lcc_strdup (const char *str) /* {{{ */ -{ - size_t strsize; - char *ret; - - strsize = strlen (str) + 1; - ret = (char *) malloc (strsize); - if (ret != NULL) - memcpy (ret, str, strsize); - return (ret); -} /* }}} char *lcc_strdup */ - -__attribute__((nonnull (1, 2))) static char *lcc_strescape (char *dest, const char *src, size_t dest_size) /* {{{ */ { size_t dest_pos; size_t src_pos; + if ((dest == NULL) || (src == NULL)) + return (NULL); + dest_pos = 0; src_pos = 0; @@ -314,7 +330,7 @@ static int lcc_receive (lcc_connection_t *c, /* {{{ */ lcc_chomp (buffer); LCC_DEBUG ("receive: <-- %s\n", buffer); - res.lines[i] = lcc_strdup (buffer); + res.lines[i] = strdup (buffer); if (res.lines[i] == NULL) { lcc_set_errno (c, ENOMEM); @@ -709,7 +725,7 @@ int lcc_getval (lcc_connection_t *c, lcc_identifier_t *ident, /* {{{ */ if (values_names != NULL) { - values_names[i] = lcc_strdup (key); + values_names[i] = strdup (key); if (values_names[i] == NULL) BAIL_OUT (ENOMEM); } @@ -722,6 +738,8 @@ int lcc_getval (lcc_connection_t *c, lcc_identifier_t *ident, /* {{{ */ if (ret_values_names != NULL) *ret_values_names = values_names; + lcc_response_free (&res); + return (0); } /* }}} int lcc_getval */ @@ -749,13 +767,13 @@ int lcc_putval (lcc_connection_t *c, const lcc_value_list_t *vl) /* {{{ */ SSTRCATF (command, "PUTVAL %s", lcc_strescape (ident_esc, ident_str, sizeof (ident_esc))); - if (vl->interval > 0) - SSTRCATF (command, " interval=%i", vl->interval); + if (vl->interval > 0.0) + SSTRCATF (command, " interval=%.3f", vl->interval); - if (vl->time > 0) - SSTRCATF (command, "%u", (unsigned int) vl->time); + if (vl->time > 0.0) + SSTRCATF (command, " %.3f", vl->time); else - SSTRCAT (command, "N"); + SSTRCAT (command, " N"); for (i = 0; i < vl->values_len; i++) { @@ -764,10 +782,15 @@ int lcc_putval (lcc_connection_t *c, const lcc_value_list_t *vl) /* {{{ */ else if (vl->values_types[i] == LCC_TYPE_GAUGE) { if (isnan (vl->values[i].gauge)) - SSTRCPY (command, ":U"); + SSTRCATF (command, ":U"); else SSTRCATF (command, ":%g", vl->values[i].gauge); } + else if (vl->values_types[i] == LCC_TYPE_DERIVE) + SSTRCATF (command, ":%"PRIu64, vl->values[i].derive); + else if (vl->values_types[i] == LCC_TYPE_ABSOLUTE) + SSTRCATF (command, ":%"PRIu64, vl->values[i].absolute); + } /* for (i = 0; i < vl->values_len; i++) */ status = lcc_sendreceive (c, command, &res); @@ -984,7 +1007,7 @@ int lcc_string_to_identifier (lcc_connection_t *c, /* {{{ */ char *type; char *type_instance; - string_copy = lcc_strdup (string); + string_copy = strdup (string); if (string_copy == NULL) { lcc_set_errno (c, ENOMEM); @@ -1040,4 +1063,47 @@ int lcc_string_to_identifier (lcc_connection_t *c, /* {{{ */ return (0); } /* }}} int lcc_string_to_identifier */ +int lcc_identifier_compare (const lcc_identifier_t *i0, /* {{{ */ + const lcc_identifier_t *i1) +{ + int status; + + if ((i0 == NULL) && (i1 == NULL)) + return (0); + else if (i0 == NULL) + return (-1); + else if (i1 == NULL) + return (1); + +#define CMP_FIELD(f) do { \ + status = strcmp (i0->f, i1->f); \ + if (status != 0) \ + return (status); \ +} while (0); + + CMP_FIELD (host); + CMP_FIELD (plugin); + CMP_FIELD (plugin_instance); + CMP_FIELD (type); + CMP_FIELD (type_instance); + +#undef CMP_FIELD + + return (0); +} /* }}} int lcc_identifier_compare */ + +int lcc_sort_identifiers (lcc_connection_t *c, /* {{{ */ + lcc_identifier_t *idents, size_t idents_num) +{ + if (idents == NULL) + { + lcc_set_errno (c, EINVAL); + return (-1); + } + + qsort (idents, idents_num, sizeof (*idents), + (void *) lcc_identifier_compare); + return (0); +} /* }}} int lcc_sort_identifiers */ + /* vim: set sw=2 sts=2 et fdm=marker : */