summaryrefslogtreecommitdiffstats
path: root/src/doveadm/doveadm-util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/doveadm/doveadm-util.c')
-rw-r--r--src/doveadm/doveadm-util.c221
1 files changed, 221 insertions, 0 deletions
diff --git a/src/doveadm/doveadm-util.c b/src/doveadm/doveadm-util.c
new file mode 100644
index 0000000..a65ef7f
--- /dev/null
+++ b/src/doveadm/doveadm-util.c
@@ -0,0 +1,221 @@
+/* Copyright (c) 2009-2018 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "array.h"
+#include "net.h"
+#include "time-util.h"
+#include "master-service.h"
+#include "module-dir.h"
+#include "doveadm-settings.h"
+#include "doveadm-mail.h"
+#include "doveadm-util.h"
+
+#include <time.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <ctype.h>
+
+#define DOVEADM_TCP_CONNECT_TIMEOUT_SECS 30
+
+bool doveadm_verbose = FALSE, doveadm_debug = FALSE, doveadm_server = FALSE;
+static struct module *modules = NULL;
+
+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. */
+ i_zero(&mod_set);
+ mod_set.abi_version = DOVECOT_ABI_VERSION;
+ 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,
+ NULL, &mod_set);
+ module_dir_init(modules);
+}
+
+void doveadm_unload_modules(void)
+{
+ module_dir_unload(&modules);
+}
+
+bool doveadm_has_unloaded_plugin(const char *name)
+{
+ struct module *module;
+ DIR *dir;
+ struct dirent *d;
+ const char *plugin_name;
+ size_t name_len = strlen(name);
+ bool found = FALSE;
+
+ /* first check that it's not actually loaded */
+ for (module = modules; module != NULL; module = module->next) {
+ if (strcmp(module_get_plugin_name(module), name) == 0)
+ return FALSE;
+ }
+
+ dir = opendir(DOVEADM_MODULEDIR);
+ if (dir == NULL)
+ return FALSE;
+
+ while ((d = readdir(dir)) != NULL) {
+ plugin_name = module_file_get_name(d->d_name);
+ if (str_begins(plugin_name, "doveadm_"))
+ plugin_name += 8;
+
+ if (strncmp(plugin_name, name, name_len) == 0 &&
+ (plugin_name[name_len] == '\0' ||
+ strcmp(plugin_name + name_len, "_plugin") == 0)) {
+ found = TRUE;
+ break;
+ }
+ }
+ (void)closedir(dir);
+ return found;
+}
+
+const char *unixdate2str(time_t timestamp)
+{
+ return t_strflocaltime("%Y-%m-%d %H:%M:%S", timestamp);
+}
+
+const char *doveadm_plugin_getenv(const char *name)
+{
+ const char *const *envs;
+ unsigned int i, count;
+
+ if (!array_is_created(&doveadm_settings->plugin_envs))
+ return NULL;
+
+ envs = array_get(&doveadm_settings->plugin_envs, &count);
+ for (i = 0; i < count; i += 2) {
+ if (strcmp(envs[i], name) == 0)
+ return envs[i+1];
+ }
+ return NULL;
+}
+
+static int
+doveadm_tcp_connect_port(const char *host, in_port_t port)
+{
+ struct ip_addr *ips;
+ unsigned int ips_count;
+ int ret, fd;
+
+ alarm(DOVEADM_TCP_CONNECT_TIMEOUT_SECS);
+ ret = net_gethostbyname(host, &ips, &ips_count);
+ if (ret != 0) {
+ i_fatal("Lookup of host %s failed: %s",
+ host, net_gethosterror(ret));
+ }
+ fd = net_connect_ip_blocking(&ips[0], port, NULL);
+ if (fd == -1) {
+ i_fatal("connect(%s:%u) failed: %m",
+ net_ip2addr(&ips[0]), port);
+ }
+ alarm(0);
+ return fd;
+}
+
+int doveadm_tcp_connect(const char *target, in_port_t default_port)
+{
+ const char *host;
+ in_port_t port;
+
+ if (net_str2hostport(target, default_port, &host, &port) < 0) {
+ i_fatal("Port not known for %s. Either set proxy_port "
+ "or use %s:port", target, target);
+ }
+ return doveadm_tcp_connect_port(host, port);
+}
+
+int doveadm_connect_with_default_port(const char *path,
+ in_port_t default_port)
+{
+ int fd;
+
+ /* we'll assume UNIX sockets typically have an absolute path,
+ or at the very least '/' somewhere. */
+ if (strchr(path, '/') == NULL)
+ fd = doveadm_tcp_connect(path, default_port);
+ else {
+ fd = net_connect_unix(path);
+ if (fd == -1)
+ i_fatal("net_connect_unix(%s) failed: %m", path);
+ }
+ return fd;
+}
+
+int doveadm_connect(const char *path)
+{
+ return doveadm_connect_with_default_port(path, 0);
+}
+
+int i_strccdascmp(const char *a, const char *b)
+{
+ while(*a != '\0' && *b != '\0') {
+ if ((*a == ' ' || *a == '-') && *a != *b && *b != ' ' && *b != '-') {
+ if (i_toupper(*(a+1)) == *(b)) a++;
+ else break;
+ } else if ((*b == ' ' || *b == '-') && *a != *b && *a != ' ' && *a != '-') {
+ if (*a == i_toupper(*(b+1))) b++;
+ else break;
+ } else if (!((*a == ' ' || *a == '-') &&
+ (*b == ' ' || *b == '-')) &&
+ (*a != *b)) break;
+ a++; b++;
+ }
+ return *a-*b;
+}
+
+char doveadm_log_type_to_char(enum log_type type)
+{
+ switch(type) {
+ case LOG_TYPE_DEBUG:
+ return '\x01';
+ case LOG_TYPE_INFO:
+ return '\x02';
+ case LOG_TYPE_WARNING:
+ return '\x03';
+ case LOG_TYPE_ERROR:
+ return '\x04';
+ case LOG_TYPE_FATAL:
+ return '\x05';
+ case LOG_TYPE_PANIC:
+ return '\x06';
+ default:
+ i_unreached();
+ }
+}
+
+bool doveadm_log_type_from_char(char c, enum log_type *type_r)
+{
+ switch(c) {
+ case '\x01':
+ *type_r = LOG_TYPE_DEBUG;
+ break;
+ case '\x02':
+ *type_r = LOG_TYPE_INFO;
+ break;
+ case '\x03':
+ *type_r = LOG_TYPE_WARNING;
+ break;
+ case '\x04':
+ *type_r = LOG_TYPE_ERROR;
+ break;
+ case '\x05':
+ *type_r = LOG_TYPE_FATAL;
+ break;
+ case '\x06':
+ *type_r = LOG_TYPE_PANIC;
+ break;
+ default:
+ *type_r = LOG_TYPE_WARNING;
+ return FALSE;
+ }
+ return TRUE;
+}