123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542 |
- /*
- * Copyright (c) 2016 Pentair Technical Products. All right reserved
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Pentair Technical Products or the names of
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * PENTAIR TECHNICAL SOLUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
- #include <malloc.h>
- #include <string.h>
- #include <ipmitool/helper.h>
- #include <ipmitool/ipmi_cfgp.h>
- #include <ipmitool/log.h>
- /* ipmi_cfgp_init initialize configuration parameter context
- * @param ctx context to initialize
- * @param set array of parameter descriptors
- * @param count amount of descriptors supplied
- * @param handler function to do real job on parameters from the set
- * @param priv private data for the handler
- */
- int
- ipmi_cfgp_init(struct ipmi_cfgp_ctx *ctx, const struct ipmi_cfgp *set,
- unsigned int count, const char *cmdname,
- ipmi_cfgp_handler_t handler, void *priv)
- {
- if (ctx == NULL || set == NULL || handler == NULL || !cmdname) {
- return -1;
- }
- memset(ctx, 0, sizeof(struct ipmi_cfgp_ctx));
- ctx->set = set;
- ctx->count = count;
- ctx->cmdname = cmdname;
- ctx->handler = handler;
- ctx->priv = priv;
- return 0;
- }
- /* ipmi_cfgp_uninit destroy data list attached to context
- * @param ctx parameter context to clear
- * @returns 0 -- list destroyed
- * -1 -- ctx is NULL
- */
- int
- ipmi_cfgp_uninit(struct ipmi_cfgp_ctx *ctx)
- {
- struct ipmi_cfgp_data *d;
- if (ctx == NULL) {
- return -1;
- }
- while (ctx->v) {
- d = ctx->v;
- ctx->v = d->next;
- free(d);
- d = NULL;
- }
- return 0;
- }
- /* lookup_cfgp -- find a parameter in a set*/
- static const struct ipmi_cfgp *
- lookup_cfgp(const struct ipmi_cfgp_ctx *ctx, const char *name)
- {
- const struct ipmi_cfgp *p;
- int i;
- for (i = 0; i < ctx->count; i++) {
- p = &ctx->set[i];
- if (p->name && !strcasecmp(p->name, name)) {
- return p;
- }
- }
- return NULL;
- }
- /* ipmi_cfgp_parse_sel parse parameter selector
- * (parameter ID, set selector, block selector) from cmdline.
- *
- * @param ctx configuration parameter context to use
- * @param argc elements left in argv
- * @param argv array of arguments
- * @param sel where to store parsed selector
- *
- * @returns >=0 number of argv elements used
- * <0 error
- */
- int
- ipmi_cfgp_parse_sel(struct ipmi_cfgp_ctx *ctx,
- int argc, const char **argv, struct ipmi_cfgp_sel *sel)
- {
- const struct ipmi_cfgp *p;
- if (ctx == NULL || argv == NULL || sel == NULL) {
- return -1;
- }
- sel->param = -1;
- sel->set = -1;
- sel->block = -1;
- if (argc == 0) {
- /* no parameter specified, good for print, save */
- return 0;
- }
- p = lookup_cfgp(ctx, argv[0]);
- if (p == NULL) {
- lprintf(LOG_ERR, "invalid parameter");
- return -1;
- }
- sel->param = p - ctx->set;
- sel->set = p->is_set ? -1 : 0;
- sel->block = p->has_blocks ? -1 : 0;
- if (argc == 1 || !p->is_set) {
- /* No set and block selector applicable or specified */
- return 1;
- }
- if (str2int(argv[1], &sel->set)
- || sel->set < 0
- || (sel->set == 0 && p->first_set)) {
- lprintf(LOG_ERR, "invalid set selector");
- return -1;
- }
- if (argc == 2 || !p->has_blocks) {
- /* No block selector applicable or specified */
- return 2;
- }
- if (str2int(argv[2], &sel->block)
- || sel->block < 0
- || (sel->block == 0 && p->first_block)) {
- lprintf(LOG_ERR, "invalid block selector");
- return -1;
- }
- return 3;
- }
- /* cfgp_add_data adds block of data to list in the configuration
- * parameter context
- *
- * @param ctx context to add data to
- * @param data parameter data
- */
- static void
- cfgp_add_data(struct ipmi_cfgp_ctx *ctx, struct ipmi_cfgp_data *data)
- {
- struct ipmi_cfgp_data **pprev = &ctx->v;
- data->next = NULL;
- while (*pprev) {
- pprev = &(*pprev)->next;
- }
- *pprev = data;
- }
- /* cfgp_usage prints format for configuration parameter
- *
- * @param p configuration parameter descriptor
- * @param write 0 if no value is expected, !=0 otherwise
- */
- static void
- cfgp_usage(const struct ipmi_cfgp *p, int write)
- {
- if (p->name == NULL) {
- return;
- }
- if (write && p->format == NULL) {
- return;
- }
- printf(" %s%s%s %s\n",
- p->name, p->is_set ? " <set_sel>" : "",
- p->has_blocks ? " <block_sel>" : "",
- write ? p->format : "");
- }
- /* ipmi_cfgp_usage prints format for configuration parameter set
- *
- * @param set configuration parameter descriptor array
- * @param count number of elements in set
- * @param write 0 if no value is expected, !=0 otherwise
- */
- void
- ipmi_cfgp_usage(const struct ipmi_cfgp *set, int count, int write)
- {
- const struct ipmi_cfgp *p;
- int i;
- if (set == NULL) {
- return;
- }
- for (i = 0; i < count; i++) {
- p = &set[i];
- if (write && p->access == CFGP_RDONLY) {
- continue;
- }
- if (!write && p->access == CFGP_WRONLY) {
- continue;
- }
- cfgp_usage(p, write);
- }
- }
- /* ipmi_cfgp_parse_data parse parameter data from command line into context
- * @param ctx context to add data
- * @param sel parameter selector
- * @param argc number of elements in argv
- * @param argv array of unparsed arguments
- *
- * @returns 0 on success
- * <0 on error
- */
- int
- ipmi_cfgp_parse_data(struct ipmi_cfgp_ctx *ctx,
- const struct ipmi_cfgp_sel *sel, int argc, const char **argv)
- {
- const struct ipmi_cfgp *p;
- struct ipmi_cfgp_data *data;
- struct ipmi_cfgp_action action;
- if (ctx == NULL || sel == NULL || argv == NULL) {
- return -1;
- }
- if (sel->param == -1 || sel->param >= ctx->count) {
- lprintf(LOG_ERR, "invalid parameter, must be one of:");
- ipmi_cfgp_usage(ctx->set, ctx->count, 1);
- return -1;
- }
- if (sel->set == -1) {
- lprintf(LOG_ERR, "set selector is not specified");
- return -1;
- }
- if (sel->block == -1) {
- lprintf(LOG_ERR, "block selector is not specified");
- return -1;
- }
- p = &ctx->set[sel->param];
- if (p->size == 0) {
- return -1;
- }
- data = malloc(sizeof(struct ipmi_cfgp_data) + p->size);
- if (data == NULL) {
- return -1;
- }
- memset(data, 0, sizeof(struct ipmi_cfgp_data) + p->size);
- action.type = CFGP_PARSE;
- action.set = sel->set;
- action.block = sel->block;
- action.argc = argc;
- action.argv = argv;
- action.file = NULL;
- if (ctx->handler(ctx->priv, p, &action, data->data) != 0) {
- ipmi_cfgp_usage(p, 1, 1);
- free(data);
- data = NULL;
- return -1;
- }
- data->sel = *sel;
- cfgp_add_data(ctx, data);
- return 0;
- }
- /* cfgp_get_param -- get parameter data from MC into data list within context
- *
- * @param ctx context
- * @param p parameter descriptor
- * @param set parameter set selector, can be -1 to scan all set selectors
- * @param block parameter block selector, can be -1 to get all blocks
- * @param quiet set to non-zero to continue on errors
- * (required for -1 to work)
- * @returns 0 on success, non-zero otherwise
- */
- static int
- cfgp_get_param(struct ipmi_cfgp_ctx *ctx, const struct ipmi_cfgp *p,
- int set, int block, int quiet)
- {
- struct ipmi_cfgp_data *data;
- struct ipmi_cfgp_action action;
- int cset;
- int cblock;
- int ret;
- if (p->size == 0) {
- return -1;
- }
- action.type = CFGP_GET;
- action.argc = 0;
- action.argv = NULL;
- action.file = NULL;
- if (set == -1 && !p->is_set) {
- set = 0;
- }
- if (block == -1 && !p->has_blocks) {
- block = 0;
- }
- if (set == -1) {
- cset = p->first_set;
- } else {
- cset = set;
- }
- action.quiet = quiet;
- do {
- if (block == -1) {
- cblock = p->first_block;
- } else {
- cblock = block;
- }
- do {
- data = malloc(sizeof(struct ipmi_cfgp_data) + p->size);
- if (data == NULL) {
- return -1;
- }
- memset(data, 0, sizeof(struct ipmi_cfgp_data) + p->size);
- action.set = cset;
- action.block = cblock;
- ret = ctx->handler(ctx->priv, p, &action, data->data);
- if (ret != 0) {
- free(data);
- data = NULL;
- if (!action.quiet) {
- return ret;
- }
- break;
- }
- data->sel.param = p - ctx->set;
- data->sel.set = cset;
- data->sel.block = cblock;
- cfgp_add_data(ctx, data);
- cblock++;
- action.quiet = 1;
- } while (block == -1);
- if (ret != 0 && cblock == p->first_block) {
- break;
- }
- cset++;
- } while (set == -1);
- return 0;
- }
- /* ipmi_cfgp_get -- get parameters data from MC into data list within context
- *
- * @param ctx context
- * @param sel parameter selector
- * @returns 0 on success, non-zero otherwise
- */
- int
- ipmi_cfgp_get(struct ipmi_cfgp_ctx *ctx, const struct ipmi_cfgp_sel *sel)
- {
- int i;
- int ret;
- if (ctx == NULL || sel == NULL) {
- return -1;
- }
- if (sel->param != -1) {
- if (sel->param >= ctx->count) {
- return -1;
- }
- ret = cfgp_get_param(ctx, &ctx->set[sel->param],
- sel->set, sel->block, 0);
- if (ret) {
- return -1;
- }
- return 0;
- }
- for (i = 0; i < ctx->count; i++) {
- if (ctx->set[i].access == CFGP_WRONLY) {
- continue;
- }
- if (cfgp_get_param(ctx, &ctx->set[i], sel->set, sel->block, 1)) {
- return -1;
- }
- }
- return 0;
- }
- static int
- cfgp_do_action(struct ipmi_cfgp_ctx *ctx, int action_type,
- const struct ipmi_cfgp_sel *sel, FILE *file, int filter)
- {
- const struct ipmi_cfgp *p;
- struct ipmi_cfgp_data *data;
- struct ipmi_cfgp_action action;
- int ret;
- if (ctx == NULL || sel == NULL) {
- return -1;
- }
- action.type = action_type;
- action.argc = 0;
- action.argv = NULL;
- action.file = file;
- for (data = ctx->v; data != NULL; data = data->next) {
- if (sel->param != -1 && sel->param != data->sel.param) {
- continue;
- }
- if (sel->set != -1 && sel->set != data->sel.set) {
- continue;
- }
- if (sel->block != -1 && sel->block != data->sel.block) {
- continue;
- }
- if (ctx->set[data->sel.param].access == filter) {
- continue;
- }
- p = &ctx->set[data->sel.param];
- action.set = data->sel.set;
- action.block = data->sel.block;
- if (action_type == CFGP_SAVE) {
- fprintf(file, "%s %s ", ctx->cmdname, p->name);
- if (p->is_set) {
- fprintf(file, "%d ", data->sel.set);
- }
- if (p->has_blocks) {
- fprintf(file, "%d ", data->sel.block);
- }
- }
- ret = ctx->handler(ctx->priv, p, &action, data->data);
- if (action_type == CFGP_SAVE) {
- fputc('\n', file);
- }
- if (ret != 0) {
- return -1;
- }
- }
- return 0;
- }
- int
- ipmi_cfgp_set(struct ipmi_cfgp_ctx *ctx, const struct ipmi_cfgp_sel *sel)
- {
- return cfgp_do_action(ctx, CFGP_SET, sel, NULL, CFGP_RDONLY);
- }
- int
- ipmi_cfgp_save(struct ipmi_cfgp_ctx *ctx,
- const struct ipmi_cfgp_sel *sel, FILE *file)
- {
- if (file == NULL) {
- return -1;
- }
- return cfgp_do_action(ctx, CFGP_SAVE, sel, file, CFGP_RDONLY);
- }
- int
- ipmi_cfgp_print(struct ipmi_cfgp_ctx *ctx,
- const struct ipmi_cfgp_sel *sel, FILE *file)
- {
- if (file == NULL) {
- return -1;
- }
- return cfgp_do_action(ctx, CFGP_PRINT, sel, file, CFGP_RESERVED);
- }
|