<commit_before>/* Copyright (c) 2009-2010 Dovecot authors, see the included COPYING file */

#include "lib.h"
#include "array.h"
#include "str.h"
#include "module-dir.h"
#include "master-service.h"
#include "master-service-settings.h"
#include "doveadm-mail.h"
#include "doveadm-settings.h"
#include "doveadm.h"

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>

bool doveadm_verbose = FALSE, doveadm_debug = FALSE;

static struct module *modules = NULL;
static ARRAY_DEFINE(doveadm_cmds, struct doveadm_cmd);

void doveadm_register_cmd(const struct doveadm_cmd *cmd)
{
	array_append(&doveadm_cmds, cmd, 1);
}

void usage(void)
{
	const struct doveadm_cmd *cmd;

	fprintf(stderr, "usage: doveadm [-Dv] <command> [<args>]\n");

	array_foreach(&doveadm_cmds, cmd) {
		fprintf(stderr, USAGE_CMDNAME_FMT" %s\n",
			cmd->name, cmd->short_usage);
	}
	doveadm_mail_usage();
	exit(1);
}

void help(const struct doveadm_cmd *cmd)
{
	fprintf(stderr, "doveadm %s %s\n", cmd->name, cmd->short_usage);
	if (cmd->long_usage != NULL)
		fprintf(stderr, "%s", cmd->long_usage);
	exit(0);
}

const char *unixdate2str(time_t timestamp)
{
	static char buf[64];
	struct tm *tm;

	tm = localtime(&timestamp);
	strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm);
	return buf;
}

static void cmd_help(int argc, char *argv[])
{
	const struct doveadm_cmd *cmd;
	string_t *name;
	int i;

	if (argv[1] == NULL)
		usage();

	name = t_str_new(100);
	for (i = 1; i < argc; i++) {
		str_append(name, argv[i]);

		array_foreach(&doveadm_cmds, cmd) {
			if (strcmp(cmd->name, str_c(name)) == 0)
				help(cmd);
		}
		doveadm_mail_try_help_name(str_c(name));

		str_append_c(name, ' ');
	}
	usage();
}

static struct doveadm_cmd doveadm_cmd_help = {
	cmd_help, "help", "<cmd>", NULL
};

static bool doveadm_try_run(const char *cmd_name, int argc, char *argv[])
{
	const struct doveadm_cmd *cmd;

	array_foreach(&doveadm_cmds, cmd) {
		if (strcmp(cmd_name, cmd->name) == 0) {
			cmd->cmd(argc, argv);
			return TRUE;
		}
	}
	return FALSE;
}

