aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Borkmann <daniel@iogearbox.net>2019-10-01 20:29:21 +0200
committerDaniel Borkmann <daniel@iogearbox.net>2019-10-01 20:53:20 +0200
commit20d4421a5686afccbe0568f1ecca6992b8fcf2d7 (patch)
tree56e952bb30c1caf7034868a7f5b79144a4e07ba8
parent4740bcd111b9c106b426a4bb9807917e9a17d4fe (diff)
downloadl2md-20d4421a5686afccbe0568f1ecca6992b8fcf2d7.tar.gz
l2md: make output modular to support different modes
Refactor the output handling of new mails in order to allow adding new modes as next step. Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
-rw-r--r--Makefile2
-rw-r--r--config.c46
-rw-r--r--env.c11
-rw-r--r--l2md.h21
-rw-r--r--mail.c14
-rw-r--r--maildir.c40
-rw-r--r--repo.c8
7 files changed, 97 insertions, 45 deletions
diff --git a/Makefile b/Makefile
index 19b0ce8..8ef22d9 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
CFLAGS = -O2 -Wall -Werror
LDFLAGS = -lgit2
-l2md: l2md.o config.o env.o utils.o repo.o mail.o
+l2md: l2md.o config.o env.o utils.o repo.o mail.o maildir.o
$(CC) -o $@ $^ $(LDFLAGS)
install:
diff --git a/config.c b/config.c
index 72eb6f8..129aa75 100644
--- a/config.c
+++ b/config.c
@@ -27,11 +27,12 @@ static void config_dump(struct config *cfg)
return;
verbose("general.base = %s\n", cfg->general.base);
- verbose("general.maildir = %s\n", cfg->general.maildir);
+ verbose("general.mode = %s\n", cfg->ops->name);
+ verbose("general.%s = %s\n", cfg->ops->name, cfg->general.out);
verbose("general.period = %u\n", cfg->general.period);
repo_for_each(cfg, repo, i) {
- verbose("repos.%s.maildir = %s\n", repo->name, repo->maildir);
+ verbose("repos.%s.%s = %s\n", repo->name, cfg->ops->name, repo->out);
verbose("repos.%s.initial_import = %u\n", repo->name, repo->initial_import);
url_for_each(repo, url, j) {
verbose("repos.%s.url = %s\n", repo->name, url->path);
@@ -70,15 +71,23 @@ static void config_set_basedir(struct config *cfg, const char *dir)
wordfree(&p);
}
-static void config_set_maildir(struct config *cfg, const char *dir, bool root)
+static void config_set_mode(struct config *cfg, const char *mode)
+{
+ if (!strncmp(mode, "maildir", sizeof("maildir")))
+ cfg->ops = &ops_maildir;
+ else
+ panic("Unknown mode: %s!\n", mode);
+}
+
+static void config_set_out(struct config *cfg, const char *ctx, bool root)
{
struct config_repo *repo = repo_last(cfg);
- char *maildir = root ? cfg->general.maildir : repo->maildir;
+ char *out = root ? cfg->general.out : repo->out;
wordexp_t p;
- wordexp(dir, &p, 0);
- dir = p.we_wordv[0];
- strlcpy(maildir, dir, sizeof(repo->maildir));
+ wordexp(ctx, &p, 0);
+ ctx = p.we_wordv[0];
+ strlcpy(out, ctx, sizeof(repo->out));
wordfree(&p);
}
@@ -113,7 +122,7 @@ static void config_new_repo(struct config *cfg, const char *name)
cfg->repos_num);
repo = repo_last(cfg);
memset(repo, 0, sizeof(*repo));
- config_set_maildir(cfg, cfg->general.maildir, false);
+ config_set_out(cfg, cfg->general.out, false);
strlcpy(repo->name, name, sizeof(repo->name));
}
@@ -121,13 +130,14 @@ static void config_set_defaults(struct config *cfg, const char *homedir)
{
char path[PATH_MAX];
+ cfg->ops = &ops_maildir;
cfg->general.period = 60;
slprintf(path, sizeof(path), "%s/.l2md", homedir);
strlcpy(cfg->general.base, path, sizeof(cfg->general.base));
slprintf(path, sizeof(path), "%s/maildir", cfg->general.base);
- strlcpy(cfg->general.maildir, path, sizeof(cfg->general.maildir));
+ strlcpy(cfg->general.out, path, sizeof(cfg->general.out));
}
void config_uninit(struct config *cfg)
@@ -144,7 +154,7 @@ void config_uninit(struct config *cfg)
struct config *config_init(int argc, char **argv)
{
const char *homedir = getenv("HOME");
- char buff[1024], tmp[1024];
+ char buff[1024], tmp[1024] = {};
char path[PATH_MAX];
bool seen[STATE_MAX] = {};
int state = STATE_NONE;
@@ -182,7 +192,7 @@ struct config *config_init(int argc, char **argv)
state_next:
if (!strcmp(buff, "[general]\n")) {
state = STATE_GENERAL;
- } else if (sscanf(buff, "[repo %[a-z0-9-]]\n",
+ } else if (sscanf(buff, "[repo %1023[a-z0-9-]]\n",
tmp) == 1) {
state = STATE_REPO;
config_new_repo(cfg, tmp);
@@ -196,19 +206,21 @@ struct config *config_init(int argc, char **argv)
panic("[general] config must be before [repo *] config");
else if (sscanf(buff, "\tperiod = %u", &val) == 1)
cfg->general.period = val;
- else if (sscanf(buff, "\tmaildir = %s", tmp) == 1)
- config_set_maildir(cfg, tmp, true);
- else if (sscanf(buff, "\tbase = %s", tmp) == 1)
+ else if (sscanf(buff, "\tmode = %1023s", tmp) == 1)
+ config_set_mode(cfg, tmp);
+ else if (sscanf(buff, "\tmaildir = %1023s", tmp) == 1)
+ config_set_out(cfg, tmp, true);
+ else if (sscanf(buff, "\tbase = %1023s", tmp) == 1)
config_set_basedir(cfg, tmp);
else
goto state_next;
break;
case STATE_REPO:
- if (sscanf(buff, "\turl = %s", tmp) == 1)
+ if (sscanf(buff, "\turl = %1023s", tmp) == 1)
config_new_url(cfg, tmp);
- else if (sscanf(buff, "\tmaildir = %s", tmp) == 1)
- config_set_maildir(cfg, tmp, false);
+ else if (sscanf(buff, "\tmaildir = %1023s", tmp) == 1)
+ config_set_out(cfg, tmp, false);
else if (sscanf(buff, "\tinitial_import = %u", &val) == 1)
config_set_initial_import(cfg, val);
else
diff --git a/env.c b/env.c
index 3139fe2..f72d15c 100644
--- a/env.c
+++ b/env.c
@@ -52,16 +52,7 @@ static void bootstrap_repos(struct config *cfg)
static void bootstrap_mail(struct config *cfg)
{
- struct config_repo *repo;
- uint32_t i;
-
- repo_for_each(cfg, repo, i) {
- xmkdir1_with_subdirs(repo->maildir);
-
- xmkdir2(repo->maildir, "cur");
- xmkdir2(repo->maildir, "tmp");
- xmkdir2(repo->maildir, "new");
- }
+ cfg->ops->bootstrap(cfg);
}
void bootstrap_env(struct config *cfg)
diff --git a/l2md.h b/l2md.h
index 45e87d5..7389d8c 100644
--- a/l2md.h
+++ b/l2md.h
@@ -34,8 +34,18 @@
#define MAIL "m"
+struct config;
+struct config_repo;
+
+struct mail_ops {
+ const char *name;
+ void (*bootstrap)(struct config *cfg);
+ void (*new_mail)(struct config_repo *repo, uint32_t url,
+ const char *oid, const void *raw, size_t len);
+};
+
struct config_general {
- char maildir[PATH_MAX];
+ char out[PATH_MAX];
char base[PATH_MAX];
uint32_t period;
};
@@ -48,7 +58,7 @@ struct config_url {
struct config_repo {
char name[128];
- char maildir[PATH_MAX];
+ char out[PATH_MAX];
git_repository *git;
struct config_url *urls;
uint32_t urls_num;
@@ -60,6 +70,7 @@ struct config {
struct config_general general;
struct config_repo *repos;
uint32_t repos_num;
+ const struct mail_ops *ops;
};
#define repo_for_each(cfg, repo, i) \
@@ -79,6 +90,8 @@ struct config {
extern pid_t own_pid;
extern bool verbose_enabled;
+extern struct mail_ops ops_maildir;
+
struct config *config_init(int argc, char **argv);
void config_uninit(struct config *cfg);
@@ -90,10 +103,10 @@ void sync_done(struct config *cfg);
void repo_clone(struct config_repo *repo, struct config_url *url, const char *target);
void repo_pull(struct config_repo *repo, struct config_url *url, const char *target);
-void repo_walk_files(struct config *cfg, struct config_repo *repo, uint32_t which,
+void repo_walk_files(struct config *cfg, struct config_repo *repo, uint32_t url,
const char *path, const char *oid_last, char *oid_done,
void (*repo_walker)(struct config *cfg, struct config_repo *repo,
- uint32_t which, const char *oid,
+ uint32_t url, const char *oid,
const void *raw, size_t len));
void repo_local_path(struct config *cfg, struct config_repo *repo,
diff --git a/mail.c b/mail.c
index fd8f783..1d2fdda 100644
--- a/mail.c
+++ b/mail.c
@@ -8,15 +8,11 @@
#include "l2md.h"
-static void repo_walker(struct config *cfg, struct config_repo *repo, uint32_t which,
- const char *oid, const void *raw, size_t len)
+static void repo_walker(struct config *cfg, struct config_repo *repo,
+ uint32_t url, const char *oid,
+ const void *raw, size_t len)
{
- char dst[PATH_MAX];
-
- slprintf(dst, sizeof(dst), "%s/new/0.%06u.%s-%u-%s",
- repo->maildir, own_pid, repo->name, which, oid);
-
- xwrite_file(dst, raw, len, true);
+ cfg->ops->new_mail(repo, url, oid, raw, len);
}
void sync_mail(struct config *cfg)
@@ -26,7 +22,7 @@ void sync_mail(struct config *cfg)
char path[PATH_MAX];
uint32_t i, j;
- verbose("Resyncing maildirs.\n");
+ verbose("Resyncing mails.\n");
repo_for_each(cfg, repo, i) {
url_for_each(repo, url, j) {
diff --git a/maildir.c b/maildir.c
new file mode 100644
index 0000000..5228650
--- /dev/null
+++ b/maildir.c
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (C) 2019 Daniel Borkmann <daniel@iogearbox.net> */
+
+#include <unistd.h>
+
+#include <sys/time.h>
+#include <sys/types.h>
+
+#include "l2md.h"
+
+static void maildir_new_mail(struct config_repo *repo, uint32_t which,
+ const char *oid, const void *raw, size_t len)
+{
+ char dst[PATH_MAX];
+
+ slprintf(dst, sizeof(dst), "%s/new/0.%06u.%s-%u-%s",
+ repo->out, own_pid, repo->name, which, oid);
+
+ xwrite_file(dst, raw, len, true);
+}
+
+static void maildir_bootstrap(struct config *cfg)
+{
+ struct config_repo *repo;
+ uint32_t i;
+
+ repo_for_each(cfg, repo, i) {
+ xmkdir1_with_subdirs(repo->out);
+
+ xmkdir2(repo->out, "cur");
+ xmkdir2(repo->out, "tmp");
+ xmkdir2(repo->out, "new");
+ }
+}
+
+struct mail_ops ops_maildir = {
+ .name = "maildir",
+ .bootstrap = maildir_bootstrap,
+ .new_mail = maildir_new_mail,
+};
diff --git a/repo.c b/repo.c
index 843bfbe..c5ca8e8 100644
--- a/repo.c
+++ b/repo.c
@@ -179,10 +179,10 @@ void repo_local_oid(struct config *cfg, struct config_repo *repo,
__repo_local_get(cfg, repo, url, OIDS, out, len);
}
-void repo_walk_files(struct config *cfg, struct config_repo *repo, uint32_t which,
+void repo_walk_files(struct config *cfg, struct config_repo *repo, uint32_t url,
const char *path, const char *oid_last, char *oid_done,
void (*repo_walker)(struct config *cfg, struct config_repo *repo,
- uint32_t which, const char *oid,
+ uint32_t url, const char *oid,
const void *raw, size_t len))
{
char oid_curr[GIT_OID_HEXSZ + 1];
@@ -249,7 +249,7 @@ void repo_walk_files(struct config *cfg, struct config_repo *repo, uint32_t whic
panic_git("Cannot revparse object");
blob = (const git_blob *)object;
- repo_walker(cfg, repo, which, oid_curr, git_blob_rawcontent(blob),
+ repo_walker(cfg, repo, url, oid_curr, git_blob_rawcontent(blob),
(size_t)git_blob_rawsize(blob));
git_object_free(object);
@@ -266,7 +266,7 @@ void repo_walk_files(struct config *cfg, struct config_repo *repo, uint32_t whic
if (have_first && count) {
git_oid_tostr(oid_curr, sizeof(oid_curr), &loid);
printf("Processed %u new mail(s) for %s. %s: %s -> %s in %ld.%02lds.\n",
- count, repo->name, repo->urls[which].path, oid_last ? oid_curr :
+ count, repo->name, repo->urls[url].path, oid_last ? oid_curr :
"[none]", oid_done, res.tv_sec, res.tv_usec);
}