Commit 727b3c75 727b3c755d6db784cedc1d334d4a70ce72543d0d by Sergey Poznyakoff

* NEWS, TODO: Update.

* examples/Makefile.am: Add aclck
* examples/aclck.c: New file. Test program for ACLs.
* include/mailutils/Makefile.am (pkginclude_HEADERS): Add acl.h,
kwd.h and vartab.h.
* include/mailutils/acl.h: New file. ACL declarations.
* include/mailutils/kwd.h: New file. Declarations for simple
string to token conversion.
* include/mailutils/vartab.h: New file. Declarations of functions
for variable expansion.
* include/mailutils/mailutils.h: Include acl.h, kwd.h and
vartab.h.
* include/mailutils/types.hin: Define mu_vartab_t

* mailbox/Makefile.am (libmailutils_la_SOURCES): Add acl.c, kwd.c,
and vartab.c.
* mailbox/acl.c: New file.
* mailbox/kwd.c: New file.
* mailbox/vartab.c: New file.

* mailbox/cfg_parser.y (parse_cidr): Fix typo.
* mailbox/list.c: Fix indentation.
* mailbox/mailbox.c (_create_mailbox): Fix type of level.
* mailbox/syslog.c: Use mu_kwd_* functions.
1 parent 24124842
2007-12-07 Sergey Poznyakoff <gray@gnu.org.ua>
* NEWS, TODO: Update.
* examples/Makefile.am: Add aclck
* examples/aclck.c: New file. Test program for ACLs.
* include/mailutils/Makefile.am (pkginclude_HEADERS): Add acl.h,
kwd.h and vartab.h.
* include/mailutils/acl.h: New file. ACL declarations.
* include/mailutils/kwd.h: New file. Declarations for simple
string to token conversion.
* include/mailutils/vartab.h: New file. Declarations of functions
for variable expansion.
* include/mailutils/mailutils.h: Include acl.h, kwd.h and
vartab.h.
* include/mailutils/types.hin: Define mu_vartab_t
* mailbox/Makefile.am (libmailutils_la_SOURCES): Add acl.c, kwd.c,
and vartab.c.
* mailbox/acl.c: New file.
* mailbox/kwd.c: New file.
* mailbox/vartab.c: New file.
* mailbox/cfg_parser.y (parse_cidr): Fix typo.
* mailbox/list.c: Fix indentation.
* mailbox/mailbox.c (_create_mailbox): Fix type of level.
* mailbox/syslog.c: Use mu_kwd_* functions.
2007-12-05 Sergey Poznyakoff <gray@gnu.org.ua>
* configure.ac: Add TCP wrappers support.
......
GNU mailutils NEWS -- history of user-visible changes. 2007-12-05
GNU mailutils NEWS -- history of user-visible changes. 2007-12-07
Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
See the end of file for copying conditions.
......@@ -151,12 +151,12 @@ functions:
New type of event, MU_EVT_MESSAGE_APPEND, is signalled whenever a new
message is appended to the mailbox.
* Quick access to a message
** Quick access to a message
A set of functions are provided for so-called `quick access' to mail
messages. FIXME: describe it.
* New `aget' and `sget' accessors for mu_url_t
** New `aget' and `sget' accessors for mu_url_t
The following new accessors are provided:
......@@ -181,20 +181,48 @@ extern int mu_url_aget_path (const mu_url_t, char **);
extern int mu_url_sget_query (const mu_url_t, const char **);
extern int mu_url_aget_query (const mu_url_t, char **);
* Incompatible change in mu_url_get_.* return value
** ACL
A set of functions implements general-purpose access control lists.
They are declared in the header file mailutils/acl.h. Currently,
these functions support IPv4 and UNIX address families. Support for
more address families, in particular IPv6, will be added in future.
The following actions can be defined in ACLs:
1. mu_acl_accept - Accept connection.
2. mu_acl_deny - Deny connection.
3. mu_acl_log - Issue a log message, using mu_diag.*
diagnostics functions.
4. mu_acl_exec - Execute an external program.
5. mu_acl_ifexec - Execute an external program and accept or
deny connection depending on its exit code.
** KWD
A set of functions is provided for translating string values to
integer tokens and vice-versa using simple translation tables.
These functions are declared in the header file mailutils/kwd.h.
** Vartab
A set of functions is provided for performing variable expansion in
strings. These functions are declared in the header file
mailutils/vartab.h.
** Incompatible change in mu_url_get_.* return value
Any mu_url_get_.* accessors return MU_ERR_ENOENT if the corresponding
field is not present in the object. Previous versions in that case
returned 0 and stored empty string in the output buffer.
* Fixed parsing of URLs similar to file:///a/b.
** Fixed parsing of URLs similar to file:///a/b.
It is parsed as an absolute file name `/a/b'.
Previous versions incorrectly understood such an URL as `a/b'
(relative file name).
* Remove v0.6 compatibility layer.
** Remove v0.6 compatibility layer.
Version 1.2:
......
GNU mailutils TODO list. 2007-11-30
GNU mailutils TODO list. 2007-12-07
Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006,
2007 Free Software Foundation, Inc.
* Documentation
* Review the code and use mu_vartab_* and mu_kwd_* functions where
necessary.
* mailbox
** Generic search interface
......
......@@ -20,6 +20,7 @@
SUBDIRS = config cpp scheme
noinst_PROGRAMS = \
aclck\
addr\
argcv\
base64\
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001, 2002, 2005,
2007 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, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301 USA */
#include <mailutils/mailutils.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
struct sockaddr *target_sa;
int target_salen;
mu_acl_t acl;
struct sockaddr *
parse_address (int *psalen, char *str)
{
struct sockaddr_in in;
struct sockaddr *sa;
in.sin_family = AF_INET;
if (inet_aton (str, &in.sin_addr) == 0)
{
mu_error ("Invalid IPv4: %s", str);
exit (1);
}
in.sin_port = 0;
*psalen = sizeof (in);
sa = malloc (*psalen);
if (!sa)
{
mu_error ("%s", mu_strerror (errno));
exit (1);
}
memcpy (sa, &in, sizeof (in));
return sa;
}
void
read_rules (FILE *fp)
{
char buf[512];
int line = 0;
int argc = 0;
char **argv;
int rc;
rc = mu_acl_create (&acl);
if (rc)
{
mu_error ("cannot create acl: %s", mu_strerror (rc));
exit (1);
}
while (fgets (buf, sizeof buf, fp))
{
unsigned long netmask;
int salen;
struct sockaddr *sa;
mu_acl_action_t action;
void *data = NULL;
char *p;
int len = strlen (buf);
if (len == 0)
continue;
if (buf[len-1] != '\n')
{
mu_error ("%d: line too long", line);
continue;
}
buf[len-1] = 0;
line++;
if (buf[0] == '#')
continue;
if (argc)
mu_argcv_free (argc, argv);
mu_argcv_get (buf, " \t", "#", &argc, &argv);
if (argc < 2)
{
mu_error ("%d: invalid input", line);
continue;
}
p = strchr (argv[1], '/');
if (p)
{
char *q;
unsigned netlen;
*p++ = 0;
netlen = strtoul (p, &q, 10);
if (*q == 0)
{
if (netlen == 0)
netmask = 0;
else
{
netmask = 0xfffffffful >> (32 - netlen);
netmask <<= (32 - netlen);
netmask = htonl (netmask);
}
}
else if (*q == '.')
{
struct in_addr addr;
if (inet_aton (p, &addr) == 0)
{
mu_error ("%d: invalid netmask", line);
continue;
}
netmask = addr.s_addr;
}
else
{
mu_error ("%d: invalid netmask", line);
continue;
}
}
else
netmask = 0xfffffffful;
sa = parse_address (&salen, argv[1]);
/* accept addr
deny addr
log addr [rest ...]
exec addr [rest ...]
execif addr rest ....]
*/
if (mu_acl_string_to_action (argv[0], &action))
{
mu_error ("%d: invalid command", line);
continue;
}
switch (action)
{
case mu_acl_accept:
case mu_acl_deny:
break;
case mu_acl_log:
case mu_acl_exec:
case mu_acl_ifexec:
data = strdup (argv[2]);
}
rc = mu_acl_append (acl, action, data, sa, salen, netmask);
if (rc)
mu_error ("%d: cannot append acl entry: %s", line,
mu_strerror (rc));
}
}
int
main (int argc, char **argv)
{
int rc;
FILE *file = NULL;
mu_acl_result_t result;
mu_set_program_name (argv[0]);
while ((rc = getopt (argc, argv, "Dd:a:f:")) != EOF)
{
switch (rc)
{
case 'D':
mu_debug_line_info = 1;
break;
case 'd':
mu_global_debug_from_string (optarg, "command line");
break;
case 'a':
target_sa = parse_address (&target_salen, optarg);
break;
case 'f':
file = fopen (optarg, "r");
if (file == 0)
{
mu_error ("cannot open file %s: %s", optarg,
mu_strerror (errno));
exit (1);
}
break;
default:
exit (1);
}
}
argv += optind;
argc -= optind;
read_rules (file ? file : stdin);
rc = mu_acl_check_sockaddr (acl, target_sa, target_salen, &result);
if (rc)
{
mu_error ("mu_acl_check_sockaddr failed: %s", mu_strerror (rc));
exit (1);
}
switch (result)
{
case mu_acl_result_undefined:
puts ("undefined");
break;
case mu_acl_result_accept:
puts ("accept");
break;
case mu_acl_result_deny:
puts ("deny");
break;
}
exit (0);
}
......@@ -32,6 +32,7 @@ DISTCLEANFILES = types.h
pkginclude_DATA = types.h
pkginclude_HEADERS = \
acl.h\
address.h\
argcv.h\
assoc.h\
......@@ -52,6 +53,7 @@ pkginclude_HEADERS = \
guile.h\
header.h\
iterator.h\
kwd.h\
ldap.h\
libargp.h\
libcfg.h\
......@@ -84,6 +86,7 @@ pkginclude_HEADERS = \
sql.h\
tls.h\
url.h\
vartab.h\
version.h
nobase_pkginclude_HEADERS = \
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2007 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/>. */
#ifndef _MAILUTILS_ACL_H
#define _MAILUTILS_ACL_H
#include <mailutils/types.h>
#include <mailutils/iterator.h>
typedef struct _mu_acl *mu_acl_t;
typedef enum mu_acl_action
{
mu_acl_accept,
mu_acl_deny,
mu_acl_log,
mu_acl_exec,
mu_acl_ifexec
}
mu_acl_action_t;
typedef enum mu_acl_result
{
mu_acl_result_undefined,
mu_acl_result_accept,
mu_acl_result_deny
}
mu_acl_result_t;
struct sockaddr;
struct in_addr;
int mu_acl_create (mu_acl_t *acl);
int mu_acl_destroy (mu_acl_t *acl);
int mu_acl_count (mu_acl_t acl, size_t *pcount);
int mu_acl_get_debug (mu_acl_t acl, mu_debug_t *pdebug);
int mu_acl_set_debug (mu_acl_t acl, mu_debug_t debug);
int mu_acl_get_iterator (mu_acl_t acl, mu_iterator_t *pitr);
int mu_acl_append (mu_acl_t acl, mu_acl_action_t act, void *data,
struct sockaddr *sa, int salen,
unsigned long netmask);
int mu_acl_prepend (mu_acl_t acl, mu_acl_action_t act, void *data,
struct sockaddr *sa, int salen, unsigned long netmask);
int mu_acl_insert (mu_acl_t acl, size_t pos, int before,
mu_acl_action_t act, void *data,
struct sockaddr *sa, int salen, unsigned long netmask);
int mu_acl_check_ipv4 (mu_acl_t acl, unsigned int addr, mu_acl_result_t *pres);
int mu_acl_check_inaddr (mu_acl_t acl, struct in_addr *inp,
mu_acl_result_t *pres);
int mu_acl_check_sockaddr (mu_acl_t acl, struct sockaddr *sa, int salen,
mu_acl_result_t *pres);
int mu_acl_check_fd (mu_acl_t acl, int fd, mu_acl_result_t *pres);
int mu_acl_action_to_string (mu_acl_action_t act, const char **pstr);
int mu_acl_string_to_action (const char *str, mu_acl_action_t *pres);
#endif
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2007 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/>. */
#ifndef _MAILUTILS_KWD_H
#define _MAILUTILS_KWD_H
typedef struct mu_kwd mu_kwd_t;
struct mu_kwd
{
char *name;
int tok;
};
int mu_kwd_xlat_name (mu_kwd_t *kwtab, const char *str, int *pres);
int mu_kwd_xlat_name_ci (mu_kwd_t *kwtab, const char *str, int *pres);
int mu_kwd_xlat_name_len (mu_kwd_t *kwtab, const char *str, size_t len,
int *pres);
int mu_kwd_xlat_name_len_ci (mu_kwd_t *kwtab, const char *str, size_t len,
int *pres);
int mu_kwd_xlat_tok (mu_kwd_t *kwtab, int tok, const char **pres);
#endif
......@@ -17,6 +17,7 @@
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA */
#include <mailutils/acl.h>
#include <mailutils/address.h>
#include <mailutils/argcv.h>
#include <mailutils/attribute.h>
......@@ -30,6 +31,7 @@
#include <mailutils/folder.h>
#include <mailutils/header.h>
#include <mailutils/iterator.h>
#include <mailutils/kwd.h>
#include <mailutils/libsieve.h>
#include <mailutils/list.h>
#include <mailutils/locker.h>
......@@ -54,6 +56,7 @@
#include <mailutils/url.h>
#include <mailutils/gocs.h>
#include <mailutils/version.h>
#include <mailutils/vartab.h>
#ifdef MU_COMPAT
# error "Version 0.6 is no longer supported. Please, update your program."
......
......@@ -96,6 +96,7 @@ typedef struct _mu_record *mu_record_t;
typedef struct _mu_stream *mu_stream_t;
typedef struct _mu_ticket *mu_ticket_t;
typedef struct _mu_url *mu_url_t;
typedef struct _mu_vartab *mu_vartab_t;
typedef struct _mu_wicket *mu_wicket_t;
typedef void *mu_transport_t;
typedef struct _mu_assoc *mu_assoc_t;
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2007 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/>. */
#ifndef _MAILUTILS_VARTAB_H
#define _MAILUTILS_VARTAB_H
#include <mailutils/types.h>
typedef int (*mu_var_expansion_fp) (const char *name, void *data, char **p);
typedef void (*mu_var_free_fp) (void *data, char *value);
int mu_vartab_create (mu_vartab_t *pvar);
int mu_vartab_destroy (mu_vartab_t *pvar);
int mu_vartab_define (mu_vartab_t var, const char *name, const char *value,
int isstatic);
int mu_vartab_define_exp (mu_vartab_t var, const char *name,
mu_var_expansion_fp fun, mu_var_free_fp free,
void *data);
int mu_vartab_count (mu_vartab_t vt, size_t *pcount);
int mu_vartab_getvar (mu_vartab_t vt, const char *name, const char **pvalue);
int mu_vartab_expand (mu_vartab_t vt, const char *str, char **pres);
#endif
......@@ -36,6 +36,7 @@ AM_CPPFLAGS = \
EXTRA_DIST = errors muerrno.cin parsedate.y fgetpwent.c cfg_parser.y cfg_parser.h inttostr.c inttostr.h
libmailutils_la_SOURCES = \
acl.c\
address.c\
amd.c\
argcv.c\
......@@ -65,6 +66,7 @@ libmailutils_la_SOURCES = \
gocs.c\
header.c\
iterator.c\
kwd.c\
list.c\
locale.c\
locker.c\
......@@ -102,6 +104,7 @@ libmailutils_la_SOURCES = \
tcp.c\
ticket.c\
url.c\
vartab.c\
version.c\
wicket.c\
imaxtostr.c offtostr.c umaxtostr.c intprops.h
......
......@@ -730,7 +730,7 @@ parse_cidr (struct scan_tree_data *sdata, const mu_cfg_node_t *node,
char astr[16], *p, *s;
p = strchr (node->tag_label, '/');
if (*p)
if (p)
{
int len = p - node->tag_label;
if (len > sizeof astr - 1) {
......@@ -780,10 +780,11 @@ parse_cidr (struct scan_tree_data *sdata, const mu_cfg_node_t *node,
int i;
unsigned short x;
addr.s_addr = 0;
p = node->tag_label;
for (i = 0; i < 3; i++)
{
STRxTONUM(p, unsigned short, x, 255, sdata->tree->debug);
STRxTONUM (p, unsigned short, x, 255, sdata->tree->debug);
if (*p != '.')
break;
addr.s_addr = (addr.s_addr << 8) + x;
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2007 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/>. */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include <mailutils/kwd.h>
#include <mailutils/errno.h>
int
mu_kwd_xlat_name_len (mu_kwd_t *kwtab, const char *str, size_t len, int *pres)
{
for (; kwtab->name; kwtab++)
{
size_t kwlen = strlen (kwtab->name);
if (kwlen == len && memcmp (kwtab->name, str, len) == 0)
{
*pres = kwtab->tok;
return 0;
}
}
return MU_ERR_NOENT;
}
int
mu_kwd_xlat_name_len_ci (mu_kwd_t *kwtab, const char *str, size_t len,
int *pres)
{
for (; kwtab->name; kwtab++)
{
size_t kwlen = strlen (kwtab->name);
if (kwlen == len && strncasecmp (kwtab->name, str, len) == 0)
{
*pres = kwtab->tok;
return 0;
}
}
return MU_ERR_NOENT;
}
int
mu_kwd_xlat_name (mu_kwd_t *kwtab, const char *str, int *pres)
{
for (; kwtab->name; kwtab++)
if (strcmp (kwtab->name, str) == 0)
{
*pres = kwtab->tok;
return 0;
}
return MU_ERR_NOENT;
}
int
mu_kwd_xlat_name_ci (mu_kwd_t *kwtab, const char *str, int *pres)
{
for (; kwtab->name; kwtab++)
if (strcasecmp (kwtab->name, str) == 0)
{
*pres = kwtab->tok;
return 0;
}
return MU_ERR_NOENT;
}
int
mu_kwd_xlat_tok (mu_kwd_t *kwtab, int tok, const char **pres)
{
for (; kwtab->name; kwtab++)
if (kwtab->tok == tok)
{
*pres = kwtab->name;
return 0;
}
return MU_ERR_NOENT;
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001, 2004, 2005, 2007 Free Software Foundation, Inc.
Copyright (C) 1999, 2000, 2001, 2004, 2005, 2007 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
......
......@@ -91,7 +91,7 @@ _create_mailbox (mu_mailbox_t *pmbox, const char *name)
if (mu_registrar_lookup (name, MU_FOLDER_ATTRIBUTE_FILE, &record, NULL) == 0)
{
unsigned level;
mu_log_level_t level;
int (*m_init) (mu_mailbox_t) = NULL;
int (*u_init) (mu_url_t) = NULL;
......
......@@ -20,38 +20,9 @@
#include <syslog.h>
#include <string.h>
#include <mailutils/diag.h>
#include <mailutils/kwd.h>
struct kw_int
{
char *name;
int tok;
};
static int
syslog_to_n (struct kw_int *kw, char *str, int *pint)
{
if (strncasecmp (str, "LOG_", 4) == 0)
str += 4;
for (; kw->name; kw++)
if (strcasecmp (kw->name, str) == 0)
{
*pint = kw->tok;
return 0;
}
return 1;
}
static const char *
n_to_syslog (struct kw_int *kw, int n)
{
for (; kw->name; kw++)
if (kw->tok == n)
return kw->name;
return NULL;
}
static struct kw_int kw_facility[] = {
static mu_kwd_t kw_facility[] = {
{ "USER", LOG_USER },
{ "DAEMON", LOG_DAEMON },
{ "AUTH", LOG_AUTH },
......@@ -69,6 +40,14 @@ static struct kw_int kw_facility[] = {
{ NULL }
};
static int
syslog_to_n (mu_kwd_t *kw, char *str, int *pint)
{
if (strncasecmp (str, "LOG_", 4) == 0)
str += 4;
return mu_kwd_xlat_name_ci (kw, str, pint);
}
int
mu_string_to_syslog_facility (char *str, int *pfacility)
{
......@@ -78,10 +57,12 @@ mu_string_to_syslog_facility (char *str, int *pfacility)
const char *
mu_syslog_facility_to_string (int n)
{
return n_to_syslog (kw_facility, n);
const char *res = NULL;
mu_kwd_xlat_tok (kw_facility, n, &res);
return res;
}
static struct kw_int kw_prio[] = {
static mu_kwd_t kw_prio[] = {
{ "EMERG", LOG_EMERG },
{ "ALERT", LOG_ALERT },
{ "CRIT", LOG_CRIT },
......@@ -102,7 +83,9 @@ mu_string_to_syslog_priority (char *str, int *pprio)
const char *
mu_syslog_priority_to_string (int n)
{
return n_to_syslog (kw_prio, n);
const char *res = NULL;
mu_kwd_xlat_tok (kw_prio, n, &res);
return res;
}
int
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2007 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/>. */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <mailutils/assoc.h>
#include <mailutils/stream.h>
#include <mailutils/errno.h>
#include <mailutils/iterator.h>
#include <mailutils/vartab.h>
struct _mu_vartab
{
mu_assoc_t assoc;
mu_stream_t stream;
char *buf;
size_t bufsize;
};
#define MU_VARDEFN_STATIC 0x1
#define MU_VARDEFN_FUNC 0x2
struct vardefn
{
int flags;
char *value;
mu_var_expansion_fp fun;
mu_var_free_fp free;
void *data;
};
int
mu_vartab_create (mu_vartab_t *pvar)
{
int rc;
struct _mu_vartab *p = calloc (1, sizeof *p);
if (!p)
return ENOMEM;
rc = mu_assoc_create (&p->assoc, sizeof (struct vardefn), 0);
if (rc)
{
free (p);
return rc;
}
*pvar = p;
return 0;
}
static void
vardefn_free (struct vardefn *vd)
{
if (vd->value)
{
if (vd->free)
vd->free (vd->data, vd->value);
else if (!(vd->flags & MU_VARDEFN_STATIC))
free (vd->value);
}
memset (vd, 0, sizeof vd);
}
int
mu_vartab_destroy (mu_vartab_t *pvar)
{
int rc;
mu_vartab_t var = *pvar;
mu_iterator_t itr;
if (!var)
return EINVAL;
rc = mu_assoc_get_iterator (var->assoc, &itr);
if (rc)
return rc;
for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
mu_iterator_next (itr))
{
struct vardefn *vd;
mu_iterator_current (itr, (void**)&vd);
vardefn_free (vd);
}
mu_iterator_destroy (&itr);
mu_assoc_destroy (&var->assoc);
mu_stream_destroy (&var->stream, NULL);
free (var->buf);
free (var);
*pvar = NULL;
return 0;
}
int
mu_vartab_define (mu_vartab_t var, const char *name, const char *value,
int isstatic)
{
int rc;
struct vardefn *vd;
if (!var)
return EINVAL;
rc = mu_assoc_ref_install (var->assoc, name, (void **) &vd);
if (rc == MU_ERR_EXISTS)
vardefn_free (vd);
else if (rc != 0)
return rc;
if (isstatic)
{
vd->flags = MU_VARDEFN_STATIC;
vd->value = (char*) value;
}
else
{
vd->flags = 0;
vd->value = strdup (value);
if (!vd->value)
return ENOMEM;
}
return 0;
}
int
mu_vartab_define_exp (mu_vartab_t var, const char *name,
mu_var_expansion_fp fun, mu_var_free_fp free,
void *data)
{
int rc;
struct vardefn *vd;
if (!var)
return EINVAL;
rc = mu_assoc_ref_install (var->assoc, name, (void **) &vd);
if (rc == MU_ERR_EXISTS)
vardefn_free (vd);
else if (rc != 0)
return rc;
vd->flags = MU_VARDEFN_FUNC;
vd->fun = fun;
vd->free = free;
vd->data = data;
return 0;
}
int
mu_vartab_count (mu_vartab_t vt, size_t *pcount)
{
if (!vt)
return EINVAL;
return mu_assoc_count (vt->assoc, pcount);
}
static int
vardefn_expand (const char *name, struct vardefn *vd, const char **pvalue)
{
if (!vd->value)
{
if (vd->fun)
{
int rc = vd->fun (name, vd->data, &vd->value);
if (rc)
return rc;
}
else
return EINVAL;
}
*pvalue = vd->value;
return 0;
}
int
mu_vartab_getvar (mu_vartab_t vt, const char *name, const char **pvalue)
{
struct vardefn *vdefn;
if (!vt)
return EINVAL;
vdefn = mu_assoc_ref (vt->assoc, name);
if (!vdefn)
return MU_ERR_NOENT;
return vardefn_expand (name, vdefn, pvalue);
}
static char *
copy_name (mu_vartab_t vt, const char *name, size_t len)
{
if (len + 1 > vt->bufsize)
{
char *p = realloc (vt->buf, len + 1);
if (!p)
return NULL;
vt->buf = p;
vt->bufsize = len + 1;
}
memcpy (vt->buf, name, len);
vt->buf[len] = 0;
return vt->buf;
}
int
mu_vartab_expand (mu_vartab_t vt, const char *str, char **pres)
{
int rc;
mu_off_t size;
const char *p;
if (!vt)
return EINVAL;
if (!vt->stream)
{
rc = mu_memory_stream_create (&vt->stream, NULL, MU_STREAM_NO_CHECK);
if (rc)
return rc;
rc = mu_stream_open (vt->stream);
}
else
mu_stream_truncate (vt->stream, 0);
mu_stream_seek (vt->stream, 0, SEEK_SET);
for (p = str; *p; )
{
if (*p == '$')
{
switch (*++p)
{
case '$':
mu_stream_sequential_write (vt->stream, str, p - str);
str = p + 1;
p = str + 1;
break;
case '{':
{
const char *e = strchr (p + 1, '}');
if (e)
{
const char *pvalue;
size_t len = e - p - 1;
char *name = copy_name (vt, p + 1, len);
rc = mu_vartab_getvar (vt, name, &pvalue);
if (rc == 0)
{
mu_stream_sequential_write (vt->stream, str,
p - str - 1);
mu_stream_sequential_write (vt->stream, pvalue,
strlen (pvalue));
str = e + 1;
p = str + 1;
}
else if (rc == MU_ERR_NOENT)
p = e + 1;
else
return rc;
}
else
p++;
}
break;
default:
{
char *name = copy_name (vt, p, 1);
const char *pvalue;
rc = mu_vartab_getvar (vt, name, &pvalue);
if (rc == 0)
{
mu_stream_sequential_write (vt->stream, str,
p - str - 1);
mu_stream_sequential_write (vt->stream, pvalue,
strlen (pvalue));
str = p + 1;
p = str + 1;
}
else if (rc == MU_ERR_NOENT)
p++;
}
break;
}
}
else
p++;
}
if (p > str)
mu_stream_sequential_write (vt->stream, str, p - str);
mu_stream_size (vt->stream, &size);
*pres = malloc (size + 1);
if (!*pres)
return ENOMEM;
mu_stream_read (vt->stream, *pres, size, 0, NULL);
(*pres)[size] = 0;
return 0;
}