X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Futils_cmd_putval.c;h=b2537859163716c0450db8a7c11c65abfe86b02e;hb=f5fdf24ccec9318baf11eec25d6dba881dc77332;hp=bf3e2b6f2b9880cf50f6d602bf721ed42c51afb7;hpb=1bdfcf9791729310f75857d0e002c40ef659a89b;p=collectd.git diff --git a/src/utils_cmd_putval.c b/src/utils_cmd_putval.c index bf3e2b6f..b2537859 100644 --- a/src/utils_cmd_putval.c +++ b/src/utils_cmd_putval.c @@ -1,6 +1,7 @@ /** * collectd - src/utils_cmd_putval.c * Copyright (C) 2007-2009 Florian octo Forster + * Copyright (C) 2016 Sebastian tokkee Harl * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -22,6 +23,7 @@ * * Authors: * Florian octo Forster + * Sebastian tokkee Harl **/ #include "collectd.h" @@ -29,20 +31,14 @@ #include "common.h" #include "plugin.h" +#include "utils_cmds.h" +#include "utils_cmd_putval.h" #include "utils_parse_option.h" #include "utils_cmd_putval.h" -#define print_to_socket(fh, ...) \ - do { \ - if (fprintf (fh, __VA_ARGS__) < 0) { \ - char errbuf[1024]; \ - WARNING ("handle_putval: failed to write to socket #%i: %s", \ - fileno (fh), sstrerror (errno, errbuf, sizeof (errbuf))); \ - sfree (vl.values); \ - return -1; \ - } \ - fflush(fh); \ - } while (0) +/* + * private helper functions + */ static int set_option (value_list_t *vl, const char *key, const char *value) { @@ -66,11 +62,18 @@ static int set_option (value_list_t *vl, const char *key, const char *value) return (1); return (0); -} /* int parse_option */ +} /* int set_option */ + +/* + * public API + */ -int handle_putval (FILE *fh, char *buffer) +cmd_status_t cmd_parse_putval (size_t argc, char **argv, + cmd_putval_t *ret_putval, const cmd_options_t *opts, + cmd_error_handler_t *err) { - char *command; + cmd_status_t result; + char *identifier; char *hostname; char *plugin; @@ -78,56 +81,45 @@ int handle_putval (FILE *fh, char *buffer) char *type; char *type_instance; int status; - int values_submitted; char *identifier_copy; const data_set_t *ds; value_list_t vl = VALUE_LIST_INIT; - vl.values = NULL; - - DEBUG ("utils_cmd_putval: handle_putval (fh = %p, buffer = %s);", - (void *) fh, buffer); + size_t i; - command = NULL; - status = parse_string (&buffer, &command); - if (status != 0) + if ((ret_putval == NULL) || (opts == NULL)) { - print_to_socket (fh, "-1 Cannot parse command.\n"); - return (-1); + errno = EINVAL; + cmd_error (CMD_ERROR, err, "Invalid arguments to cmd_parse_putval."); + return (CMD_ERROR); } - assert (command != NULL); - if (strcasecmp ("PUTVAL", command) != 0) + if (argc < 2) { - print_to_socket (fh, "-1 Unexpected command: `%s'.\n", command); - return (-1); + cmd_error (CMD_PARSE_ERROR, err, + "Missing identifier and/or value-list."); + return (CMD_PARSE_ERROR); } - identifier = NULL; - status = parse_string (&buffer, &identifier); - if (status != 0) - { - print_to_socket (fh, "-1 Cannot parse identifier.\n"); - return (-1); - } - assert (identifier != NULL); + identifier = argv[0]; - /* parse_identifier() modifies its first argument, - * returning pointers into it */ + /* parse_identifier() modifies its first argument, returning pointers into + * it; retain the old value for later. */ identifier_copy = sstrdup (identifier); - status = parse_identifier (identifier_copy, &hostname, + status = parse_identifier (identifier, &hostname, &plugin, &plugin_instance, - &type, &type_instance); + &type, &type_instance, + opts->identifier_default_host); if (status != 0) { - DEBUG ("handle_putval: Cannot parse identifier `%s'.", - identifier); - print_to_socket (fh, "-1 Cannot parse identifier `%s'.\n", - identifier); + DEBUG ("cmd_handle_putval: Cannot parse identifier `%s'.", + identifier_copy); + cmd_error (CMD_PARSE_ERROR, err, "Cannot parse identifier `%s'.", + identifier_copy); sfree (identifier_copy); - return (-1); + return (CMD_PARSE_ERROR); } if ((strlen (hostname) >= sizeof (vl.host)) @@ -137,9 +129,9 @@ int handle_putval (FILE *fh, char *buffer) || ((type_instance != NULL) && (strlen (type_instance) >= sizeof (vl.type_instance)))) { - print_to_socket (fh, "-1 Identifier too long.\n"); + cmd_error (CMD_PARSE_ERROR, err, "Identifier too long."); sfree (identifier_copy); - return (-1); + return (CMD_PARSE_ERROR); } sstrncpy (vl.host, hostname, sizeof (vl.host)); @@ -151,84 +143,151 @@ int handle_putval (FILE *fh, char *buffer) sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance)); ds = plugin_get_ds (type); - if (ds == NULL) { - print_to_socket (fh, "-1 Type `%s' isn't defined.\n", type); + if (ds == NULL) + { + cmd_error (CMD_PARSE_ERROR, err, "1 Type `%s' isn't defined.", type); sfree (identifier_copy); - return (-1); + return (CMD_PARSE_ERROR); } - /* Free identifier_copy */ hostname = NULL; plugin = NULL; plugin_instance = NULL; type = NULL; type_instance = NULL; - sfree (identifier_copy); vl.values_len = ds->ds_num; vl.values = malloc (vl.values_len * sizeof (*vl.values)); if (vl.values == NULL) { - print_to_socket (fh, "-1 malloc failed.\n"); - return (-1); + cmd_error (CMD_ERROR, err, "malloc failed."); + sfree (identifier_copy); + return (CMD_ERROR); } - /* All the remaining fields are part of the optionlist. */ - values_submitted = 0; - while (*buffer != 0) + ret_putval->raw_identifier = identifier_copy; + if (ret_putval->raw_identifier == NULL) { - char *string = NULL; - char *value = NULL; + cmd_error (CMD_ERROR, err, "malloc failed."); + cmd_destroy_putval (ret_putval); + sfree (vl.values); + return (CMD_ERROR); + } - status = parse_option (&buffer, &string, &value); - if (status < 0) - { - /* parse_option failed, buffer has been modified. - * => we need to abort */ - print_to_socket (fh, "-1 Misformatted option.\n"); - sfree (vl.values); - return (-1); - } - else if (status == 0) + /* All the remaining fields are part of the option list. */ + result = CMD_OK; + for (i = 1; i < argc; ++i) + { + value_list_t *tmp; + + char *key = NULL; + char *value = NULL; + + status = cmd_parse_option (argv[i], &key, &value, err); + if (status == CMD_OK) { - assert (string != NULL); + assert (key != NULL); assert (value != NULL); - set_option (&vl, string, value); + set_option (&vl, key, value); continue; } - /* else: parse_option but buffer has not been modified. This is - * the default if no `=' is found.. */ + else if (status != CMD_NO_OPTION) + { + /* parse_option failed, buffer has been modified. + * => we need to abort */ + result = status; + break; + } + /* else: cmd_parse_option did not find an option; treat this as a + * value list. */ - status = parse_string (&buffer, &string); + status = parse_values (argv[i], &vl, ds); if (status != 0) { - print_to_socket (fh, "-1 Misformatted value.\n"); - sfree (vl.values); - return (-1); + cmd_error (CMD_PARSE_ERROR, err, "Parsing the values string failed."); + result = CMD_PARSE_ERROR; + break; } - assert (string != NULL); - status = parse_values (string, &vl, ds); - if (status != 0) + tmp = (value_list_t *) realloc (ret_putval->vl, + (ret_putval->vl_num + 1) * sizeof(*ret_putval->vl)); + if (tmp == NULL) { - print_to_socket (fh, "-1 Parsing the values string failed.\n"); - sfree (vl.values); - return (-1); + cmd_error (CMD_ERROR, err, "realloc failed."); + cmd_destroy_putval (ret_putval); + result = CMD_ERROR; + break; } - plugin_dispatch_values (&vl); - values_submitted++; + ret_putval->vl = tmp; + ret_putval->vl_num++; + memcpy (&ret_putval->vl[ret_putval->vl_num - 1], &vl, sizeof (vl)); } /* while (*buffer != 0) */ /* Done parsing the options. */ - if (fh!=stdout) - print_to_socket (fh, "0 Success: %i %s been dispatched.\n", - values_submitted, - (values_submitted == 1) ? "value has" : "values have"); + if (result != CMD_OK) + { + if (ret_putval->vl_num == 0) + sfree (vl.values); + cmd_destroy_putval (ret_putval); + } - sfree (vl.values); - return (0); -} /* int handle_putval */ + return (result); +} /* cmd_status_t cmd_parse_putval */ + +void cmd_destroy_putval (cmd_putval_t *putval) +{ + size_t i; + + if (putval == NULL) + return; + + sfree (putval->raw_identifier); + + for (i = 0; i < putval->vl_num; ++i) + { + if (i == 0) /* values is shared between all entries */ + sfree (putval->vl[i].values); + meta_data_destroy (putval->vl[i].meta); + putval->vl[i].meta = NULL; + } + sfree (putval->vl); + putval->vl = NULL; + putval->vl_num = 0; +} /* void cmd_destroy_putval */ + +cmd_status_t cmd_handle_putval (FILE *fh, char *buffer) +{ + cmd_error_handler_t err = { cmd_error_fh, fh }; + cmd_t cmd; + size_t i; + + int status; + + DEBUG ("utils_cmd_putval: cmd_handle_putval (fh = %p, buffer = %s);", + (void *) fh, buffer); + + if ((status = cmd_parse (buffer, &cmd, NULL, &err)) != CMD_OK) + return (status); + if (cmd.type != CMD_PUTVAL) + { + cmd_error (CMD_UNKNOWN_COMMAND, &err, "Unexpected command: `%s'.", + CMD_TO_STRING (cmd.type)); + cmd_destroy (&cmd); + return (CMD_UNKNOWN_COMMAND); + } + + for (i = 0; i < cmd.cmd.putval.vl_num; ++i) + plugin_dispatch_values (&cmd.cmd.putval.vl[i]); + + if (fh != stdout) + cmd_error (CMD_OK, &err, "Success: %i %s been dispatched.", + (int)cmd.cmd.putval.vl_num, + (cmd.cmd.putval.vl_num == 1) ? "value has" : "values have"); + + cmd_destroy (&cmd); + return (CMD_OK); +} /* int cmd_handle_putval */ -int create_putval (char *ret, size_t ret_len, /* {{{ */ +int cmd_create_putval (char *ret, size_t ret_len, /* {{{ */ const data_set_t *ds, const value_list_t *vl) { char buffer_ident[6 * DATA_MAX_NAME_LEN]; @@ -255,4 +314,4 @@ int create_putval (char *ret, size_t ret_len, /* {{{ */ buffer_values); return (0); -} /* }}} int create_putval */ +} /* }}} int cmd_create_putval */