/*
 * vdevadm — main dispatcher
 */

#include "vdevadm.h"

#include <errno.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static int adm_version(void)
{
	printf("%s\n", VDEVADM_VERSION);
	return 0;
}

static int adm_help(void);

static const struct vdevadm_cmd cmds[] = {
	{ "info", "Query device properties from vdev udev-compat database",
	  vdevadm_info_main },
	{ "trigger", "Trigger sysfs uevents for vdevd", vdevadm_trigger_main },
	{ "settle", "Wait for vdev input settle or coldplug stamp",
	  vdevadm_settle_main },
	{ "control", "Send commands to vdevd / vdev_settle",
	  vdevadm_control_main },
	{ "monitor", "Listen for udev/kernel events (libudev)",
	  vdevadm_monitor_main },
	{ "help", "Show help", NULL },
	{ "version", "Show version", NULL },
};

static int adm_help(void)
{
	size_t i;

	printf("vdevadm [--version] [--help] COMMAND [OPTIONS]\n\n"
		   "vdev administration tool (udevadm-like interface for vdev).\n\n"
		   "Commands:\n");
	for (i = 0; i < sizeof(cmds) / sizeof(cmds[0]); i++) {
		if (!strcmp(cmds[i].name, "help") || !strcmp(cmds[i].name, "version"))
			continue;
		printf("  %-10s %s\n", cmds[i].name, cmds[i].help);
	}
	return 0;
}

int main(int argc, char *argv[])
{
	struct vdevadm_ctx ctx;
	const char *command;
	size_t i;
	int rc;

	if (argc < 2) {
		adm_help();
		return 1;
	}

	if (!strcmp(argv[1], "--version") || !strcmp(argv[1], "-V")) {
		adm_version();
		return 0;
	}
	if (!strcmp(argv[1], "--help") || !strcmp(argv[1], "-h")) {
		adm_help();
		return 0;
	}

	if (vdevadm_ctx_init(&ctx) != 0) {
		fprintf(stderr, "vdevadm: failed to initialize context\n");
		return 1;
	}

	command = argv[1];

	if (!strcmp(command, "version")) {
		adm_version();
		return 0;
	}
	if (!strcmp(command, "help")) {
		if (argc >= 3) {
			for (i = 0; i < sizeof(cmds) / sizeof(cmds[0]); i++) {
				if (!strcmp(cmds[i].name, argv[2]) && cmds[i].cmd) {
					char *fake_argv[3] = { "vdevadm", argv[2], "--help" };

					return cmds[i].cmd(&ctx, 3, fake_argv);
				}
			}
		}
		adm_help();
		return 0;
	}

	for (i = 0; i < sizeof(cmds) / sizeof(cmds[0]); i++) {
		if (strcmp(cmds[i].name, command) != 0)
			continue;
		if (!cmds[i].cmd) {
			fprintf(stderr, "vdevadm: internal command '%s'\n", command);
			return 1;
		}
		{
			char *sub_argv[argc];

			sub_argv[0] = "vdevadm";
			memcpy(sub_argv + 1, argv + 2,
				   (size_t)(argc - 2) * sizeof(sub_argv[0]));
			rc = cmds[i].cmd(&ctx, argc, sub_argv);
		}
		return rc != 0 ? rc : 0;
	}

	fprintf(stderr, "vdevadm: unknown command '%s'\n", command);
	adm_help();
	return 1;
}
