int lcc_putval (lcc_connection_t *c, const lcc_value_list_t *vl) /* {{{ */ { char ident_str[6 * LCC_NAME_LEN]; char ident_esc[12 * LCC_NAME_LEN]; char command[1024] = ""; lcc_response_t res; int status; size_t i; if ((c == NULL) || (vl == NULL) || (vl->values_len < 1) || (vl->values == NULL) || (vl->values_types == NULL)) { lcc_set_errno (c, EINVAL); return (-1); } status = lcc_identifier_to_string (c, ident_str, sizeof (ident_str), &vl->identifier); if (status != 0) return (status); 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->time > 0) SSTRCATF (command, "%u", (unsigned int) vl->time); else SSTRCAT (command, "N"); for (i = 0; i < vl->values_len; i++) { if (vl->values_types[i] == LCC_TYPE_COUNTER) SSTRCATF (command, ":%"PRIu64, vl->values[i].counter); else if (vl->values_types[i] == LCC_TYPE_GAUGE) { if (isnan (vl->values[i].gauge)) SSTRCPY (command, ":U"); else SSTRCATF (command, ":%g", vl->values[i].gauge); } } /* for (i = 0; i < vl->values_len; i++) */ status = lcc_sendreceive (c, command, &res); if (status != 0) return (status); if (res.status != 0) { LCC_SET_ERRSTR (c, "Server error: %s", res.message); lcc_response_free (&res); return (-1); } lcc_response_free (&res); return (0); } /* }}} int lcc_putval */
int lcc_flush (lcc_connection_t *c, const char *plugin, /* {{{ */ lcc_identifier_t *ident, int timeout) { char command[1024] = ""; lcc_response_t res; int status; if (c == NULL) { lcc_set_errno (c, EINVAL); return (-1); } SSTRCPY (command, "FLUSH"); if (timeout > 0) SSTRCATF (command, " timeout=%i", timeout); if (plugin != NULL) { char buffer[2 * LCC_NAME_LEN]; SSTRCATF (command, " plugin=%s", lcc_strescape (buffer, plugin, sizeof (buffer))); } if (ident != NULL) { char ident_str[6 * LCC_NAME_LEN]; char ident_esc[12 * LCC_NAME_LEN]; status = lcc_identifier_to_string (c, ident_str, sizeof (ident_str), ident); if (status != 0) return (status); SSTRCATF (command, " identifier=%s", lcc_strescape (ident_esc, ident_str, sizeof (ident_esc))); } status = lcc_sendreceive (c, command, &res); if (status != 0) return (status); if (res.status != 0) { LCC_SET_ERRSTR (c, "Server error: %s", res.message); lcc_response_free (&res); return (-1); } lcc_response_free (&res); return (0); } /* }}} int lcc_flush */
int lcc_string_to_identifier (lcc_connection_t *c, /* {{{ */ lcc_identifier_t *ident, const char *string) { char *string_copy; char *host; char *plugin; char *plugin_instance; char *type; char *type_instance; string_copy = strdup (string); if (string_copy == NULL) { lcc_set_errno (c, ENOMEM); return (-1); } host = string_copy; plugin = strchr (host, '/'); if (plugin == NULL) { LCC_SET_ERRSTR (c, "Malformed identifier string: %s", string); free (string_copy); return (-1); } *plugin = 0; plugin++; type = strchr (plugin, '/'); if (type == NULL) { LCC_SET_ERRSTR (c, "Malformed identifier string: %s", string); free (string_copy); return (-1); } *type = 0; type++; plugin_instance = strchr (plugin, '-'); if (plugin_instance != NULL) { *plugin_instance = 0; plugin_instance++; } type_instance = strchr (type, '-'); if (type_instance != NULL) { *type_instance = 0; type_instance++; } memset (ident, 0, sizeof (*ident)); SSTRCPY (ident->host, host); SSTRCPY (ident->plugin, plugin); if (plugin_instance != NULL) SSTRCPY (ident->plugin_instance, plugin_instance); SSTRCPY (ident->type, type); if (type_instance != NULL) SSTRCPY (ident->type_instance, type_instance); free (string_copy); return (0); } /* }}} int lcc_string_to_identifier */
int lcc_listval (lcc_connection_t *c, /* {{{ */ lcc_identifier_t **ret_ident, size_t *ret_ident_num) { lcc_response_t res; size_t i; int status; lcc_identifier_t *ident; size_t ident_num; if (c == NULL) return (-1); if ((ret_ident == NULL) || (ret_ident_num == NULL)) { lcc_set_errno (c, EINVAL); return (-1); } status = lcc_sendreceive (c, "LISTVAL", &res); if (status != 0) return (status); if (res.status != 0) { LCC_SET_ERRSTR (c, "Server error: %s", res.message); lcc_response_free (&res); return (-1); } ident_num = res.lines_num; ident = (lcc_identifier_t *) malloc (ident_num * sizeof (*ident)); if (ident == NULL) { lcc_response_free (&res); lcc_set_errno (c, ENOMEM); return (-1); } for (i = 0; i < res.lines_num; i++) { char *time_str; char *ident_str; /* First field is the time. */ time_str = res.lines[i]; /* Set `ident_str' to the beginning of the second field. */ ident_str = time_str; while ((*ident_str != ' ') && (*ident_str != '\t') && (*ident_str != 0)) ident_str++; while ((*ident_str == ' ') || (*ident_str == '\t')) { *ident_str = 0; ident_str++; } if (*ident_str == 0) { lcc_set_errno (c, EILSEQ); status = -1; break; } status = lcc_string_to_identifier (c, ident + i, ident_str); if (status != 0) break; } lcc_response_free (&res); if (status != 0) { free (ident); return (-1); } *ret_ident = ident; *ret_ident_num = ident_num; return (0); } /* }}} int lcc_listval */
int lcc_getval (lcc_connection_t *c, lcc_identifier_t *ident, /* {{{ */ size_t *ret_values_num, gauge_t **ret_values, char ***ret_values_names) { char ident_str[6 * LCC_NAME_LEN]; char ident_esc[12 * LCC_NAME_LEN]; char command[14 * LCC_NAME_LEN]; lcc_response_t res; size_t values_num; gauge_t *values = NULL; char **values_names = NULL; size_t i; int status; if (c == NULL) return (-1); if (ident == NULL) { lcc_set_errno (c, EINVAL); return (-1); } /* Build a commend with an escaped version of the identifier string. */ status = lcc_identifier_to_string (c, ident_str, sizeof (ident_str), ident); if (status != 0) return (status); snprintf (command, sizeof (command), "GETVAL %s", lcc_strescape (ident_esc, ident_str, sizeof (ident_esc))); command[sizeof (command) - 1] = 0; /* Send talk to the daemon.. */ status = lcc_sendreceive (c, command, &res); if (status != 0) return (status); if (res.status != 0) { LCC_SET_ERRSTR (c, "Server error: %s", res.message); lcc_response_free (&res); return (-1); } values_num = res.lines_num; #define BAIL_OUT(e) do { \ lcc_set_errno (c, (e)); \ free (values); \ if (values_names != NULL) { \ for (i = 0; i < values_num; i++) { \ free (values_names[i]); \ } \ } \ free (values_names); \ lcc_response_free (&res); \ return (-1); \ } while (0) /* If neither the values nor the names are requested, return here.. */ if ((ret_values == NULL) && (ret_values_names == NULL)) { if (ret_values_num != NULL) *ret_values_num = values_num; lcc_response_free (&res); return (0); } /* Allocate space for the values */ if (ret_values != NULL) { values = (gauge_t *) malloc (values_num * sizeof (*values)); if (values == NULL) BAIL_OUT (ENOMEM); } if (ret_values_names != NULL) { values_names = (char **) calloc (values_num, sizeof (*values_names)); if (values_names == NULL) BAIL_OUT (ENOMEM); } for (i = 0; i < res.lines_num; i++) { char *key; char *value; char *endptr; key = res.lines[i]; value = strchr (key, '='); if (value == NULL) BAIL_OUT (EILSEQ); *value = 0; value++; if (values != NULL) { endptr = NULL; errno = 0; values[i] = strtod (value, &endptr); if ((endptr == value) || (errno != 0)) BAIL_OUT (errno); } if (values_names != NULL) { values_names[i] = strdup (key); if (values_names[i] == NULL) BAIL_OUT (ENOMEM); } } /* for (i = 0; i < res.lines_num; i++) */ if (ret_values_num != NULL) *ret_values_num = values_num; if (ret_values != NULL) *ret_values = values; if (ret_values_names != NULL) *ret_values_names = values_names; lcc_response_free (&res); return (0); } /* }}} int lcc_getval */
static int lcc_open_netsocket (lcc_connection_t *c, /* {{{ */ const char *addr_orig) { struct addrinfo ai_hints; struct addrinfo *ai_res; struct addrinfo *ai_ptr; char addr_copy[NI_MAXHOST]; char *addr; char *port; int fd; int status; assert (c != NULL); assert (c->fh == NULL); assert (addr_orig != NULL); strncpy(addr_copy, addr_orig, sizeof(addr_copy)); addr_copy[sizeof(addr_copy) - 1] = '\0'; addr = addr_copy; memset (&ai_hints, 0, sizeof (ai_hints)); ai_hints.ai_flags = 0; #ifdef AI_ADDRCONFIG ai_hints.ai_flags |= AI_ADDRCONFIG; #endif ai_hints.ai_family = AF_UNSPEC; ai_hints.ai_socktype = SOCK_STREAM; port = NULL; if (*addr == '[') /* IPv6+port format */ { /* `addr' is something like "[2001:780:104:2:211:24ff:feab:26f8]:12345" */ addr++; port = strchr (addr, ']'); if (port == NULL) { LCC_SET_ERRSTR (c, "malformed address: %s", addr_orig); return (-1); } *port = 0; port++; if (*port == ':') port++; else if (*port == 0) port = NULL; else { LCC_SET_ERRSTR (c, "garbage after address: %s", port); return (-1); } } /* if (*addr = ']') */ else if (strchr (addr, '.') != NULL) /* Hostname or IPv4 */ { port = strrchr (addr, ':'); if (port != NULL) { *port = 0; port++; } } ai_res = NULL; status = getaddrinfo (addr, port == NULL ? LCC_DEFAULT_PORT : port, &ai_hints, &ai_res); if (status != 0) { LCC_SET_ERRSTR (c, "getaddrinfo: %s", gai_strerror (status)); return (-1); } for (ai_ptr = ai_res; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) { fd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol); if (fd < 0) { status = errno; continue; } status = connect (fd, ai_ptr->ai_addr, ai_ptr->ai_addrlen); if (status != 0) { status = errno; close (fd); continue; } c->fh = fdopen (fd, "r+"); if (c->fh == NULL) { status = errno; close (fd); continue; } assert (status == 0); break; } /* for (ai_ptr) */ if (status != 0) { lcc_set_errno (c, status); return (-1); } return (0); } /* }}} int lcc_open_netsocket */