/* $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 #include #include #include #include #include #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; }