summaryrefslogtreecommitdiff
path: root/libmailutils/registrar.c
diff options
context:
space:
mode:
Diffstat (limited to 'libmailutils/registrar.c')
-rw-r--r--libmailutils/registrar.c443
1 files changed, 443 insertions, 0 deletions
diff --git a/libmailutils/registrar.c b/libmailutils/registrar.c
new file mode 100644
index 000000000..a1a2b4f1a
--- /dev/null
+++ b/libmailutils/registrar.c
@@ -0,0 +1,443 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 1999, 2000, 2001, 2004, 2005, 2006, 2007, 2009, 2010
+ 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, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301 USA */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+
+#include <mailutils/iterator.h>
+#include <mailutils/list.h>
+#include <mailutils/monitor.h>
+#include <mailutils/errno.h>
+#include <mailutils/nls.h>
+#include <mailutils/error.h>
+#include <mailutils/url.h>
+#include <mailutils/mutil.h>
+#include <mailutils/sys/registrar.h>
+
+/* NOTE: We will leak here since the monitor and the registrar will never
+ be released. That's ok we can live with this, it's only done once. */
+static mu_list_t registrar_list;
+struct mu_monitor registrar_monitor = MU_MONITOR_INITIALIZER;
+
+static mu_record_t mu_default_record;
+
+void
+mu_registrar_set_default_record (mu_record_t record)
+{
+ mu_default_record = record;
+}
+
+int
+mu_registrar_get_default_record (mu_record_t *prec)
+{
+ if (mu_default_record)
+ {
+ if (prec)
+ *prec = mu_default_record;
+ return 0;
+ }
+ return MU_ERR_NOENT;
+}
+
+int
+mu_registrar_set_default_scheme (const char *scheme)
+{
+ int status;
+ mu_record_t rec;
+
+ status = mu_registrar_lookup_scheme (scheme, &rec);
+ if (status == 0)
+ mu_default_record = rec;
+ return status;
+}
+
+const char *
+mu_registrar_get_default_scheme ()
+{
+ return mu_default_record ? mu_default_record->scheme : NULL;
+}
+
+static int
+_registrar_get_list (mu_list_t *plist)
+{
+ int status = 0;
+
+ if (plist == NULL)
+ return MU_ERR_OUT_PTR_NULL;
+ mu_monitor_wrlock (&registrar_monitor);
+ if (registrar_list == NULL)
+ status = mu_list_create (&registrar_list);
+ *plist = registrar_list;
+ mu_monitor_unlock (&registrar_monitor);
+ return status;
+}
+
+/* Provided for backward compatibility */
+int
+mu_registrar_get_list (mu_list_t *plist)
+{
+ static int warned;
+
+ if (!warned)
+ {
+ mu_error (_("program uses mu_registrar_get_list(), which is deprecated"));
+ warned = 1;
+ }
+ return _registrar_get_list (plist);
+}
+
+int
+mu_registrar_get_iterator (mu_iterator_t *pitr)
+{
+ int status = 0;
+ if (pitr == NULL)
+ return MU_ERR_OUT_PTR_NULL;
+ mu_monitor_wrlock (&registrar_monitor);
+ if (registrar_list == NULL)
+ {
+ status = mu_list_create (&registrar_list);
+ if (status)
+ return status;
+ }
+ status = mu_list_get_iterator (registrar_list, pitr);
+ mu_monitor_unlock (&registrar_monitor);
+ return status;
+}
+
+int
+mu_registrar_lookup_scheme (const char *scheme, mu_record_t *precord)
+{
+ size_t len;
+ mu_iterator_t iterator;
+ int status = mu_registrar_get_iterator (&iterator);
+ if (status != 0)
+ return status;
+ status = MU_ERR_NOENT;
+ len = strcspn (scheme, ":");
+ for (mu_iterator_first (iterator); !mu_iterator_is_done (iterator);
+ mu_iterator_next (iterator))
+ {
+ mu_record_t record;
+ mu_iterator_current (iterator, (void **)&record);
+ if (strlen (record->scheme) == len
+ && memcmp (record->scheme, scheme, len) == 0)
+ {
+ if (precord)
+ *precord = record;
+ status = 0;
+ break;
+ }
+ }
+ mu_iterator_destroy (&iterator);
+ return status;
+}
+
+int
+mu_registrar_lookup_url (mu_url_t url, int flags,
+ mu_record_t *precord, int *pflags)
+{
+ mu_iterator_t iterator;
+ mu_record_t last_record = NULL;
+ int last_flags = 0;
+ int status = mu_registrar_get_iterator (&iterator);
+ if (status != 0)
+ return status;
+ status = MU_ERR_NOENT;
+ for (mu_iterator_first (iterator); !mu_iterator_is_done (iterator);
+ mu_iterator_next (iterator))
+ {
+ int rc;
+ mu_record_t record;
+ mu_iterator_current (iterator, (void **)&record);
+ if ((rc = mu_record_is_scheme (record, url, flags)))
+ {
+ if (rc == flags)
+ {
+ status = 0;
+ last_record = record;
+ last_flags = rc;
+ break;
+ }
+ else if (rc > last_flags)
+ {
+ status = 0;
+ last_record = record;
+ last_flags = rc;
+ }
+ }
+ }
+ mu_iterator_destroy (&iterator);
+
+ if (status == 0)
+ {
+ if (precord)
+ *precord = last_record;
+ if (pflags)
+ *pflags = last_flags;
+ }
+ else if (!mu_is_proto (mu_url_to_string (url)) /* FIXME: This check is not
+ enough. */
+ && mu_registrar_get_default_record (precord) == 0)
+ {
+ status = 0;
+ if (pflags)
+ *pflags = flags & MU_FOLDER_ATTRIBUTE_FILE; /* FIXME? */
+ }
+
+ return status;
+}
+
+int
+mu_registrar_lookup (const char *name, int flags,
+ mu_record_t *precord, int *pflags)
+{
+ int rc;
+ mu_url_t url;
+
+ rc = mu_url_create (&url, name);
+ if (rc)
+ return rc;
+ rc = mu_url_parse (url);
+ if (rc == 0)
+ rc = mu_registrar_lookup_url (url, flags, precord, pflags);
+ mu_url_destroy (&url);
+ return rc;
+}
+
+static int
+_compare_prio (const void *item, const void *value)
+{
+ const mu_record_t a = (const mu_record_t) item;
+ const mu_record_t b = (const mu_record_t) value;
+ if (a->priority > b->priority)
+ return 0;
+ return -1;
+}
+
+int
+mu_registrar_record (mu_record_t record)
+{
+ int status;
+ mu_list_t list;
+ mu_list_comparator_t comp;
+
+ if (!record)
+ return 0;
+ _registrar_get_list (&list);
+ comp = mu_list_set_comparator (list, _compare_prio);
+ status = mu_list_insert (list, record, record, 1);
+ if (status == MU_ERR_NOENT)
+ status = mu_list_append (list, record);
+ mu_list_set_comparator (list, comp);
+ return status;
+}
+
+int
+mu_unregistrar_record (mu_record_t record)
+{
+ mu_list_t list;
+ _registrar_get_list (&list);
+ mu_list_remove (list, record);
+ return 0;
+}
+
+int
+mu_record_is_scheme (mu_record_t record, mu_url_t url, int flags)
+{
+ if (record == NULL)
+ return 0;
+
+ /* Overload. */
+ if (record->_is_scheme)
+ return record->_is_scheme (record, url, flags);
+
+ if (mu_url_is_scheme (url, record->scheme))
+ return MU_FOLDER_ATTRIBUTE_ALL;
+
+ return 0;
+}
+
+int
+mu_record_set_scheme (mu_record_t record, const char *scheme)
+{
+ if (record == NULL)
+ return EINVAL;
+ record->scheme = scheme;
+ return 0;
+}
+
+int
+mu_record_set_is_scheme (mu_record_t record,
+ int (*_is_scheme) (mu_record_t, mu_url_t, int))
+{
+ if (record == NULL)
+ return EINVAL;
+ record->_is_scheme = _is_scheme;
+ return 0;
+}
+
+int
+mu_record_get_url (mu_record_t record, int (*(*_purl)) (mu_url_t))
+{
+ if (record == NULL)
+ return EINVAL;
+ if (_purl == NULL)
+ return MU_ERR_OUT_PTR_NULL;
+ /* Overload. */
+ if (record->_get_url)
+ return record->_get_url (record, _purl);
+ *_purl = record->_url;
+ return 0;
+}
+
+int
+mu_record_set_url (mu_record_t record, int (*_mu_url) (mu_url_t))
+{
+ if (record == NULL)
+ return EINVAL;
+ record->_url = _mu_url;
+ return 0;
+}
+
+int
+mu_record_set_get_url (mu_record_t record, int (*_get_url)
+ (mu_record_t, int (*(*)) (mu_url_t)))
+{
+ if (record == NULL)
+ return EINVAL;
+ record->_get_url = _get_url;
+ return 0;
+}
+
+int
+mu_record_get_mailbox (mu_record_t record, int (*(*_pmailbox)) (mu_mailbox_t))
+{
+ if (record == NULL)
+ return EINVAL;
+ if (_pmailbox == NULL)
+ return MU_ERR_OUT_PTR_NULL;
+ /* Overload. */
+ if (record->_get_mailbox)
+ return record->_get_mailbox (record, _pmailbox);
+ *_pmailbox = record->_mailbox;
+ return 0;
+}
+
+int
+mu_record_set_mailbox (mu_record_t record, int (*_mu_mailbox) (mu_mailbox_t))
+{
+ if (record)
+ return EINVAL;
+ record->_mailbox = _mu_mailbox;
+ return 0;
+}
+
+int
+mu_record_set_get_mailbox (mu_record_t record,
+ int (*_get_mailbox) (mu_record_t, int (*(*)) (mu_mailbox_t)))
+{
+ if (record)
+ return EINVAL;
+ record->_get_mailbox = _get_mailbox;
+ return 0;
+}
+
+int
+mu_record_get_mailer (mu_record_t record, int (*(*_pmailer)) (mu_mailer_t))
+{
+ if (record == NULL)
+ return EINVAL;
+ if (_pmailer == NULL)
+ return MU_ERR_OUT_PTR_NULL;
+ /* Overload. */
+ if (record->_get_mailer)
+ return record->_get_mailer (record, _pmailer);
+ *_pmailer = record->_mailer;
+ return 0;
+}
+
+int
+mu_record_set_mailer (mu_record_t record, int (*_mu_mailer) (mu_mailer_t))
+{
+ if (record)
+ return EINVAL;
+ record->_mailer = _mu_mailer;
+ return 0;
+}
+
+int
+mu_record_set_get_mailer (mu_record_t record,
+ int (*_get_mailer) (mu_record_t, int (*(*)) (mu_mailer_t)))
+{
+ if (record == NULL)
+ return EINVAL;
+ record->_get_mailer = _get_mailer;
+ return 0;
+}
+
+int
+mu_record_get_folder (mu_record_t record, int (*(*_pfolder)) (mu_folder_t))
+{
+ if (record == NULL)
+ return EINVAL;
+ if (_pfolder == NULL)
+ return MU_ERR_OUT_PTR_NULL;
+ /* Overload. */
+ if (record->_get_folder)
+ return record->_get_folder (record, _pfolder);
+ *_pfolder = record->_folder;
+ return 0;
+}
+
+int
+mu_record_set_folder (mu_record_t record, int (*_mu_folder) (mu_folder_t))
+{
+ if (record == NULL)
+ return EINVAL;
+ record->_folder = _mu_folder;
+ return 0;
+}
+
+int
+mu_record_set_get_folder (mu_record_t record,
+ int (*_get_folder) (mu_record_t, int (*(*)) (mu_folder_t)))
+{
+ if (record == NULL)
+ return EINVAL;
+ record->_get_folder = _get_folder;
+ return 0;
+}
+
+int
+mu_record_list_p (mu_record_t record, const char *name, int flags)
+{
+ if (record == NULL)
+ return EINVAL;
+ return record == NULL
+ || !record->_list_p
+ || record->_list_p (record, name, flags);
+}

Return to:

Send suggestions and report system problems to the System administrator.