summaryrefslogtreecommitdiff
path: root/libproto/mh/mbox.c
diff options
context:
space:
mode:
Diffstat (limited to 'libproto/mh/mbox.c')
-rw-r--r--libproto/mh/mbox.c546
1 files changed, 0 insertions, 546 deletions
diff --git a/libproto/mh/mbox.c b/libproto/mh/mbox.c
deleted file mode 100644
index 13467a939..000000000
--- a/libproto/mh/mbox.c
+++ /dev/null
@@ -1,546 +0,0 @@
-/* GNU Mailutils -- a suite of utilities for electronic mail
- Copyright (C) 1999-2019 Free Software Foundation, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 3 of the License, or (at your option) any later version.
-
- This library 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
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General
- Public License along with this library. If not, see
- <http://www.gnu.org/licenses/>. */
-
-/* First draft by Sergey Poznyakoff */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <sys/types.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <time.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <dirent.h>
-
-#ifdef WITH_PTHREAD
-# ifdef HAVE_PTHREAD_H
-# ifndef _XOPEN_SOURCE
-# define _XOPEN_SOURCE 500
-# endif
-# include <pthread.h>
-# endif
-#endif
-
-#include <string.h>
-#ifdef HAVE_STRINGS_H
-# include <strings.h>
-#endif
-
-#include <mailutils/attribute.h>
-#include <mailutils/body.h>
-#include <mailutils/debug.h>
-#include <mailutils/envelope.h>
-#include <mailutils/error.h>
-#include <mailutils/errno.h>
-#include <mailutils/header.h>
-#include <mailutils/locker.h>
-#include <mailutils/message.h>
-#include <mailutils/util.h>
-#include <mailutils/property.h>
-#include <mailutils/stream.h>
-#include <mailutils/url.h>
-#include <mailutils/observer.h>
-#include <mailutils/io.h>
-#include <mailutils/cctype.h>
-#include <mailutils/cstr.h>
-#include <mailutils/mh.h>
-#include <mailutils/sys/mailbox.h>
-#include <mailutils/sys/registrar.h>
-#include <mailutils/sys/amd.h>
-
-struct _mh_message
-{
- struct _amd_message amd_message;
- size_t seq_number; /* message sequence number */
-};
-
-static int
-mh_message_cmp (struct _amd_message *a, struct _amd_message *b)
-{
- struct _mh_message *ma = (struct _mh_message *) a;
- struct _mh_message *mb = (struct _mh_message *) b;
- if (ma->seq_number < mb->seq_number)
- return -1;
- else if (ma->seq_number > mb->seq_number)
- return 1;
- return 0;
-}
-
-static size_t
-_mh_next_seq (struct _amd_data *amd)
-{
- struct _mh_message *msg = (struct _mh_message *)
- _amd_get_message (amd, amd->msg_count);
- return (msg ? msg->seq_number : 0) + 1;
-}
-
-/* Return current filename for the message.
- NOTE: Allocates memory. */
-static int
-_mh_cur_message_name (struct _amd_message *amsg, char **pname)
-{
- int status = 0;
- struct _mh_message *mhm = (struct _mh_message *) amsg;
- char *filename;
- char *pnum;
- size_t len;
-
- status = mu_asprintf (&pnum, "%lu", (unsigned long) mhm->seq_number);
- if (status)
- return status;
- len = strlen (amsg->amd->name) + 1 + strlen (pnum) + 1;
- filename = malloc (len);
- if (filename)
- {
- strcpy (filename, amsg->amd->name);
- strcat (filename, "/");
- strcat (filename, pnum);
- *pname = filename;
- }
- else
- status = ENOMEM;
- free (pnum);
- return status;
-}
-
-/* Return newfilename for the message.
- NOTE: Allocates memory. */
-static int
-_mh_new_message_name (struct _amd_message *amsg, int flags,
- int expunge MU_ARG_UNUSED,
- char **pname)
-{
- int status = 0;
- struct _mh_message *mhm = (struct _mh_message *) amsg;
- char *filename;
- char *pnum;
- size_t len;
-
- status = mu_asprintf (&pnum, "%lu", (unsigned long) mhm->seq_number);
- if (status)
- return status;
- len = strlen (amsg->amd->name) + 1 +
- ((flags & MU_ATTRIBUTE_DELETED) ? 1 : 0) + strlen (pnum) + 1;
- filename = malloc (len);
- if (filename)
- {
- strcpy (filename, amsg->amd->name);
- strcat (filename, "/");
- if (flags & MU_ATTRIBUTE_DELETED)
- strcat (filename, ",");
- strcat (filename, pnum);
- *pname = filename;
- }
- else
- status = ENOMEM;
- free (pnum);
- return status;
-}
-
-/* Find the message with the given sequence number */
-static struct _mh_message *
-_mh_get_message_seq (struct _amd_data *amd, size_t seq)
-{
- struct _mh_message msg;
- size_t index;
-
- msg.seq_number = seq;
- if (amd_msg_lookup (amd, (struct _amd_message*) &msg, &index))
- return NULL;
-
- return (struct _mh_message *) _amd_get_message (amd, index);
-}
-
-/* Scan the mailbox */
-static int
-mh_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED, size_t *pcount,
- int do_notify)
-{
- struct _amd_data *amd = mailbox->data;
- struct _mh_message *msg;
- DIR *dir;
- struct dirent *entry;
- int status = 0;
- struct stat st;
- int need_sort = 0;
-
- if (amd == NULL)
- return EINVAL;
-
- dir = opendir (amd->name);
- if (!dir)
- return errno;
-
- mu_monitor_wrlock (mailbox->monitor);
-
-#ifdef WITH_PTHREAD
- pthread_cleanup_push (amd_cleanup, (void *)mailbox);
-#endif
-
- mu_locker_lock (mailbox->locker);
-
- /* Do actual work. */
-
- while ((entry = readdir (dir)))
- {
- char *namep;
- int attr_flags;
- size_t num;
-
- attr_flags = 0;
- switch (entry->d_name[0])
- {
- case '.':
- /* FIXME: .mh_sequences */
- continue;
- case ',':
- continue;
-#if 0
- attr_flags |= MU_ATTRIBUTE_DELETED;
- namep = entry->d_name+1;
- break;
-#endif
- case '0':case '1':case '2':case '3':case '4':
- case '5':case '6':case '7':case '8':case '9':
- namep = entry->d_name;
- break;
- default:
- /*FIXME: Invalid entry. Report? */
- continue;
- }
-
- num = strtoul (namep, &namep, 10);
- if (namep[0])
- continue;
-
- msg = _mh_get_message_seq (amd, num);
- if (!msg)
- {
- msg = calloc (1, sizeof(*msg));
- status = _amd_message_append (amd, (struct _amd_message *) msg);
- if (status)
- {
- free (msg);
- break;
- }
-
- msg->seq_number = num;
- msg->amd_message.attr_flags = attr_flags;
- msg->amd_message.orig_flags = msg->amd_message.attr_flags;
-
- need_sort = 1;
- }
- else
- {
- msg->amd_message.attr_flags = attr_flags;
- msg->amd_message.orig_flags = msg->amd_message.attr_flags;
- }
- }
-
- closedir (dir);
-
- if (need_sort)
- amd_sort (amd);
-
- if (status == 0)
- {
- if (do_notify)
- {
- size_t i;
-
- for (i = 0; i < amd->msg_count; i++)
- {
- DISPATCH_ADD_MSG (mailbox, amd, i);
- }
- }
-
- if (stat (amd->name, &st) == 0)
- amd->mtime = st.st_mtime;
-
- if (pcount)
- *pcount = amd->msg_count;
- }
- /* Clean up the things */
-
- mu_locker_unlock (mailbox->locker);
- amd_cleanup (mailbox);
-#ifdef WITH_PTHREAD
- pthread_cleanup_pop (0);
-#endif
- return status;
-}
-
-static int
-mh_size_unlocked (struct _amd_data *amd, mu_off_t *psize)
-{
- mu_off_t size = 0;
- int rc;
- struct stat st;
- DIR *dir;
- struct dirent *entry;
-
- dir = opendir (amd->name);
- if (!dir)
- return errno;
-
- while ((entry = readdir (dir)))
- {
- if (*mu_str_skip_class (entry->d_name, MU_CTYPE_DIGIT) == 0)
- {
- char *fname = mu_make_file_name (amd->name, entry->d_name);
- if (!fname)
- continue;
- if (stat (fname, &st))
- {
- rc = errno;
- mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_ERROR,
- ("can't stat %s: %s", fname, mu_strerror (rc)));
- free (fname);
- continue;
- }
- if (S_ISREG (st.st_mode))
- size += st.st_size;
- }
- }
-
- *psize = size;
-
- closedir (dir);
-
- return 0;
-}
-
-static int
-mh_size (mu_mailbox_t mailbox, mu_off_t *psize)
-{
- struct _amd_data *amd = mailbox->data;
- int rc;
-
- mu_monitor_wrlock (mailbox->monitor);
-#ifdef WITH_PTHREAD
- pthread_cleanup_push (amd_cleanup, (void *)mailbox);
-#endif
- mu_locker_lock (mailbox->locker);
-
- rc = mh_size_unlocked (amd, psize);
-
- mu_locker_unlock (mailbox->locker);
- mu_monitor_unlock (mailbox->monitor);
-#ifdef WITH_PTHREAD
- pthread_cleanup_pop (0);
-#endif
- return rc;
-}
-
-
-static int
-mh_qfetch (struct _amd_data *amd, mu_message_qid_t qid)
-{
- char *p;
- size_t num = 0;
- int attr_flags = 0;
- struct _mh_message *msg;
-
- p = qid + strlen (qid) - 1;
- if (!mu_isdigit (*p))
- return EINVAL;
-
- for (p--; p >= qid && mu_isdigit (*p); p--)
- ;
-
- if (p == qid)
- return EINVAL;
-
- num = strtoul (p + 1, NULL, 10);
-
- if (*p == ',')
- {
- attr_flags |= MU_ATTRIBUTE_DELETED;
- p--;
- }
-
- if (*p != '/')
- return EINVAL;
-
- msg = calloc (1, sizeof (*msg));
- msg->seq_number = num;
- msg->amd_message.attr_flags = attr_flags;
- msg->amd_message.orig_flags = msg->amd_message.attr_flags;
- _amd_message_insert (amd, (struct _amd_message*) msg);
- return 0;
-}
-
-
-/* Note: In this particular implementation the message sequence number
- serves also as its UID. This allows to avoid many problems related
- to keeping the uids in the headers of the messages. */
-
-static int
-mh_message_uid (mu_message_t msg, size_t *puid)
-{
- struct _mh_message *mhm = mu_message_get_owner (msg);
- if (puid)
- *puid = mhm->seq_number;
- return 0;
-}
-
-static int
-_mh_msg_init (struct _amd_data *amd, struct _amd_message *amm)
-{
- struct _mh_message *mhm = (struct _mh_message *) amm;
- mhm->seq_number = _mh_next_seq (amd);
- return 0;
-}
-
-static int
-_mh_msg_delete (struct _amd_data *amd, struct _amd_message *amm)
-{
- int rc, status;
- char *name;
- char *argv[3];
- /* FIXME: Cache this value */
- const char *proc = mu_mhprop_get_value (mu_mh_profile, "rmmproc", NULL);
- if (!proc)
- return ENOSYS;
-
- rc = amd->cur_msg_file_name (amm, &name);
- if (rc)
- return rc;
-
- if (proc[0] == 0)
- {
- rc = unlink (name);
- if (rc)
- rc = errno;
- }
- else
- {
- argv[0] = (char*) proc;
- argv[1] = name;
- argv[2] = NULL;
- rc = mu_spawnvp (proc, argv, &status);
- }
- free (name);
- return rc;
-}
-
-
-static int
-mh_remove (struct _amd_data *amd)
-{
- return amd_remove_dir (amd->name);
-}
-
-
-static int
-mh_get_property (mu_mailbox_t mailbox, mu_property_t *pprop)
-{
- struct _amd_data *amd = mailbox->data;
- mu_property_t property = NULL;
- struct mu_mh_prop *mhprop;
- const char *p;
-
- mhprop = calloc (1, sizeof (mhprop[0]));
- if (!mhprop)
- return ENOMEM;
- p = mu_mhprop_get_value (mu_mh_profile, "mh-sequences",
- MU_MH_SEQUENCES_FILE);
- mhprop->filename = mu_make_file_name (amd->name, p);
- mu_property_create_init (&property, mu_mh_property_init, mhprop);
- mu_mailbox_set_property (mailbox, property);
-
- /*FIXME mu_property_set_value (property, "TYPE", "MH", 1);*/
- *pprop = property;
- return 0;
-}
-
-
-
-static int
-mh_translate (mu_mailbox_t mbox, int cmd, size_t from, size_t *to)
-{
- struct _amd_data *amd = mbox->data;
- struct _mh_message msg, *mp;
- size_t n;
-
- /* Make sure the mailbox has been scanned */
- mu_mailbox_messages_count (mbox, &n);
-
- switch (cmd)
- {
- case MU_MAILBOX_UID_TO_MSGNO:
- msg.seq_number = from;
- if (amd_msg_lookup (amd, (struct _amd_message*) &msg, &n))
- return MU_ERR_NOENT;
- *to = n;
- break;
-
- case MU_MAILBOX_MSGNO_TO_UID:
- mp = (struct _mh_message *) _amd_get_message (amd, from);
- if (!mp)
- return MU_ERR_NOENT;
- *to = mp->seq_number;
- break;
-
- default:
- return ENOSYS;
- }
- return 0;
-}
-
-
-
-int
-_mailbox_mh_init (mu_mailbox_t mailbox)
-{
- int rc;
- struct _amd_data *amd;
-
- rc = amd_init_mailbox (mailbox, sizeof (struct _amd_data), &amd);
- if (rc)
- return rc;
-
- amd->msg_size = sizeof (struct _mh_message);
- amd->msg_free = NULL;
- amd->msg_init_delivery = _mh_msg_init;
- amd->msg_finish_delivery = NULL;
- amd->cur_msg_file_name = _mh_cur_message_name;
- amd->new_msg_file_name = _mh_new_message_name;
- amd->scan0 = mh_scan0;
- amd->qfetch = mh_qfetch;
- amd->msg_cmp = mh_message_cmp;
- amd->message_uid = mh_message_uid;
- amd->next_uid = _mh_next_seq;
- amd->remove = mh_remove;
- amd->mailbox_size = mh_size;
-
- mailbox->_get_property = mh_get_property;
- mailbox->_translate = mh_translate;
-
- if (mu_mhprop_get_value (mu_mh_profile, "rmmproc", NULL))
- amd->delete_msg = _mh_msg_delete;
-
-
- return 0;
-}
-
-

Return to:

Send suggestions and report system problems to the System administrator.