Commit 72beac0a 72beac0a0f1bc97283ffefac9c79730b94e62f53 by Sergey Poznyakoff

Move MH profile & context support to libproto.

* mh/mh_ctx.c: Remove.
* mh/Makefile.am (libmh_a_SOURCES): Remove mh_ctx.c
* mh/folder.c (read_seq_file): Use mu_property_t.
* mh/mh.h (mh_context_iterator): Remove typedef.
(mh_global_profile_get, mh_global_profile_set)
(mh_global_profile_iterate)
(mh_global_context_set,mh_global_context_set)
(mh_global_context_iterate): Rewrite as macros.
(mh_global_sequences_iterate): Change signature.
(mh_read_property_file,mh_property_merge): New protos.
(mh_context_create,mh_context_read,mh_context_write)
(mh_context_get_value,mh_context_set_value,mh_context_iterate)
(mh_context_destroy,mh_context_merge): Remove protos.
* mh/mh_global.c (mh_global_profile_get, mh_global_profile_set)
(mh_global_profile_iterate)
(mh_global_context_set,mh_global_context_set)
(mh_global_context_iterate): Remove.
(mh_read_property_file,mh_property_merge): New functions.
(_mh_init_global_context,mh_read_profile)
(mh_set_current_folder,mh_global_sequences_iterate): Rewrite.
(mh_global_save_state): Rewrite.
* mh/mh_whom.c (mh_whom): Use mu_property_t.
* mh/send.c: Use mu_property_t.
* po/POTFILES.in: Add mh/mboxprop.c.
1 parent c08b926f
......@@ -68,7 +68,6 @@ libmh_a_SOURCES= \
mh_alias_gram.c\
mh_alias_lex.c\
mh_argp.c\
mh_ctx.c\
mh_getopt.c\
mh_global.c\
mh_format.c\
......
......@@ -272,18 +272,15 @@ static void
read_seq_file (struct folder_info *info, const char *prefix, const char *name)
{
char *pname = NULL;
mh_context_t *ctx;
mu_property_t prop;
const char *p;
pname = mh_safe_make_file_name (prefix, name);
ctx = mh_context_create (pname, 1);
mh_context_read (ctx);
prop = mh_read_property_file (pname, 1);
p = mh_context_get_value (ctx, "cur", NULL);
if (p)
if (mu_property_sget_value (prop, "cur", &p) == 0)
info->cur = strtoul (p, NULL, 0);
free (pname);
free (ctx);
mu_property_destroy (&prop);
}
static void
......
......@@ -56,6 +56,7 @@
#include <mailutils/mime.h>
#include <mailutils/io.h>
#include <mailutils/property.h>
#include <mailutils/mh.h>
#include <mu_umaxtostr.h>
......@@ -228,9 +229,6 @@ struct mh_whatnow_env /* whatnow shell environment */
#define DISP_USE 1
#define DISP_REPLACE 2
typedef int (*mh_context_iterator) (const char *field, const char *value,
void *data);
#define SEQ_PRIVATE 1
#define SEQ_ZERO 2
......@@ -246,10 +244,23 @@ mu_message_t mh_file_to_message (const char *folder, const char *file_name);
mu_message_t mh_stream_to_message (mu_stream_t stream);
void mh_install (char *name, int automode);
const char *mh_global_profile_get (const char *name, const char *defval);
int mh_global_profile_set (const char *name, const char *value);
const char *mh_global_context_get (const char *name, const char *defval);
int mh_global_context_set (const char *name, const char *value);
mu_property_t mh_read_property_file (char *name, int ro);
void mh_property_merge (mu_property_t dst, mu_property_t src);
#define mh_global_profile_get(name, defval) \
mu_mhprop_get_value (mu_mh_profile, name, defval)
#define mh_global_profile_set(name, value) \
mu_property_set_value (mu_mh_profile, name, value, 1))
#define mh_global_profile_iterate(fp, data) \
mu_mhprop_iterate (mu_mh_profile, fp, data)
#define mh_global_context_get(name, defval) \
mu_mhprop_get_value (mu_mh_context, name, defval)
#define mh_global_context_set(name, value) \
mu_property_set_value (mu_mh_context, name, value, 1)
#define mh_global_context_iterate(fp, data) \
mu_mhprop_iterate (mu_mh_context, fp, data)
const char *mh_set_current_folder (const char *val);
const char *mh_current_folder (void);
......@@ -259,12 +270,10 @@ const char *mh_global_sequences_get (mu_mailbox_t mbox,
void mh_global_sequences_set (mu_mailbox_t mbox,
const char *name, const char *value);
void mh_global_sequences_iterate (mu_mailbox_t mbox,
mh_context_iterator fp, void *data);
mu_mhprop_iterator_t fp, void *data);
void mh_global_sequences_drop (mu_mailbox_t mbox);
void mh_global_save_state (void);
int mh_global_profile_iterate (mh_context_iterator fp, void *data);
int mh_global_context_iterate (mh_context_iterator fp, void *data);
int mh_interactive_mode_p (void);
int mh_getyn (const char *fmt, ...) MU_PRINTFLIKE(1,2);
......@@ -287,17 +296,6 @@ void mh_err_memory (int fatal);
FILE *mh_audit_open (char *name, mu_mailbox_t mbox);
void mh_audit_close (FILE *fp);
mh_context_t *mh_context_create (const char *name, int copy);
int mh_context_read (mh_context_t *ctx);
int mh_context_write (mh_context_t *ctx);
const char *mh_context_get_value (mh_context_t *ctx, const char *name,
const char *defval);
int mh_context_set_value (mh_context_t *ctx, const char *name,
const char *value);
int mh_context_iterate (mh_context_t *ctx, mh_context_iterator fp, void *data);
void mh_context_destroy (mh_context_t **pctx);
void mh_context_merge (mh_context_t *dst, mh_context_t *src);
int mh_message_number (mu_message_t msg, size_t *pnum);
mu_mailbox_t mh_open_folder (const char *folder, int create);
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2009,
2010 Free Software Foundation, Inc.
GNU Mailutils 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 3, or (at your option)
any later version.
GNU Mailutils 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 GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
/* MH context functions. */
#include <mh.h>
#include <sys/types.h>
#include <sys/stat.h>
mh_context_t *
mh_context_create (const char *name, int copy)
{
mh_context_t *ctx;
ctx = malloc (sizeof (*ctx));
if (!ctx)
mh_err_memory (1);
if (copy)
ctx->name = name;
else
{
ctx->name = strdup (name);
if (!ctx->name)
mh_err_memory (1);
}
ctx->header = NULL;
return ctx;
}
void
mh_context_destroy (mh_context_t **pctx)
{
mh_context_t *ctx = *pctx;
free ((char*) ctx->name);
if (ctx->header)
mu_header_destroy (&ctx->header);
free (ctx);
*pctx = NULL;
}
void
mh_context_merge (mh_context_t *dst, mh_context_t *src)
{
if (!dst->header)
{
dst->header = src->header;
src->header = NULL;
}
else
{
size_t i, count;
mu_header_get_field_count (src->header, &count);
for (i = 1; i <= count; i++)
{
const char *name = NULL;
const char *value = NULL;
mu_header_sget_field_name (src->header, i, &name);
mu_header_sget_field_value (src->header, i, &value);
mu_header_set_value (dst->header, name, value, 1);
}
}
}
int
mh_context_read (mh_context_t *ctx)
{
int rc;
char *blurb, *p;
mu_stream_t stream;
mu_off_t stream_size;
char *buf = NULL;
size_t size = 0, n;
if (!ctx)
return MU_ERR_OUT_NULL;
rc = mu_file_stream_create (&stream, ctx->name, MU_STREAM_READ);
if (rc)
return rc;
rc = mu_stream_size (stream, &stream_size);
if (rc)
{
mu_stream_destroy (&stream);
return rc;
}
blurb = malloc (stream_size + 1);
if (!blurb)
{
mu_stream_destroy (&stream);
return ENOMEM;
}
p = blurb;
while (mu_stream_getline (stream, &buf, &size, &n) == 0 && n > 0)
{
char *q = mu_str_skip_class (buf, MU_CTYPE_SPACE);
if (!*q || *q == '#')
continue;
for (q = buf; *q;)
*p++ = *q++;
}
mu_stream_destroy (&stream);
rc = mu_header_create (&ctx->header, blurb, p - blurb);
free (blurb);
return rc;
}
int
mh_context_write (mh_context_t *ctx)
{
int rc;
mu_stream_t instream, outstream;
mu_off_t size;
if (!ctx)
return MU_ERR_OUT_NULL;
rc = mu_file_stream_create (&outstream, ctx->name,
MU_STREAM_WRITE|MU_STREAM_CREAT);
if (rc)
{
mu_error (_("cannot open context file %s for writing: %s"),
ctx->name, mu_strerror (rc));
return MU_ERR_FAILURE;
}
mu_header_get_streamref (ctx->header, &instream);
rc = mu_stream_copy (outstream, instream, 0, &size);
if (rc)
{
mu_error (_("error writing to context file %s: %s"),
ctx->name, mu_strerror (rc));
return MU_ERR_FAILURE;
}
else
rc = mu_stream_truncate (outstream, size);
mu_stream_destroy (&instream);
mu_stream_destroy (&outstream);
return 0;
}
const char *
mh_context_get_value (mh_context_t *ctx, const char *name, const char *defval)
{
const char *p;
if (!ctx || mu_header_sget_value (ctx->header, name, &p))
p = defval;
return p;
}
int
mh_context_set_value (mh_context_t *ctx, const char *name, const char *value)
{
if (!ctx)
return EINVAL;
if (!ctx->header)
{
int rc;
if ((rc = mu_header_create (&ctx->header, NULL, 0)) != 0)
{
mu_error (_("cannot create context %s: %s"),
ctx->name,
mu_strerror (rc));
return 1;
}
}
return mu_header_set_value (ctx->header, name, value, 1);
}
int
mh_context_iterate (mh_context_t *ctx, mh_context_iterator fp, void *data)
{
size_t i, nfields;
int rc = 0;
if (!ctx)
return EINVAL;
if (!ctx->header)
return 0;
rc = mu_header_get_field_count (ctx->header, &nfields);
if (rc)
{
mu_error (_("cannot obtain field count for context %s"), ctx->name);
return rc;
}
for (i = 1; i <= nfields && rc == 0; i++)
{
const char *name, *value;
rc = mu_header_sget_field_name (ctx->header, i, &name);
if (rc)
{
mu_error (_("cannot obtain field name for context %s:%d: %s"),
ctx->name,i,mu_strerror (rc));
break;
}
rc = mu_header_sget_field_value (ctx->header, i, &value);
if (rc)
{
mu_error (_("cannot obtain field value for context %s:%d: %s"),
ctx->name,i,mu_strerror (rc));
break;
}
rc = fp (name, value, data);
}
return rc;
}
......@@ -20,29 +20,70 @@
#include <mh.h>
static const char *current_folder = NULL;
mh_context_t *context;
mh_context_t *profile;
int rcpt_mask = RCPT_DEFAULT;
int mh_auto_install = 1;
/* Global profile */
mu_property_t
mh_read_property_file (char *name, int ro)
{
mu_property_t prop;
struct mu_mh_prop *mhprop;
int rc;
mhprop = xzalloc (sizeof (mhprop[0]));
mhprop->filename = name;
mhprop->ro = ro;
rc = mu_property_create_init (&prop, mu_mh_property_init, mhprop);
if (rc)
{
mu_diag_funcall (MU_DIAG_ERROR, "mu_property_create_init", name, rc);
exit (1);
}
return prop;
}
const char *
mh_global_profile_get (const char *name, const char *defval)
static int
prop_merger (const char *field, const char *value, void *data)
{
return mh_context_get_value (profile, name, defval);
mu_property_t dst;
return mu_property_set_value (dst, field, value, 1);
}
int
mh_global_profile_set (const char *name, const char *value)
void
mh_property_merge (mu_property_t dst, mu_property_t src)
{
return mh_context_set_value (profile, name, value);
int rc;
if (!src)
return;
rc = mu_mhprop_iterate (src, prop_merger, dst);
if (rc)
{
mu_diag_funcall (MU_DIAG_ERROR, "mu_mhprop_iterate", NULL, rc);
exit (1);
}
}
/* Global profile */
int
mh_global_profile_iterate (mh_context_iterator fp, void *data)
void
_mh_init_global_context ()
{
return mh_context_iterate (profile, fp, data);
char *p, *ctx_name;
if (mu_mh_context)
return;
p = getenv ("CONTEXT");
if (!p)
p = MH_CONTEXT_FILE;
ctx_name = mh_expand_name (NULL, p, 0);
mu_mh_context = mh_read_property_file (ctx_name, 0);
if (!current_folder)
current_folder = mh_global_context_get ("Current-Folder",
mh_global_profile_get ("Inbox",
"inbox"));
}
void
......@@ -66,8 +107,7 @@ mh_read_profile ()
if (mh_auto_install && access (p, R_OK))
mh_install (p, 1);
profile = mh_context_create (p, 1);
mh_context_read (profile);
mu_mh_profile = mh_read_property_file (p, 0);
mu_set_folder_directory (mh_get_dir ());
......@@ -75,55 +115,15 @@ mh_read_profile ()
fallback = mh_global_profile_get ("Decode-Fallback", NULL);
if (fallback && mu_set_default_fallback (fallback))
mu_error (_("Incorrect value for decode-fallback"));
}
/* Global context */
void
_mh_init_global_context ()
{
char *p, *ctx_name;
if (context)
return;
p = getenv ("CONTEXT");
if (!p)
p = MH_CONTEXT_FILE;
ctx_name = mh_expand_name (NULL, p, 0);
context = mh_context_create (ctx_name, 1);
mh_context_read (context);
if (!current_folder)
current_folder = mh_context_get_value (context, "Current-Folder",
mh_global_profile_get ("Inbox",
"inbox"));
}
const char *
mh_global_context_get (const char *name, const char *defval)
{
_mh_init_global_context ();
return mh_context_get_value (context, name, defval);
}
int
mh_global_context_set (const char *name, const char *value)
{
_mh_init_global_context ();
return mh_context_set_value (context, name, value);
}
int
mh_global_context_iterate (mh_context_iterator fp, void *data)
{
_mh_init_global_context ();
return mh_context_iterate (context, fp, data);
}
/* Global context */
const char *
mh_current_folder ()
{
_mh_init_global_context ();
return mh_global_context_get ("Current-Folder",
mh_global_profile_get ("Inbox", "inbox"));
}
......@@ -131,7 +131,13 @@ mh_current_folder ()
const char *
mh_set_current_folder (const char *val)
{
mh_global_context_set ("Current-Folder", val);
int rc = mh_global_context_set ("Current-Folder", val);
if (rc)
{
mu_diag_funcall (MU_DIAG_ERROR, "mh_global_context_set",
"Current-Folder", rc);
exit (1);
}
current_folder = mh_current_folder ();
return current_folder;
}
......@@ -192,10 +198,9 @@ mh_global_sequences_set (mu_mailbox_t mbox, const char *name,
}
}
/* FIXME: Rewrite using mu_mhprop_iterate */
void
mh_global_sequences_iterate (mu_mailbox_t mbox,
mh_context_iterator fp, void *data)
mu_mhprop_iterator_t fp, void *data)
{
int rc;
mu_iterator_t itr;
......@@ -207,16 +212,7 @@ mh_global_sequences_iterate (mu_mailbox_t mbox,
mu_diag_funcall (MU_DIAG_ERROR, "mu_property_get_iterator", NULL, rc);
exit (1);
}
for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
mu_iterator_next (itr))
{
const char *name, *val;
mu_iterator_current_kv (itr, (const void **)&name, (void**)&val);
if (fp (name, val, data))
break;
}
mu_iterator_destroy (&itr);
mu_mhprop_iterate (prop, fp, data);
}
/* Global state */
......@@ -224,6 +220,15 @@ mh_global_sequences_iterate (mu_mailbox_t mbox,
void
mh_global_save_state ()
{
mh_context_set_value (context, "Current-Folder", current_folder);
mh_context_write (context);
int rc;
mh_global_context_set ("Current-Folder", current_folder);
rc = mu_property_save (mu_mh_context);
if (rc)
{
mu_diag_funcall (MU_DIAG_ERROR, "mu_profile_save", "context", rc);
exit (1);
}
}
......
......@@ -202,26 +202,22 @@ int
mh_whom (const char *filename, int check)
{
int rc = 0;
mh_context_t *ctx;
mh_read_aliases ();
ctx = mh_context_create (filename, 1);
if ((rc = mh_context_read (ctx)))
if (access (filename, R_OK))
{
if (rc == ENOENT)
mu_error ("%s: %s", filename, mu_strerror (rc));
else
mu_error ("%s: %s (%s)", filename, _("malformed message"),
mu_strerror (rc));
mu_error ("%s: %s", filename, mu_strerror (rc));
rc = -1;
}
else
{
size_t count = 0;
mu_property_t prop;
scan_addrs (mh_context_get_value (ctx, MU_HEADER_TO, NULL), 0);
scan_addrs (mh_context_get_value (ctx, MU_HEADER_CC, NULL), 0);
scan_addrs (mh_context_get_value (ctx, MU_HEADER_BCC, NULL), 1);
mh_read_aliases ();
prop = mh_read_property_file (xstrdup (filename), 1);
scan_addrs (mu_mhprop_get_value (prop, MU_HEADER_TO, NULL), 0);
scan_addrs (mu_mhprop_get_value (prop, MU_HEADER_CC, NULL), 0);
scan_addrs (mu_mhprop_get_value (prop, MU_HEADER_BCC, NULL), 1);
if (local_rcp)
{
......@@ -240,8 +236,8 @@ mh_whom (const char *filename, int check)
mu_error(_("no recipients"));
rc = -1;
}
mu_property_destroy (&prop);
}
free (ctx);
destroy_addrs (&network_rcp);
destroy_addrs (&local_rcp);
return rc;
......
......@@ -283,7 +283,7 @@ struct list_elt /* Element of the send list */
};
static mu_list_t mesg_list;
static mh_context_t *mts_profile;
static mu_property_t mts_profile;
int
check_file (char *name)
......@@ -313,36 +313,42 @@ check_file (char *name)
void
read_mts_profile ()
{
char *name;
const char *p;
char *hostname = NULL;
int rc;
mh_context_t *local_profile;
mu_property_t local_profile;
p = mh_expand_name (MHLIBDIR, "mtstailor", 0);
mts_profile = mh_context_create (p, 1);
mh_context_read (mts_profile);
name = mh_expand_name (MHLIBDIR, "mtstailor", 0);
mts_profile = mh_read_property_file (name, 1);
p = mu_tilde_expansion ("~/.mtstailor", "/", NULL);
local_profile = mh_context_create (p, 1);
if (mh_context_read (local_profile) == 0)
mh_context_merge (mts_profile, local_profile);
mh_context_destroy (&local_profile);
name = mu_tilde_expansion ("~/.mtstailor", "/", NULL);
local_profile = mh_read_property_file (name, 1);
if ((p = mh_context_get_value (mts_profile, "localname", NULL)))
mh_property_merge (mts_profile, local_profile);
mu_property_destroy (&local_profile);
rc = mu_property_aget_value (mts_profile, "localname", &hostname);
if (rc == MU_ERR_NOENT)
{
rc = mu_get_host_name (&hostname);
if (rc)
{
mu_error (_("cannot get system host name: %s"), mu_strerror (rc));
exit (1);
}
}
else
{
hostname = xstrdup (p);
mu_set_user_email_domain (p);
mu_diag_funcall (MU_DIAG_ERROR, "mu_profile_aget_value", "localname", rc);
exit (1);
}
else if ((rc = mu_get_host_name (&hostname)))
mu_error (_("cannot get system host name: %s"), mu_strerror (rc));
if ((p = mh_context_get_value (mts_profile, "localdomain", NULL)))
rc = mu_property_sget_value (mts_profile, "localdomain", &p);
if (rc == 0)
{
char *newdomain;
if (!hostname)
exit (1);
newdomain = xmalloc (strlen (hostname) + 1 + strlen (p) + 1);
strcpy (newdomain, hostname);
strcat (newdomain, ".");
......@@ -355,8 +361,15 @@ read_mts_profile ()
exit (1);
}
}
if ((p = mh_context_get_value (mts_profile, "username", NULL)))
else if (rc != MU_ERR_NOENT)
{
mu_diag_funcall (MU_DIAG_ERROR, "mu_profile_sget_value",
"localdomain", rc);
exit (1);
}
rc = mu_property_sget_value (mts_profile, "username", &p);
if (rc == 0)
{
size_t len;
const char *domain;
......@@ -385,15 +398,21 @@ read_mts_profile ()
free (newemail);
}
else if (rc != MU_ERR_NOENT)
{
mu_diag_funcall (MU_DIAG_ERROR, "mu_profile_sget_value",
"username", rc);
exit (1);
}
}
mu_mailer_t
open_mailer ()
{
const char *url = mh_context_get_value (mts_profile,
"url",
"sendmail:/usr/sbin/sendmail");
const char *url = mu_mhprop_get_value (mts_profile,
"url",
"sendmail:/usr/sbin/sendmail");
mu_mailer_t mailer;
int status;
......@@ -667,8 +686,8 @@ _action_send (void *item, void *data)
if (mu_header_get_value (hdr, MU_HEADER_X_MAILER, NULL, 0, &n))
{
const char *p = mh_context_get_value (mts_profile,
"x-mailer", "yes");
const char *p = mu_mhprop_get_value (mts_profile,
"x-mailer", "yes");
if (!strcmp (p, "yes"))
mu_header_set_value (hdr, MU_HEADER_X_MAILER,
......
......@@ -165,6 +165,7 @@ mh/forw.c
mh/inc.c
mh/install-mh.c
mh/mark.c
mh/mboxprop.c
mh/mh_argp.c
mh/mh_ctx.c
mh/mh_fmtgram.y
......