summaryrefslogtreecommitdiffstats
path: root/src/unix.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/unix.c')
-rw-r--r--src/unix.c218
1 files changed, 218 insertions, 0 deletions
diff --git a/src/unix.c b/src/unix.c
new file mode 100644
index 0000000..181ff7a
--- /dev/null
+++ b/src/unix.c
@@ -0,0 +1,218 @@
+/* $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 "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 _query(struct nm_spool *s, enum nm_query query, struct nm_status *status) {
+ struct data *data = (struct data*) s->data;
+ status->new = status->cur = -1;
+
+
+ if (query & (NM_QUERY_NCUR|NM_QUERY_NNEW)) {
+ FILE *f;
+ struct stat st;
+ int hdr=1, old=0;
+
+ if (!(f = fopen(data->path, "r"))) {
+
+ if (errno == ENOENT) {
+ status->new = status->cur = 0;
+ return 0;
+ } else {
+ nm_error(NM_ERROR_NOFILE|NM_ERROR_SYSTEM, NULL);
+ return -1;
+ }
+
+ }
+
+ if (fstat(fileno(f), &st) < 0) {
+ nm_error(NM_ERROR_NOFILE|NM_ERROR_SYSTEM, "fstat() failed");
+ fclose(f);
+ return -1;
+ }
+
+ if (!S_ISREG(st.st_mode)) {
+ nm_error(NM_ERROR_NOFILE, "Mailbox not a regular file");
+ fclose(f);
+ return -1;
+ }
+
+ status->cur = 0;
+
+ while (!feof(f)) {
+ static char ln[128];
+
+ if (!fgets(ln, sizeof(ln), f))
+ break;
+
+ if (strncmp(ln, "From ", 5) == 0) {
+ hdr = 1;
+ status->cur++;
+ } else if (hdr && strcmp(ln, "\n") == 0)
+ hdr = 0;
+ else if (hdr && strncmp(ln, "Status: ", 8) == 0) {
+ old++;
+ hdr = 0;
+ }
+ }
+
+ fclose(f);
+
+ status->new = status->cur-old;
+
+ return 0;
+
+ } else if (query & (NM_QUERY_CUR|NM_QUERY_NEW)) {
+ struct stat st;
+
+ if (stat(data->path, &st) < 0) {
+ if (errno == ENOENT) {
+ status->cur = status->new = 0;
+ return 0;
+ }
+
+ nm_error(NM_ERROR_NOFILE|NM_ERROR_SYSTEM, NULL);
+ return -1;
+ }
+
+ if (!S_ISREG(st.st_mode)) {
+ nm_error(NM_ERROR_NOFILE, "Mailbox not a regular file");
+ return -1;
+ }
+
+ status->cur = st.st_size != 0 ? 1 : 0;
+ status->new = status->cur && (st.st_atime < st.st_mtime) ? 1 : 0;
+ return 0;
+ }
+
+ 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->user = NULL;
+ data->query = 0;
+ 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->user = user;
+ data->query = query;
+ 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), "Unix mail spool %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;
+
+ if (!(def = getenv("MAIL"))) {
+ static char fn[PATH_MAX];
+ static struct stat st;
+
+ def = fn;
+
+ snprintf(fn, sizeof(fn), "/var/mail/%s", getenv("USER"));
+ if (stat(fn, &st) < 0 || !S_ISREG(st.st_mode))
+ snprintf(fn, sizeof(fn), "/var/spool/mail/%s", getenv("USER"));
+ }
+
+ 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@.unix");
+
+ 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;
+}
+
+