diff options
Diffstat (limited to 'src/maildir.c')
-rw-r--r-- | src/maildir.c | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/src/maildir.c b/src/maildir.c new file mode 100644 index 0000000..8d379cc --- /dev/null +++ b/src/maildir.c @@ -0,0 +1,210 @@ +/* $Id$ */ + +/*** + This file is part of libnewmail + + libnewmail is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + libnewmail is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libnewmail; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA +***/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <errno.h> +#include <dirent.h> + +#include "module.h" +#include "newmail.h" +#include "util.h" + +struct data { + char *path; + enum nm_query query; + nm_query_cb_t cb; + void *user; + oop_source *oop; +}; + +static int _is_maildir(char *p) { + static char fn[PATH_MAX]; + static struct stat st; + + + if (stat(p, &st) == 0 && S_ISDIR(st.st_mode)) { + snprintf(fn, sizeof(fn), "%s/cur", p); + + if (stat(fn, &st) == 0 && S_ISDIR(st.st_mode)) + return 0; + } + + return -1; +} + +static int _query(struct nm_spool *s, enum nm_query query, struct nm_status *status) { + struct data *data = (struct data*) s->data; + DIR* d; + static char c[PATH_MAX]; + status->new = status->cur = -1; + + if (_is_maildir(data->path)) { + nm_error(NM_ERROR_NOFILE, "Mailbox not maildir"); + return -1; + } + + + snprintf(c, sizeof(c), "%s/new", data->path); + if ((d = opendir(c))) { + int n = 0; + struct dirent *de; + + while ((de = readdir(d))) { + if (de->d_name[0] == '.') + continue; + n++; + if (!(query & NM_QUERY_NNEW)) + break; + } + + closedir(d); + + snprintf(c, sizeof(c), "%s/cur", data->path); + if ((d = opendir(c))) { + int n2 = 0; + + while ((de = readdir(d))) { + if (de->d_name[0] == '.') + continue; + n2++; + if (!(query & NM_QUERY_NCUR)) + break; + } + + closedir(d); + + status->new = n; + status->cur = query & NM_QUERY_NCUR ? (n+n2) : (n||n2 ? 1 : 0); + + return 0; + } else + nm_error(NM_ERROR_SYSTEM|NM_ERROR_NOFILE, NULL); + + } else + nm_error(NM_ERROR_SYSTEM|NM_ERROR_NOFILE, NULL); + + return -1; +} + +static void * _cb(oop_source *source, struct timeval tv, void *user) { + struct nm_status status; + struct nm_spool *s = (struct nm_spool *) user; + struct data *data = (struct data*) s->data; + + if (_query(s, data->query, &status) < 0) + data->cb(s, NULL, data->user); + else + data->cb(s, &status, data->user); + + data->cb = NULL; + data->query = 0; + data->user = NULL; + data->oop = NULL; + + return OOP_CONTINUE; +} + +static int _query_submit(struct nm_spool *s, enum nm_query query, oop_source *oop, nm_query_cb_t cb, void *user) { + struct data *data = (struct data*) s->data; + + if (data->cb) { + nm_error(NM_ERROR_ALREADY, NULL); + return -1; + } + + data->cb = cb; + data->query = query; + data->user = user; + data->oop = oop; + + data->oop->on_time(data->oop, OOP_TIME_NOW, _cb, s); + + return 0; +} + +static int _configure(struct nm_spool *s) { + return -1; +} + +static int _info(struct nm_spool *s, struct nm_info *i) { + struct data *data = (struct data*) s->data; + + snprintf(i->text, sizeof(i->text), "qmail Maildir %s", data->path); + i->flags = NM_FLAG_SYNCHRONOUS; + + return 0; +} + +static void _done(struct nm_spool *s) { + struct data *data = (struct data*) s->data; + if (data) { + if (data->cb && data->oop) + data->oop->cancel_time(data->oop, OOP_TIME_NOW, _cb, s); + + nm_free(data->path); + nm_free(data); + } +} + + +int nm_init(struct nm_spool *s) { + struct data *data; + char *def; + + def = NULL; + if (!(def = getenv("MAILDIR"))) + if ((def = getenv("MAIL"))) + if (_is_maildir(def) != 0) { + if (!s->config) + return -1; + + def = NULL; + } + + if (!def) { + static char fn[PATH_MAX]; + snprintf(fn, sizeof(fn), "%s/Maildir", getenv("HOME")); + if (s->config || _is_maildir(fn) == 0) + def = fn; + else + return -1; + } + + + s->query = _query; + s->query_submit = _query_submit; + s->configure = _configure; + s->info = _info; + s->done = _done; + + if (!s->path) + s->path = nm_strdup("@AUTOMATIC@.maildir"); + + data = nm_malloc(sizeof(struct data)); + memset(data, 0, sizeof(struct data)); + + data->path = nm_strdup(nm_specials(nm_config_get(s->config, "Path", def))); + s->data = (void*) data; + return 0; +} |