static void doveadm_load_modules(void)
{
	struct module_dir_load_settings mod_set;

	/* some doveadm plugins have dependencies to mail plugins. we can load
	   only those whose dependencies have been loaded earlier, the rest are
	   ignored. */
	memset(&mod_set, 0, sizeof(mod_set));
	mod_set.version = master_service_get_version_string(master_service);
	mod_set.require_init_funcs = TRUE;
	mod_set.debug = doveadm_debug;
	mod_set.ignore_dlopen_errors = TRUE;

	modules = module_dir_load_missing(modules, DOVEADM_MODULEDIR,<commit_msg>doveadm: Added support for multi-word (non-mail) commands.<commit_after>/* Copyright (c) 2009-2010 Dovecot authors, see the included COPYING file */

#include "lib.h"
#include "array.h"
#include "str.h"
#include "module-dir.h"
#include "master-service.h"
#include "master-service-settings.h"
#include "doveadm-mail.h"
#include "doveadm-settings.h"
#include "doveadm.h"

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>

bool doveadm_verbose = FALSE, doveadm_debug = FALSE;

static struct module *modules = NULL;
static ARRAY_DEFINE(doveadm_cmds, struct doveadm_cmd);

void doveadm_register_cmd(const struct doveadm_cmd *cmd)
{
	array_append(&doveadm_cmds, cmd, 1);
}

void usage(void)
{
	const struct doveadm_cmd *cmd;

	fprintf(stderr, "usage: doveadm [-Dv] <command> [<args>]\n");

	array_foreach(&doveadm_cmds, cmd) {
		fprintf(stderr, USAGE_CMDNAME_FMT" %s\n",
			cmd->name, cmd->short_usage);
	}
	doveadm_mail_usage();
	exit(1);
}

void help(const struct doveadm_cmd *cmd)
{
	fprintf(stderr, "doveadm %s %s\n", cmd->name, cmd->short_usage);
	if (cmd->long_usage != NULL)
		fprintf(stderr, "%s", cmd->long_usage);
	exit(0);
}

const char *unixdate2str(time_t timestamp)
{
	static char buf[64];
	struct tm *tm;

	tm = localtime(&timestamp);
	strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm);
	return buf;
}

static void cmd_help(int argc, char *argv[])
{
	const struct doveadm_cmd *cmd;
	string_t *name;
	int i;

	if (argv[1] == NULL)
		usage();

	name = t_str_new(100);
	for (i = 1; i < argc; i++) {
		str_append(name, argv[i]);

		array_foreach(&doveadm_cmds, cmd) {
			if (strcmp(cmd->name, str_c(name)) == 0)
				help(cmd);
		}
		doveadm_mail_try_help_name(str_c(name));

		str_append_c(name, ' ');
	}
	usage();
}

static struct doveadm_cmd doveadm_cmd_help = {
	cmd_help, "help", "<cmd>", NULL
};

static bool
doveadm_try_run_multi_word(const struct doveadm_cmd *cmd,
			   const char *cmdname, int argc, char *argv[])
{
	unsigned int len;

	if (argc < 1)
		return FALSE;

	len = strlen(argv[1]);
	if (strncmp(cmdname, argv[1], len) != 0)
		return FALSE;

	if (cmdname[len] == ' ') {
		/* more args */
		return doveadm_try_run_multi_word(cmd, cmdname + len + 1,
						  argc - 1, argv + 1);
	}
	if (cmdname[len] != '\0')
		return FALSE;

	/* match */
	cmd->cmd(argc - 1, argv + 1);
	return TRUE;
}

static bool doveadm_try_run(const char *cmd_name, int argc, char *argv[])
{
	const struct doveadm_cmd *cmd;
	unsigned int cmd_name_len;

	i_assert(argc > 0);

	cmd_name_len = strlen(cmd_name);
	array_foreach(&doveadm_cmds, cmd) {
		if (strcmp(cmd->name, cmd_name) == 0) {
			cmd->cmd(argc, argv);
			return TRUE;
		}

		/* see if it matches a multi-word command */
		if (strncmp(cmd->name, cmd_name, cmd_name_len) == 0 &&
		    cmd->name[cmd_name_len] == ' ') {
			const char *subcmd = cmd->name + cmd_name_len + 1;

			if (doveadm_try_run_multi_word(cmd, subcmd,
						       argc, argv))
				return TRUE;
		}
	}

	return FALSE;
}

static void doveadm_load_modules(void)
{
	struct module_dir_load_settings mod_set;

	/* some doveadm plugins have dependencies to mail plugins. we can load
	   only those whose dependencies have been loaded earlier, the rest are
	   ignored. */
	memset(&mod_set, 0, sizeof(mod_set));
	mod_set.version = master_service_get_version_string(master_service);
	mod_set.require_init_funcs = TRUE;
	mod_set.debug = doveadm_debug;
	mod_set.ignore_dlopen_errors = TRUE;

	modules = module_dir_load_missing(modules, DOVEADM_MODULEDIR,
{'fraction_non_alphanumeric': 0.14745175655616033, 'fraction_numerical': 0.009401286491835725, 'mean_word_length': 4.635687732342007, 'pattern_counts': {'":': 0, '<': 20, '<?xml version=': 0, '>': 40, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1511307', 'n_tokens_mistral': 2543, 'n_tokens_neox': 2359, 'n_words': 555}