Blame lib/ipmi_cfgp.c

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