/*
 * Copyright (C) 2015 Red Hat, Inc.
 *
 * This file is part of LVM2.
 *
 * This copyrighted material is made available to anyone wishing to use,
 * modify, copy, or redistribute it subject to the terms and conditions
 * of the GNU Lesser General Public License v.2.1.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include "lvmpolld-common.h"

/* extract this info from autoconf/automake files */
#define LVPOLL_CMD "lvpoll"

#define MIN_ARGV_SIZE  8

static const char *const const polling_ops[] = { [PVMOVE] = LVMPD_REQ_PVMOVE,
						 [CONVERT] = LVMPD_REQ_CONVERT,
						 [MERGE] = LVMPD_REQ_MERGE,
						 [MERGE_THIN] = LVMPD_REQ_MERGE_THIN };

const char *polling_op(enum poll_type type)
{
	return type < POLL_TYPE_MAX ? polling_ops[type] : "<undefined>";
}

static int add_to_cmd_arr(const char ***cmdargv, const char *str, unsigned *ind)
{
	const char **newargv;

	if (*ind && !(*ind % MIN_ARGV_SIZE)) {
		newargv = dm_realloc(*cmdargv, (*ind / MIN_ARGV_SIZE + 1) * MIN_ARGV_SIZE * sizeof(char *));
		if (!newargv)
			return 0;
		*cmdargv = newargv;
	}

	*(*cmdargv + (*ind)++) = str;

	return 1;
}

const char **cmdargv_ctr(const struct lvmpolld_lv *pdlv, const char *lvm_binary, unsigned abort_polling, unsigned handle_missing_pvs)
{
	unsigned i = 0;
	const char **cmd_argv = dm_malloc(MIN_ARGV_SIZE * sizeof(char *));

	if (!cmd_argv)
		return NULL;

	/* path to lvm2 binary */
	if (!add_to_cmd_arr(&cmd_argv, lvm_binary, &i))
		goto err;

	/* cmd to execute */
	if (!add_to_cmd_arr(&cmd_argv, LVPOLL_CMD, &i))
		goto err;

	/* transfer internal polling interval */
	if (pdlv->sinterval &&
	    (!add_to_cmd_arr(&cmd_argv, "--interval", &i) ||
	     !add_to_cmd_arr(&cmd_argv, pdlv->sinterval, &i)))
		goto err;

	/* pass abort param */
	if (abort_polling &&
	    !add_to_cmd_arr(&cmd_argv, "--abort", &i))
		goto err;

	/* pass handle-missing-pvs. used by mirror polling operation */
	if (handle_missing_pvs &&
	    !add_to_cmd_arr(&cmd_argv, "--handlemissingpvs", &i))
		goto err;

	/* one of: "convert", "pvmove", "merge", "merge_thin" */
	if (!add_to_cmd_arr(&cmd_argv, "--polloperation", &i) ||
	    !add_to_cmd_arr(&cmd_argv, polling_ops[pdlv->type], &i))
		goto err;

	/* vg/lv name */
	if (!add_to_cmd_arr(&cmd_argv, pdlv->lvname, &i))
		goto err;

	/* disable metadata backup */
	if (!add_to_cmd_arr(&cmd_argv, "-An", &i))
		goto err;

	/* terminating NULL */
	if (!add_to_cmd_arr(&cmd_argv, NULL, &i))
		goto err;

	return cmd_argv;
err:
	dm_free(cmd_argv);
	return NULL;
}

/* FIXME: in fact exclude should be va list */
static int copy_env(const char ***cmd_envp, unsigned *i, const char *exclude)
{
	const char * const* tmp = (const char * const*) environ;

	if (!tmp)
		return 0;

	while (*tmp) {
		if (strncmp(*tmp, exclude, strlen(exclude)) && !add_to_cmd_arr(cmd_envp, *tmp, i))
			return 0;
		tmp++;
	}

	return 1;
}

const char **cmdenvp_ctr(const struct lvmpolld_lv *pdlv)
{
	unsigned i = 0;
	const char **cmd_envp = dm_malloc(MIN_ARGV_SIZE * sizeof(char *));

	if (!cmd_envp)
		return NULL;

	/* copy whole environment from lvmpolld, exclude LVM_SYSTEM_DIR if set */
	if (!copy_env(&cmd_envp, &i, "LVM_SYSTEM_DIR="))
		goto err;

	/* Add per client LVM_SYSTEM_DIR variable if set */
	if (*pdlv->lvm_system_dir_env && !add_to_cmd_arr(&cmd_envp, pdlv->lvm_system_dir_env, &i))
		goto err;

	/* terminating NULL */
	if (!add_to_cmd_arr(&cmd_envp, NULL, &i))
		goto err;

	return cmd_envp;
err:
	dm_free(cmd_envp);
	return NULL;
}
