Commit 7c8e01ff 7c8e01ff3f278a56067353b8dd7030e3cfc47495 by Sergey Poznyakoff

Change configuration file parser based on the lexer/parser from GNU Dico.

* auth/gsasl.c: Remove deprecated data types.
* imap4d/auth_gsasl.c (retrieve_password): Minor fix.

* imap4d/imap4d.c, imap4d/imap4d.h, imap4d/namespace.c,
lib/tcpwrap.c, libcfg/acl.c, libcfg/auth.c, libcfg/common.c,
libcfg/ldap.c, libcfg/sieve.c, libcfg/sql.c, maidag/maidag.c,
mail.local/main.c, mailbox/gdebug.c, mailbox/msrv.c,
mimeview/mimeview.c, pop3d/bulletin.c, pop3d/pop3d.c,
pop3d/pop3d.h, sieve/sieve.c: Reflect changes to the configuration
system.

* mailbox/Makefile.am (AM_LFLAGS): New variable.
(EXTRA_DIST) Add cfg_lexer.l.
(libmailutils_la_SOURCES): Add alloc.c and opool.c
(BUILT_SOURCES): Add cfg_lexer.c.
(cfg_lexer.c): New goal.
* mailbox/alloc.c, mailbox/opool.c: New files.
* mailbox/cfg_lexer.c: Remove.
* mailbox/cfg_lexer.l: New file.
* mailbox/.cvsignore: Add cfg_lexer.c.

* include/mailutils/Makefile.am: Add alloc.h and opool.h
* include/mailutils/alloc.h: New file.
* include/mailutils/opool.h: New file.

* include/mailutils/cfg.h (mu_cfg_lexer_t,mu_cfg_alloc_t)
(mu_cfg_free_t): Remove types.
(MU_CFG_STRING, MU_CFG_LIST, MU_CFG_ARRAY): New defines.
(mu_config_value_t): New data type.
(struct mu_cfg_node): Change type of `label'.
(struct mu_cfg_tree): Remove `alloc', `free'.
New member `pool'.
(mu_cfg_parse): Simplify the signature by removing superfluous
arguments.
(mu_cfg_tie_in): Remove.
(mu_cfg_lexer_pool): New function.
(mu_cfg_find_node, mu_cfg_find_node_label): Remove.
(mu_cfg_callback_t): Change signature.
(MU_CFG_LIST_MASK): New define.
(MU_CFG_LIST_OF, MU_CFG_TYPE, MU_CFG_IS_LIST): New defines.
(mu_cfg_get_debug): New function.
(mu_cfg_assert_value_type, mu_cfg_string_value_cb): New functions.
(mu_cfg_tree_set_alloc, mu_cfg_tree_alloc): Remove.
* mailbox/cfg_driver.c: Adapt for new node structure.
(mu_cfg_assert_value_type, mu_cfg_string_value_cb): New function.
* mailbox/cfg_format.c: Adapt for new node structure.
* mailbox/cfg_parser.y: Adapt for changes in cfg data types and
lexer.

* include/mailutils/mailutils.h: Include alloc.h and opool.h
* include/mailutils/mu_auth.h (mu_authorization_add_module)
(mu_authentication_add_module): New prototypes.

* include/mailutils/syslog.h (mu_string_to_syslog_facility)
(mu_string_to_syslog_priority): First argument is const char *.
* mailbox/syslog.c: Likewise.

* include/mailutils/types.hin (mu_opool_t): New type.
* mailbox/list.c (mu_list_get_comparator): Add missing return
statement.
1 parent e1db594c
2008-08-19 Sergey Poznyakoff <gray@gnu.org.ua>
Change configuration file parser based on the lexer/parser from
GNU Dico.
* auth/gsasl.c: Remove deprecated data types.
* imap4d/auth_gsasl.c (retrieve_password): Minor fix.
* imap4d/imap4d.c, imap4d/imap4d.h, imap4d/namespace.c,
lib/tcpwrap.c, libcfg/acl.c, libcfg/auth.c, libcfg/common.c,
libcfg/ldap.c, libcfg/sieve.c, libcfg/sql.c, maidag/maidag.c,
mail.local/main.c, mailbox/gdebug.c, mailbox/msrv.c,
mimeview/mimeview.c, pop3d/bulletin.c, pop3d/pop3d.c,
pop3d/pop3d.h, sieve/sieve.c: Reflect changes to the configuration
system.
* mailbox/Makefile.am (AM_LFLAGS): New variable.
(EXTRA_DIST) Add cfg_lexer.l.
(libmailutils_la_SOURCES): Add alloc.c and opool.c
(BUILT_SOURCES): Add cfg_lexer.c.
(cfg_lexer.c): New goal.
* mailbox/alloc.c, mailbox/opool.c: New files.
* mailbox/cfg_lexer.c: Remove.
* mailbox/cfg_lexer.l: New file.
* mailbox/.cvsignore: Add cfg_lexer.c.
* include/mailutils/Makefile.am: Add alloc.h and opool.h
* include/mailutils/alloc.h: New file.
* include/mailutils/opool.h: New file.
* include/mailutils/cfg.h (mu_cfg_lexer_t,mu_cfg_alloc_t)
(mu_cfg_free_t): Remove types.
(MU_CFG_STRING, MU_CFG_LIST, MU_CFG_ARRAY): New defines.
(mu_config_value_t): New data type.
(struct mu_cfg_node): Change type of `label'.
(struct mu_cfg_tree): Remove `alloc', `free'.
New member `pool'.
(mu_cfg_parse): Simplify the signature by removing superfluous
arguments.
(mu_cfg_tie_in): Remove.
(mu_cfg_lexer_pool): New function.
(mu_cfg_find_node, mu_cfg_find_node_label): Remove.
(mu_cfg_callback_t): Change signature.
(MU_CFG_LIST_MASK): New define.
(MU_CFG_LIST_OF, MU_CFG_TYPE, MU_CFG_IS_LIST): New defines.
(mu_cfg_get_debug): New function.
(mu_cfg_assert_value_type, mu_cfg_string_value_cb): New functions.
(mu_cfg_tree_set_alloc, mu_cfg_tree_alloc): Remove.
* mailbox/cfg_driver.c: Adapt for new node structure.
(mu_cfg_assert_value_type, mu_cfg_string_value_cb): New function.
* mailbox/cfg_format.c: Adapt for new node structure.
* mailbox/cfg_parser.y: Adapt for changes in cfg data types and
lexer.
* include/mailutils/mailutils.h: Include alloc.h and opool.h
* include/mailutils/mu_auth.h (mu_authorization_add_module)
(mu_authentication_add_module): New prototypes.
* include/mailutils/syslog.h (mu_string_to_syslog_facility)
(mu_string_to_syslog_priority): First argument is const char *.
* mailbox/syslog.c: Likewise.
* include/mailutils/types.hin (mu_opool_t): New type.
* mailbox/list.c (mu_list_get_comparator): Add missing return
statement.
2008-08-18 Sergey Poznyakoff <gray@gnu.org.ua>
Autobuild setup.
......
......@@ -52,7 +52,7 @@ mu_gsasl_module_init (void *data)
}
struct _gsasl_stream {
Gsasl_session_ctx *sess_ctx; /* Context */
Gsasl_session *sess_ctx; /* Context */
int last_err; /* Last Gsasl error code */
mu_stream_t stream; /* I/O stream */
......@@ -238,7 +238,7 @@ _gsasl_wait (mu_stream_t stream, int *pflags, struct timeval *tvp)
int
mu_gsasl_stream_create (mu_stream_t *stream, mu_stream_t transport,
Gsasl_session_ctx *ctx, int flags)
Gsasl_session *ctx, int flags)
{
struct _gsasl_stream *s;
int rc;
......
......@@ -175,7 +175,7 @@ static int
retrieve_password (Gsasl *ctx, Gsasl_session *sctx)
{
char **username = gsasl_callback_hook_get (ctx);
char *authid = gsasl_property_get (sctx, GSASL_AUTHID);
const char *authid = gsasl_property_get (sctx, GSASL_AUTHID);
if (username && *username == 0)
*username = strdup (authid);
......
......@@ -169,27 +169,37 @@ imap4d_parse_opt (int key, char *arg, struct argp_state *state)
}
static int
cb_other (mu_debug_t debug, void *data, char *arg)
cb2_namespace (mu_debug_t debug, const char *arg, void *data)
{
set_namespace (NS_OTHER, arg);
int what = (int) data;
set_namespace (what, arg);
return 0;
}
static int
cb_shared (mu_debug_t debug, void *data, char *arg)
cb_other (mu_debug_t debug, void *data, mu_config_value_t *val)
{
set_namespace (NS_SHARED, arg);
return mu_cfg_string_value_cb (debug, val, cb2_namespace, (void*)NS_OTHER);
}
static int
cb_shared (mu_debug_t debug, void *data, mu_config_value_t *val)
{
return mu_cfg_string_value_cb (debug, val, cb2_namespace, (void*)NS_SHARED);
return 0;
}
static int
cb_mode (mu_debug_t debug, void *data, char *arg)
cb_mode (mu_debug_t debug, void *data, mu_config_value_t *val)
{
char *p;
home_dir_mode = strtoul (arg, &p, 8);
if (mu_cfg_assert_value_type (val, MU_CFG_STRING, debug))
return 1;
home_dir_mode = strtoul (val->v.string, &p, 8);
if (p[0] || (home_dir_mode & ~0777))
mu_cfg_format_error (debug, MU_DEBUG_ERROR,
_("Invalid mode specification: %s"), arg);
_("Invalid mode specification: %s"),
val->v.string);
return 0;
}
......@@ -239,22 +249,24 @@ parse_preauth_scheme (mu_debug_t debug, const char *scheme, mu_url_t url)
preauth stdio
*/
static int
cb_preauth (mu_debug_t debug, void *data, char *arg)
cb_preauth (mu_debug_t debug, void *data, mu_config_value_t *val)
{
if (strcmp (arg, "stdio") == 0)
if (mu_cfg_assert_value_type (val, MU_CFG_STRING, debug))
return 1;
if (strcmp (val->v.string, "stdio") == 0)
preauth_mode = preauth_stdio;
else if (strcmp (arg, "ident") == 0)
return parse_preauth_scheme (debug, arg, NULL);
else if (arg[0] == '/')
else if (strcmp (val->v.string, "ident") == 0)
return parse_preauth_scheme (debug, val->v.string, NULL);
else if (val->v.string[0] == '/')
{
preauth_program = xstrdup (arg);
preauth_program = xstrdup (val->v.string);
preauth_mode = preauth_prog;
}
else
{
mu_url_t url;
char *scheme;
int rc = mu_url_create (&url, arg);
int rc = mu_url_create (&url, val->v.string);
if (rc)
{
......@@ -266,7 +278,7 @@ cb_preauth (mu_debug_t debug, void *data, char *arg)
if (rc)
{
mu_cfg_format_error (debug, MU_DEBUG_ERROR,
"%s: %s", arg, mu_strerror (rc));
"%s: %s", val->v.string, mu_strerror (rc));
return 1;
}
......@@ -301,7 +313,7 @@ static struct mu_cfg_param imap4d_cfg_param[] = {
{ "home-dir-mode", mu_cfg_callback, NULL, 0, cb_mode,
N_("File mode for creating user home directories (octal)."),
N_("mode") },
{ "tls-required", mu_cfg_int, &tls_required, 0, NULL,
{ "tls-required", mu_cfg_bool, &tls_required, 0, NULL,
N_("Always require STARTTLS before entering authentication phase.") },
{ "preauth", mu_cfg_callback, NULL, 0, cb_preauth,
N_("Configure PREAUTH mode. MODE is one of:\n"
......
......@@ -100,6 +100,8 @@
#include <mailutils/pam.h>
#include <mailutils/acl.h>
#include <mailutils/server.h>
#include <mailutils/argcv.h>
#include <mailutils/alloc.h>
#include <mu_asprintf.h>
#include <mu_umaxtostr.h>
......@@ -271,7 +273,7 @@ extern int imap4d_bye (int);
extern int imap4d_bye0 (int reason, struct imap4d_command *command);
/* Namespace functions */
extern int set_namespace (int i, char *str);
extern int set_namespace (int i, const char *str);
extern int namespace_init (char *path);
extern char * namespace_getfullpath (char *name, const char *delim);
extern char * namespace_checkfullpath (char *name, const char *pattern,
......
......@@ -18,6 +18,8 @@
#include "imap4d.h"
/* FIXME: Rewrite using mu_list_t */
/*FIXME: should be global? */
typedef int (*nsfp_t) (void *closure, int ns, char *path, int delim);
......@@ -31,34 +33,20 @@ struct namespace_t namespace[NS_MAX];
/* Note: str is not supposed to be NULL */
int
set_namespace (int i, char *str)
set_namespace (int i, const char *str)
{
char *p, *save;
struct namespace_t ns;
/* first, estimate the number of items in subdir_v array: */
ns.subdir_c = 1;
for (p = strchr (str, ':'); p && *p; p = strchr (p + 1, ':'))
ns.subdir_c++;
/* Now allocate the memory */
ns.subdir_v = calloc (ns.subdir_c, sizeof (ns.subdir_v[0]));
/* Fill in the array */
if (ns.subdir_c == 1)
{
ns.subdir_v[0] = mu_normalize_path (strdup (str), "/");
}
else
{
ns.subdir_c = 0;
for (p = strtok_r (str, ":", &save); p; p = strtok_r (NULL, ":", &save))
{
ns.subdir_v[ns.subdir_c++] = mu_normalize_path (strdup (p), "/");
}
}
namespace[i] = ns;
struct namespace_t *ns = namespace + i;
int argc;
char **argv;
mu_argcv_get (str, ":", NULL, &argc, &argv);
ns->subdir_v = mu_realloc (ns->subdir_v,
(ns->subdir_c + argc) * sizeof (ns->subdir_v[0]));
for (i = 0; i < argc; i++)
ns->subdir_v[ns->subdir_c++] = mu_normalize_path (argv[i], "/");
/* Free only argv, not its members */
free (argv);
return 0;
}
......
## Process this file with GNU Automake to create Makefile.in
## Copyright (C) 2000, 2001, 2002, 2003,
## 2004, 2005, 2007 Free Software Foundation, Inc.
## 2004, 2005, 2007, 2008 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
......@@ -34,6 +34,7 @@ pkginclude_DATA = types.h
pkginclude_HEADERS = \
acl.h\
address.h\
alloc.h\
argcv.h\
assoc.h\
attribute.h\
......@@ -73,6 +74,7 @@ pkginclude_HEADERS = \
nls.h\
nntp.h\
observer.h\
opool.h\
pam.h\
parse822.h\
pop3.h\
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2008 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 */
#ifndef _MAILUTILS_ALLOC_H
#define _MAILUTILS_ALLOC_H
#include <mailutils/types.h>
# ifndef MU_ATTRIBUTE_NORETURN
# define MU_ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
# endif
extern void (*mu_alloc_die_hook) (void);
void mu_alloc_die (void) MU_ATTRIBUTE_NORETURN;
void *mu_alloc (size_t);
void *mu_calloc (size_t, size_t);
void *mu_zalloc (size_t size);
void *mu_realloc (void *, size_t);
char *mu_strdup (const char *);
void *mu_2nrealloc (void *, size_t *, size_t);
#endif
......@@ -20,6 +20,7 @@
#include <mailutils/list.h>
#include <mailutils/debug.h>
#include <mailutils/opool.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
......@@ -33,14 +34,32 @@ typedef struct mu_cfg_node mu_cfg_node_t;
typedef struct mu_cfg_locus mu_cfg_locus_t;
typedef struct mu_cfg_tree mu_cfg_tree_t;
typedef int (*mu_cfg_lexer_t) (void *ptr, mu_debug_t dbg);
typedef void *(*mu_cfg_alloc_t) (size_t size);
typedef void (*mu_cfg_free_t) (void *ptr);
#define MU_CFG_STRING 0
#define MU_CFG_LIST 1
#define MU_CFG_ARRAY 2
typedef struct mu_config_value mu_config_value_t;
struct mu_config_value
{
int type;
union
{
mu_list_t list;
const char *string;
struct
{
size_t c;
mu_config_value_t *v;
} arg;
} v;
};
enum mu_cfg_node_type
{
mu_cfg_node_undefined,
mu_cfg_node_tag,
mu_cfg_statement,
mu_cfg_node_tag=mu_cfg_statement, /* FIXME: remove */
mu_cfg_node_param
};
......@@ -55,8 +74,8 @@ struct mu_cfg_node
mu_cfg_node_t *next;
mu_cfg_locus_t locus;
enum mu_cfg_node_type type;
char *tag_name;
char *tag_label;
char *tag;
mu_config_value_t *label;
mu_cfg_node_t *node;
};
......@@ -64,19 +83,14 @@ struct mu_cfg_tree
{
mu_cfg_node_t *node;
mu_debug_t debug;
mu_cfg_alloc_t alloc;
mu_cfg_free_t free;
mu_opool_t pool;
};
int mu_cfg_parse (mu_cfg_tree_t **ptree,
void *data,
mu_cfg_lexer_t lexer,
mu_debug_t debug,
mu_cfg_alloc_t alloc,
mu_cfg_free_t free);
int mu_cfg_parse (mu_cfg_tree_t **ptree);
extern mu_cfg_locus_t mu_cfg_locus;
extern int mu_cfg_tie_in;
mu_opool_t mu_cfg_lexer_pool (void);
void mu_cfg_perror (const mu_cfg_locus_t *, const char *, ...);
void mu_cfg_format_error (mu_debug_t debug, size_t, const char *fmt, ...);
......@@ -96,10 +110,6 @@ int mu_cfg_postorder (mu_cfg_node_t *node,
mu_cfg_iter_func_t fun, mu_cfg_iter_func_t endfun,
void *data);
int mu_cfg_find_node (mu_cfg_node_t *tree, const char *path,
mu_cfg_node_t **pval);
int mu_cfg_find_node_label (mu_cfg_node_t *tree, const char *path,
const char **pval);
/* Table-driven parsing */
enum mu_cfg_param_data_type
......@@ -122,7 +132,12 @@ enum mu_cfg_param_data_type
mu_cfg_section
};
typedef int (*mu_cfg_callback_t) (mu_debug_t, void *, char *);
#define MU_CFG_LIST_MASK 0x8000
#define MU_CFG_LIST_OF(t) ((t) | MU_CFG_LIST_MASK)
#define MU_CFG_TYPE(t) ((t) & ~MU_CFG_LIST_MASK)
#define MU_CFG_IS_LIST(t) ((t) & MU_CFG_LIST_MASK)
typedef int (*mu_cfg_callback_t) (mu_debug_t, void *, mu_config_value_t *);
struct mu_cfg_param
{
......@@ -218,6 +233,8 @@ int mu_config_register_plain_section (const char *parent_path,
const char *ident,
struct mu_cfg_param *params);
mu_debug_t mu_cfg_get_debug (void);
#define MU_PARSE_CONFIG_GLOBAL 0x1
#define MU_PARSE_CONFIG_VERBOSE 0x2
#define MU_PARSE_CONFIG_DUMP 0x4
......@@ -240,6 +257,11 @@ void mu_format_config_tree (mu_stream_t stream, const char *progname,
int mu_cfg_tree_reduce (mu_cfg_tree_t *parse_tree, const char *progname,
struct mu_cfg_param *progparam,
int flags, void *target_ptr);
int mu_cfg_assert_value_type (mu_config_value_t *val, int type,
mu_debug_t debug);
int mu_cfg_string_value_cb (mu_debug_t debug, mu_config_value_t *val,
int (*fun) (mu_debug_t, const char *, void *),
void *data);
int mu_get_config (const char *file, const char *progname,
struct mu_cfg_param *progparam, int flags,
......@@ -248,14 +270,12 @@ int mu_get_config (const char *file, const char *progname,
int mu_cfg_tree_create (struct mu_cfg_tree **ptree);
void mu_cfg_tree_set_debug (struct mu_cfg_tree *tree, mu_debug_t debug);
void mu_cfg_tree_set_alloc (struct mu_cfg_tree *tree,
mu_cfg_alloc_t alloc, mu_cfg_free_t free);
void *mu_cfg_tree_alloc (struct mu_cfg_tree *tree, size_t size);
void mu_cfg_tree_free (struct mu_cfg_tree *tree, void *mem);
mu_cfg_node_t *mu_cfg_tree_create_node (struct mu_cfg_tree *tree,
enum mu_cfg_node_type type,
const mu_cfg_locus_t *loc,
const char *tag, const char *label,
const char *tag,
const char *label,
mu_cfg_node_t *node);
void mu_cfg_tree_add_node (mu_cfg_tree_t *tree, mu_cfg_node_t *node);
......
......@@ -19,6 +19,7 @@
#include <mailutils/acl.h>
#include <mailutils/address.h>
#include <mailutils/alloc.h>
#include <mailutils/assoc.h>
#include <mailutils/argcv.h>
#include <mailutils/attribute.h>
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2002, 2005, 2007 Free Software Foundation, Inc.
Copyright (C) 2002, 2005, 2007, 2008 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
......@@ -109,7 +109,9 @@ extern int mu_auth_nosupport (struct mu_auth_data **return_data,
extern void mu_auth_register_module (struct mu_auth_module *mod);
extern int mu_authorization_add_module (const char *modname);
extern void mu_authorization_add_module_list (const char *modlist);
extern int mu_authentication_add_module (const char *modname);
extern void mu_authentication_add_module_list (const char *modlist);
extern void mu_authentication_clear_list (void);
extern void mu_authorization_clear_list (void);
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2008 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 */
#ifndef _MAILUTILS_OPOOL_H
#define _MAILUTILS_OPOOL_H
#include <mailutils/types.h>
#ifndef MU_OPOOL_BUCKET_SIZE
# define MU_OPOOL_BUCKET_SIZE 1024
#endif
/* Create an object pool. If MEMERR is not 0, any operation of the
resulting pool (including mu_opool_create itself) will abort on
not enough memory condition, using mu_alloc_die. */
int mu_opool_create (mu_opool_t *pret, int memerr);
/* Clear all data from the pool, so next mu_opool_append* call will
begin a new object. */
void mu_opool_clear (mu_opool_t opool);
/* Destroy the pool, reclaim any memory associated with it. */
void mu_opool_destroy (mu_opool_t *popool);
/* Append to the current object N bytes pointed to by STR. */
int mu_opool_append (mu_opool_t opool, const void *str, size_t n);
/* Append to the current object a nul-terminated string STR. */
int mu_opool_appendz (mu_opool_t opool, const char *str);
/* Append a single byte C to the current object. */
int mu_opool_append_char (mu_opool_t opool, char c);
/* Return size of the current object in the pool. */
size_t mu_opool_size (mu_opool_t opool);
/* Coalesce all data collected so far (by using mu_opool_append* calls)
into a single contiguous memory chunk. Return the size of the resulting
object in *PSIZE, unless PSIZE==NULL. Return 0 on success, error code on
failure (unless the pool was created with `memerr' option, see
mu_opool_create, above). */
int mu_opool_coalesce (mu_opool_t opool, size_t *psize);
/* Return the pointer to the current object head chunk. If mu_opool_coalesce
was called before, the returned value points to the entire object.
If PSIZE is not NULL, store the size of the head chunk to *PSIZE. */
void *mu_opool_head (mu_opool_t opool, size_t *psize);
/* Finish building the object. Equivalent to:
mu_opool_coalesce (opool, NULL);
p = mu_opool_head (opool, psize);
mu_opool_clear (opool);
return p; */
void *mu_opool_finish (mu_opool_t opool, size_t *psize);
#endif
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2007 Free Software Foundation, Inc.
Copyright (C) 2007, 2008 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
......@@ -29,9 +29,9 @@ extern int mu_log_facility;
extern char *mu_log_tag;
#define MU_LOG_TAG() (mu_log_tag ? mu_log_tag : mu_program_name)
int mu_string_to_syslog_facility (char *str, int *pfacility);
int mu_string_to_syslog_facility (const char *str, int *pfacility);
const char *mu_syslog_facility_to_string (int n);
int mu_string_to_syslog_priority (char *str, int *pprio);
int mu_string_to_syslog_priority (const char *str, int *pprio);
const char *mu_syslog_priority_to_string (int n);
#ifdef __cplusplus
......
......@@ -110,7 +110,8 @@ typedef struct _mu_acl *mu_acl_t;
typedef struct _mu_server *mu_server_t;
typedef struct _mu_ip_server *mu_ip_server_t;
typedef struct _mu_m_server *mu_m_server_t;
typedef struct _mu_opool *mu_opool_t;
#define MU_FOLDER_ATTRIBUTE_DIRECTORY 0x001
#define MU_FOLDER_ATTRIBUTE_FILE 0x002
......
......@@ -39,37 +39,28 @@ int deny_severity = LOG_INFO;
int allow_severity = LOG_INFO;
int
mu_tcp_wrapper_cb_hosts_allow (mu_debug_t debug, void *data, char *arg)
{
hosts_allow_table = strdup (arg);
return 0;
}
int
mu_tcp_wrapper_cb_hosts_deny (mu_debug_t debug, void *data, char *arg)
{
hosts_deny_table = strdup (arg);
return 0;
}
int
mu_tcp_wrapper_cb_hosts_allow_syslog (mu_debug_t debug, void *data,
char *arg)
mu_config_value_t *val)
{
if (mu_string_to_syslog_priority (arg, &allow_severity))
if (mu_cfg_assert_value_type (val, MU_CFG_STRING, debug))
return 1;
if (mu_string_to_syslog_priority (val->v.string, &allow_severity))
mu_cfg_format_error (debug, MU_DEBUG_ERROR,
_("Unknown syslog priority `%s'"),
arg);
val->v.string);
return 0;
}
int
mu_tcp_wrapper_cb_hosts_deny_syslog (mu_debug_t debug, void *data, char *arg)
mu_tcp_wrapper_cb_hosts_deny_syslog (mu_debug_t debug, void *data,
mu_config_value_t *val)
{
if (mu_string_to_syslog_priority (arg, &deny_severity))
if (mu_cfg_assert_value_type (val, MU_CFG_STRING, debug))
return 1;
if (mu_string_to_syslog_priority (val->v.string, &deny_severity))
mu_cfg_format_error (debug, MU_DEBUG_ERROR,
_("Unknown syslog priority `%s'"),
arg);
val->v.string);
return 0;
}
......@@ -95,13 +86,13 @@ struct mu_cfg_param tcpwrapper_param[] = {
{ "daemon", mu_cfg_string, &mu_tcp_wrapper_daemon, 0, NULL,
N_("Set daemon name for TCP wrapper lookups. Default is program name."),
N_("name") },
{ "allow-table", mu_cfg_callback, NULL, 0,
mu_tcp_wrapper_cb_hosts_allow,
{ "allow-table", mu_cfg_string, &hosts_allow_table,
0, NULL,
N_("Use file for positive client address access control "
"(default: /etc/hosts.allow)."),
N_("file") },
{ "deny-table", mu_cfg_callback, NULL, 0,
mu_tcp_wrapper_cb_hosts_deny,
{ "deny-table", mu_cfg_string, &hosts_deny_table,
0, NULL,
N_("Use file for negative client address access control "
"(default: /etc/hosts.deny)."),
N_("file") },
......
/* This file is part of GNU Mailutils
Copyright (C) 2007 Free Software Foundation, Inc.
Copyright (C) 2007, 2008 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
......@@ -35,23 +35,21 @@
#define SKIPWS(p) while (*(p) && ISSPACE (*(p))) (p)++;
static char *
getword (char **parg)
static const char *
getword (mu_config_value_t *val, int *pn, mu_debug_t err)
{
char *arg = *parg;
char *word;
int n = (*pn)++;
mu_config_value_t *v;
SKIPWS (arg);
word = arg;
if (*arg)
if (n >= val->v.arg.c)
{
while (*arg && !ISSPACE (*arg))
arg++;
if (*arg)
*arg++ = 0;
mu_cfg_format_error (err, MU_DEBUG_ERROR, _("not enough arguments"));
return NULL;
}
*parg = arg;
return word;
v = &val->v.arg.v[n];
if (mu_cfg_assert_value_type (v, MU_CFG_STRING, err))
return NULL;
return v->v.string;
}
struct netdef
......@@ -66,7 +64,7 @@ struct netdef
#endif
int
parse_address (mu_debug_t err, char *str, struct netdef *nd)
parse_address (mu_debug_t err, const char *str, struct netdef *nd)
{
struct sockaddr_in in;
......@@ -94,21 +92,33 @@ parse_address (mu_debug_t err, char *str, struct netdef *nd)
}
static int
parsearg (mu_debug_t err, char *arg, struct netdef *pnd, char **prest)
parsearg (mu_debug_t err, mu_config_value_t *val, struct netdef *pnd,
char **prest)
{
char *w, *p;
const char *w;
char *p;
unsigned long netmask;
w = getword (&arg);
if (strcmp (w, "from") == 0)
w = getword (&arg);
int n = 0;
if (mu_cfg_assert_value_type (val, MU_CFG_ARRAY, err))
return 1;
w = getword (val, &n, err);
if (!w)
return 1;
if (strcmp (w, "from") == 0) {
w = getword (val, &n, err);
if (!w)
return 1;
}
p = strchr (w, '/');
if (p)
{
char *q;
unsigned netlen;
/* FIXME: This modifies a const char! */
*p++ = 0;
netlen = strtoul (p, &q, 10);
if (*q == 0)
......@@ -146,28 +156,44 @@ parsearg (mu_debug_t err, char *arg, struct netdef *pnd, char **prest)
if (parse_address (err, w, pnd))
return 1;
SKIPWS (arg);
if (prest)
{
if (*arg == 0)
if (n == val->v.arg.c)
*prest = NULL;
else
{
int len = strlen (arg);
*prest = malloc (len);
if (!prest)
size_t size;
int i;
char *buf;
for (i = n; i < val->v.arg.c; i++)
{
if (mu_cfg_assert_value_type (&val->v.arg.v[i], MU_CFG_STRING,
err))
return 1;
size += strlen (val->v.arg.v[i].v.string) + 1;
}
buf = malloc (size);
if (!buf)
{
mu_cfg_format_error (err, MU_DEBUG_ERROR,
"%s", mu_strerror (errno));
return 1;
}
*prest = buf;
for (i = n; i < val->v.arg.c; i++)
{
if (i > n)
*buf++ = ' ';
strcpy (buf, val->v.arg.v[i].v.string);
buf += strlen (buf);
}
if (arg[0] == '"' || arg[0] == '\'')
mu_argcv_unquote_copy (*prest, arg, len);
else
strcpy (*prest, arg);
*buf = 0;
}
}
else if (*arg != 0)
else if (n != val->v.arg.c)
{
mu_cfg_format_error (err, MU_DEBUG_ERROR, _("junk after IP address"));
return 1;
......@@ -176,13 +202,13 @@ parsearg (mu_debug_t err, char *arg, struct netdef *pnd, char **prest)
}
static int
cb_allow (mu_debug_t err, void *data, char *arg)
cb_allow (mu_debug_t err, void *data, mu_config_value_t *val)
{
int rc;
mu_acl_t acl = *(mu_acl_t*)data;
struct netdef ndef;
if (parsearg (err, arg, &ndef, NULL))
if (parsearg (err, val, &ndef, NULL))
return 1;
rc = mu_acl_append (acl, mu_acl_accept, NULL, ndef.sa, ndef.len,
ndef.netmask);
......@@ -195,13 +221,13 @@ cb_allow (mu_debug_t err, void *data, char *arg)
}
static int
cb_deny (mu_debug_t err, void *data, char *arg)
cb_deny (mu_debug_t err, void *data, mu_config_value_t *val)
{
int rc;
mu_acl_t acl = *(mu_acl_t*)data;
struct netdef ndef;
if (parsearg (err, arg, &ndef, NULL))
if (parsearg (err, val, &ndef, NULL))
return 1;
rc = mu_acl_append (acl, mu_acl_deny, NULL, ndef.sa, ndef.len,
ndef.netmask);
......@@ -214,14 +240,14 @@ cb_deny (mu_debug_t err, void *data, char *arg)
}
static int
cb_log (mu_debug_t err, void *data, char *arg)
cb_log (mu_debug_t err, void *data, mu_config_value_t *val)
{
int rc;
mu_acl_t acl = *(mu_acl_t*)data;
struct netdef ndef;
char *rest;
if (parsearg (err, arg, &ndef, &rest))
if (parsearg (err, val, &ndef, &rest))
return 1;
rc = mu_acl_append (acl, mu_acl_log, rest, ndef.sa, ndef.len,
ndef.netmask);
......@@ -234,14 +260,14 @@ cb_log (mu_debug_t err, void *data, char *arg)
}
static int
cb_exec (mu_debug_t err, void *data, char *arg)
cb_exec (mu_debug_t err, void *data, mu_config_value_t *val)
{
int rc;
mu_acl_t acl = *(mu_acl_t*)data;
struct netdef ndef;
char *rest;
if (parsearg (err, arg, &ndef, &rest))
if (parsearg (err, val, &ndef, &rest))
return 1;
rc = mu_acl_append (acl, mu_acl_exec, rest, ndef.sa, ndef.len,
ndef.netmask);
......@@ -254,14 +280,14 @@ cb_exec (mu_debug_t err, void *data, char *arg)
}
static int
cb_ifexec (mu_debug_t err, void *data, char *arg)
cb_ifexec (mu_debug_t err, void *data, mu_config_value_t *val)
{
int rc;
mu_acl_t acl = *(mu_acl_t*)data;
struct netdef ndef;
char *rest;
if (parsearg (err, arg, &ndef, &rest))
if (parsearg (err, val, &ndef, &rest))
return 1;
rc = mu_acl_append (acl, mu_acl_ifexec, rest, ndef.sa, ndef.len,
ndef.netmask);
......
/* This file is part of GNU Mailutils
Copyright (C) 2007 Free Software Foundation, Inc.
Copyright (C) 2007, 2008 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
......@@ -29,28 +29,73 @@
/* Resource-style configuration */
/* ************************************************************************* */
static int
cb_authentication (mu_debug_t err, void *data, char *arg)
cb_authentication (mu_debug_t err, void *data, mu_config_value_t *val)
{
if (strcmp (arg, "clear") == 0)
mu_authentication_clear_list ();
if (val->type == MU_CFG_STRING)
{
if (strcmp (val->v.string, "clear") == 0)
mu_authentication_clear_list ();
else
/*FIXME: use err for error reporting*/
mu_authentication_add_module_list (val->v.string);
}
else if (val->type == MU_CFG_LIST)
{
int i;
for (i = 0; i < val->v.arg.c; i++)
{
if (mu_cfg_assert_value_type (&val->v.arg.v[i], MU_CFG_STRING, err))
return 1;
if (strcmp (val->v.arg.v[i].v.string, "clear") == 0)
mu_authentication_clear_list ();
else
mu_authentication_add_module (val->v.arg.v[i].v.string);
}
}
else
mu_authentication_add_module_list (arg);/*FIXME: use err for error
reporting*/
{
mu_cfg_format_error (err, MU_DEBUG_ERROR, _("expected string value"));
return 1;
}
return 0;
}
static int
cb_authorization (mu_debug_t err, void *data, char *arg)
cb_authorization (mu_debug_t err, void *data, mu_config_value_t *val)
{
if (strcmp (arg, "clear") == 0)
mu_authorization_clear_list ();
if (val->type == MU_CFG_STRING)
{
if (strcmp (val->v.string, "clear") == 0)
mu_authorization_clear_list ();
else
/*FIXME: use err for error reporting*/
mu_authorization_add_module_list (val->v.string);
}
else if (val->type == MU_CFG_LIST)
{
int i;
for (i = 0; i < val->v.arg.c; i++)
{
if (mu_cfg_assert_value_type (&val->v.arg.v[i], MU_CFG_STRING, err))
return 1;
if (strcmp (val->v.arg.v[i].v.string, "clear") == 0)
mu_authorization_clear_list ();
else
mu_authorization_add_module (val->v.arg.v[i].v.string);
}
}
else
mu_authorization_add_module_list (arg);/* FIXME: see above */
{
mu_cfg_format_error (err, MU_DEBUG_ERROR, _("expected string value"));
return 1;
}
return 0;
}
static struct mu_cfg_param mu_auth_param[] = {
{ "authentication", mu_cfg_callback, NULL, 0, cb_authentication,
/* FIXME: The description is incomplete. MU-list is also allowed as
argument */
N_("Set a list of modules for authentication. Modlist is a "
"colon-separated list of module names or a word `clear' to "
"clear the previously set up values."),
......
......@@ -39,9 +39,11 @@ static struct mu_gocs_debug debug_settings;
/* ************************************************************************* */
static int
_cb_folder (mu_debug_t debug, void *data, char *arg)
_cb_folder (mu_debug_t debug, void *data, mu_config_value_t *val)
{
mu_set_folder_directory (arg);
if (mu_cfg_assert_value_type (val, MU_CFG_STRING, debug))
return 1;
mu_set_folder_directory (val->v.string);
return 0;
}
......@@ -127,13 +129,16 @@ DCL_CFG_CAPA (mailer);
/* ************************************************************************* */
int
cb_facility (mu_debug_t debug, void *data, char *arg)
cb_facility (mu_debug_t debug, void *data, mu_config_value_t *val)
{
if (mu_string_to_syslog_facility (arg, &logging_settings.facility))
if (mu_cfg_assert_value_type (val, MU_CFG_STRING, debug))
return 1;
if (mu_string_to_syslog_facility (val->v.string, &logging_settings.facility))
{
mu_cfg_format_error (debug, MU_DEBUG_ERROR,
_("Unknown syslog facility `%s'"),
arg);
val->v.string);
return 1;
}
return 0;
......@@ -157,7 +162,7 @@ DCL_CFG_CAPA (logging);
/* ************************************************************************* */
static int
cb_debug_level (mu_debug_t debug, void *data, char *arg)
_cb2_debug_level (mu_debug_t debug, const char *arg, void *data MU_ARG_UNUSED)
{
char buf[UINTMAX_STRSIZE_BOUND];
char *p;
......@@ -185,7 +190,8 @@ cb_debug_level (mu_debug_t debug, void *data, char *arg)
}
else
pfx = strdup ("command line");/*FIXME*/
/*FIXME:*/
/*FIXME: this is suboptimal, there's no use parsing 1st arg in
mu_global_debug_from_string */
mu_global_debug_from_string (debug_settings.string, pfx);
free (debug_settings.string);
free (debug_settings.errpfx);
......@@ -193,6 +199,12 @@ cb_debug_level (mu_debug_t debug, void *data, char *arg)
return 0;
}
static int
cb_debug_level (mu_debug_t debug, void *data, mu_config_value_t *val)
{
return mu_cfg_string_value_cb (debug, val, _cb2_debug_level, NULL);
}
static struct mu_cfg_param mu_debug_param[] = {
{ "level", mu_cfg_callback, NULL, 0, &cb_debug_level,
N_("Set Mailutils debugging level. Argument is a colon-separated list "
......
/* This file is part of GNU Mailutils
Copyright (C) 2007 Free Software Foundation, Inc.
Copyright (C) 2007, 2008 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
......@@ -26,16 +26,23 @@
static struct mu_ldap_module_config ldap_settings;
static int
cb_field_map (mu_debug_t debug, void *data, char *arg)
_cb2_field_map (mu_debug_t debug, const char *arg, void *data)
{
int err;
int rc = mutil_parse_field_map (arg, &ldap_settings.field_map, &err);
if (rc)
/* FIXME: this message may be misleading */
mu_cfg_format_error (debug, MU_DEBUG_ERROR, _("Error near element %d: %s"),
err, mu_strerror (rc));
return 0;
}
static int
cb_field_map (mu_debug_t debug, void *data, mu_config_value_t *val)
{
return mu_cfg_string_value_cb (debug, val, _cb2_field_map, NULL);
}
static struct mu_cfg_param mu_ldap_param[] = {
{ "enable", mu_cfg_bool, &ldap_settings.enable, 0, NULL,
N_("Enable LDAP lookups.") },
......
/* This file is part of GNU Mailutils
Copyright (C) 2007 Free Software Foundation, Inc.
Copyright (C) 2007, 2008 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
......@@ -25,10 +25,13 @@
static struct mu_gocs_sieve sieve_settings;
static int
cb_clear_library_path (mu_debug_t debug, void *data, char *arg)
cb_clear_library_path (mu_debug_t debug, void *data, mu_config_value_t *val)
{
int flag;
if (mu_cfg_parse_boolean (arg, &flag))
if (mu_cfg_assert_value_type (val, MU_CFG_STRING, debug))
return 1;
if (mu_cfg_parse_boolean (val->v.string, &flag))
{
mu_cfg_format_error (debug, MU_DEBUG_ERROR, _("not a boolean"));
return 1;
......@@ -39,10 +42,13 @@ cb_clear_library_path (mu_debug_t debug, void *data, char *arg)
}
static int
cb_clear_include_path (mu_debug_t debug, void *data, char *arg)
cb_clear_include_path (mu_debug_t debug, void *data, mu_config_value_t *val)
{
int flag;
if (mu_cfg_parse_boolean (arg, &flag))
if (mu_cfg_assert_value_type (val, MU_CFG_STRING, debug))
return 1;
if (mu_cfg_parse_boolean (val->v.string, &flag))
{
mu_cfg_format_error (debug, MU_DEBUG_ERROR, _("not a boolean"));
return 1;
......@@ -59,10 +65,11 @@ destroy_string (void *str)
}
static int
_add_path (mu_list_t *plist, mu_debug_t debug, void *data, char *arg)
_add_path (mu_debug_t debug, const char *arg, void *data)
{
char *p;
char *p, *tmp;
mu_list_t *plist = data;
if (!*plist)
{
int rc = mu_list_create (plist);
......@@ -74,21 +81,26 @@ _add_path (mu_list_t *plist, mu_debug_t debug, void *data, char *arg)
}
mu_list_set_destroy_item (*plist, destroy_string);
}
for (p = strtok (arg, ":"); p; p = strtok (NULL, ":"))
/* FIXME: Use mu_argcv */
tmp = strdup (arg);
for (p = strtok (tmp, ":"); p; p = strtok (NULL, ":"))
mu_list_append (*plist, strdup (p));
free (tmp);
return 0;
}
static int
cb_include_path (mu_debug_t debug, void *data, char *arg)
cb_include_path (mu_debug_t debug, void *data, mu_config_value_t *val)
{
return _add_path (&sieve_settings.include_path, debug, data, arg);
}
return mu_cfg_string_value_cb (debug, val, _add_path,
&sieve_settings.include_path);
}
static int
cb_library_path (mu_debug_t debug, void *data, char *arg)
cb_library_path (mu_debug_t debug, void *data, mu_config_value_t *val)
{
return _add_path (&sieve_settings.library_path, debug, data, arg);
return mu_cfg_string_value_cb (debug, val, _add_path,
&sieve_settings.library_path);
}
static struct mu_cfg_param mu_sieve_param[] = {
......
......@@ -29,26 +29,36 @@ static struct mu_sql_module_config sql_settings;
/* Resource file configuration */
static int
cb_password_type (mu_debug_t debug, void *data, char *arg)
cb_password_type (mu_debug_t debug, void *data, mu_config_value_t *val)
{
if (mu_sql_decode_password_type (arg, &sql_settings.password_type))
if (mu_cfg_assert_value_type (val, MU_CFG_STRING, debug))
return 1;
if (mu_sql_decode_password_type (val->v.string, &sql_settings.password_type))
mu_cfg_format_error (debug, MU_DEBUG_ERROR,
_("Unknown password type `%s'"),
arg);
val->v.string);
return 0;
}
static int
cb_field_map (mu_debug_t debug, void *data, char *arg)
_cb2_field_map (mu_debug_t debug, const char *arg, void *data)
{
int err;
int rc = mutil_parse_field_map (arg, &sql_settings.field_map, &err);
if (rc)
/* FIXME: this message may be misleading */
mu_cfg_format_error (debug, MU_DEBUG_ERROR, _("Error near element %d: %s"),
err, mu_strerror (rc));
return 0;
}
static int
cb_field_map (mu_debug_t debug, void *data, mu_config_value_t *val)
{
return mu_cfg_string_value_cb (debug, val, _cb2_field_map, NULL);
}
static struct mu_cfg_param mu_sql_param[] = {
{ "interface", mu_cfg_string, &sql_settings.interface, 0, NULL,
N_("Set SQL interface to use (one of: mysql, odbc, or postgres).") },
......
......@@ -242,9 +242,11 @@ parse_opt (int key, char *arg, struct argp_state *state)
static int
cb_debug (mu_debug_t debug, void *data, char *arg)
cb_debug (mu_debug_t debug, void *data, mu_config_value_t *val)
{
set_debug_flags (debug, arg);
if (mu_cfg_assert_value_type (val, MU_CFG_STRING, debug))
return 1;
set_debug_flags (debug, val->v.string);
return 0;
}
......
......@@ -249,9 +249,11 @@ parse_opt (int key, char *arg, struct argp_state *state)
static int
cb_debug (mu_debug_t debug, void *data, char *arg)
cb_debug (mu_debug_t debug, void *data, mu_config_value_t *val)
{
set_debug_flags (debug, arg);
if (mu_cfg_assert_value_type (val, MU_CFG_STRING, debug))
return 1;
set_debug_flags (debug, val->v.string);
return 0;
}
......
......@@ -11,5 +11,6 @@ mailutils-config
parsedate.c
*y.output
muerrno.c
cfg_lexer.c
cfg_parser.c
cfg_parser.h
......
......@@ -22,6 +22,7 @@ INCLUDES = @MU_COMMON_INCLUDES@ -I${top_srcdir}/libproto/include
YLWRAP = $(SHELL) $(top_srcdir)/scripts/gylwrap
AM_YFLAGS=-vt
AM_LFLAGS=-dvp
SUBDIRS = testsuite
......@@ -33,11 +34,21 @@ AM_CPPFLAGS = \
-DSITE_VIRTUAL_PWDDIR=\"@SITE_VIRTUAL_PWDDIR@\"\
-DLOCALEDIR=\"$(localedir)\"
EXTRA_DIST = errors muerrno.cin parsedate.y fgetpwent.c cfg_parser.y cfg_parser.h inttostr.c inttostr.h
EXTRA_DIST = \
errors\
muerrno.cin\
parsedate.y\
fgetpwent.c\
cfg_lexer.l\
cfg_parser.y\
cfg_parser.h\
inttostr.c\
inttostr.h
libmailutils_la_SOURCES = \
acl.c\
address.c\
alloc.c\
amd.c\
argcv.c\
assoc.c\
......@@ -94,6 +105,7 @@ libmailutils_la_SOURCES = \
muerrno.c\
nls.c\
observer.c\
opool.c\
parse822.c\
parsedate.c\
property.c\
......@@ -114,7 +126,7 @@ libmailutils_la_SOURCES = \
wicket.c\
imaxtostr.c offtostr.c umaxtostr.c intprops.h
BUILT_SOURCES = parsedate.c muerrno.c cfg_parser.c cfg_parser.h
BUILT_SOURCES = parsedate.c muerrno.c cfg_parser.c cfg_parser.h cfg_lexer.c
MOSTLYCLEANFILES=
parsedate.c: $(srcdir)/parsedate.y
......@@ -128,6 +140,11 @@ cfg_parser.c cfg_parser.h: $(srcdir)/cfg_parser.y
y.output cfg_parser.y.output \
-- -yy mu_cfg_yy
cfg_lexer.c: $(srcdir)/cfg_lexer.l cfg_parser.h
$(YLWRAP) "$(LEX) $(AM_LFLAGS) $(LFLAGS)" \
$(srcdir)/cfg_lexer.l lex.yy.c cfg_lexer.c \
-- -yy mu_cfg_yy
muerrno.c: errors muerrno.cin
$(AWK) -f $(top_srcdir)/scripts/generr.awk $^ > $@
......
/* Error-proof memory allocation functions.
Copyright (C) 2008 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.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mailutils/error.h>
#include <mailutils/nls.h>
#include <mailutils/alloc.h>
void (*mu_alloc_die_hook) (void) = NULL;
void
mu_alloc_die ()
{
if (mu_alloc_die_hook)
mu_alloc_die_hook ();
mu_error (_("Not enough memory"));
abort ();
}
void *
mu_alloc (size_t size)
{
void *p = malloc (size);
if (!p)
mu_alloc_die ();
return p;
}
void *
mu_calloc (size_t nmemb, size_t size)
{
void *p = calloc (nmemb, size);
if (!p)
mu_alloc_die ();
return p;
}
void *
mu_zalloc (size_t size)
{
void *p = mu_alloc (size);
memset (p, 0, size);
return p;
}
void *
mu_realloc (void *p, size_t size)
{
void *newp = realloc (p, size);
if (!newp)
mu_alloc_die ();
return newp;
}
char *
mu_strdup (const char *s)
{
char *news = strdup (s);
if (!news)
mu_alloc_die ();
return news;
}
/* Copied from gnulib */
void *
mu_2nrealloc (void *p, size_t *pn, size_t s)
{
size_t n = *pn;
if (!p)
{
if (!n)
{
/* The approximate size to use for initial small allocation
requests, when the invoking code specifies an old size of
zero. 64 bytes is the largest "small" request for the
GNU C library malloc. */
enum { DEFAULT_MXFAST = 64 };
n = DEFAULT_MXFAST / s;
n += !n;
}
}
else
{
/* Set N = ceil (1.5 * N) so that progress is made if N == 1.
Check for overflow, so that N * S stays in size_t range.
The check is slightly conservative, but an exact check isn't
worth the trouble. */
if ((size_t) -1 / 3 * 2 / s <= n)
mu_alloc_die ();
n += (n + 1) / 2;
}
*pn = n;
return mu_realloc (p, n * s);
}
......@@ -442,8 +442,11 @@ prog_parser (enum mu_cfg_section_stage stage,
mu_cfg_tree_t *tree)
{
if (stage == mu_cfg_section_start)
return strcmp (node->tag_label, label);
{
return node->label->type == MU_CFG_STRING
&& strcmp (node->label->v.string, label);
}
return 0;
}
......@@ -473,14 +476,18 @@ struct include_data
};
static int
_cb_include (mu_debug_t debug, void *data, char *arg)
_cb_include (mu_debug_t debug, void *data, mu_config_value_t *val)
{
int ret = 0;
struct stat sb;
char *dirname = arg;
const char *dirname;
struct include_data *idp = data;
char *tmp = NULL;
if (mu_cfg_assert_value_type (val, MU_CFG_STRING, debug))
return 1;
dirname = val->v.string;
if (dirname[0] != '/')
dirname = tmp = make_file_name (SYSCONFDIR, dirname);
......@@ -641,3 +648,59 @@ mu_parse_config (const char *file, const char *progname,
rc = ENOMEM;
return rc;
}
int
mu_cfg_assert_value_type (mu_config_value_t *val, int type, mu_debug_t debug)
{
if (val->type != MU_CFG_STRING)
{
/* FIXME */
mu_cfg_format_error (debug, MU_DEBUG_ERROR,
_("expected string value"));
return 1;
}
return 0;
}
int
mu_cfg_string_value_cb (mu_debug_t debug, mu_config_value_t *val,
int (*fun) (mu_debug_t, const char *, void *),
void *data)
{
switch (val->type)
{
case MU_CFG_STRING:
return fun (debug, val->v.string, data);
break;
case MU_CFG_ARRAY:
{
int i;
for (i = 0; i < val->v.arg.c; i++)
{
if (mu_cfg_assert_value_type (&val->v.arg.v[i],
MU_CFG_STRING, debug))
return 1;
fun (debug, val->v.arg.v[i].v.string, data);
}
}
break;
case MU_CFG_LIST:
{
mu_iterator_t itr;
mu_list_get_iterator (val->v.list, &itr);
for (mu_iterator_first (itr);
!mu_iterator_is_done (itr); mu_iterator_next (itr))
{
mu_config_value_t *pval;
mu_iterator_current (itr, (void*) &pval);
if (mu_cfg_assert_value_type (pval, MU_CFG_STRING, debug))
fun (debug, pval->v.string, data);
}
mu_iterator_destroy (&itr);
}
}
return 0;
}
......
/* cfg_print.c -- convert configuration parse tree to human-readable format.
Copyright (C) 2007 Free Software Foundation, Inc.
Copyright (C) 2007, 2008 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
......@@ -18,11 +18,13 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <mailutils/alloc.h>
#include <mailutils/stream.h>
#include <mailutils/error.h>
#include <mailutils/cfg.h>
#include <mailutils/argcv.h>
#include <mailutils/nls.h>
#include <mailutils/iterator.h>
#include <ctype.h>
struct tree_print
......@@ -41,25 +43,19 @@ format_level (mu_stream_t stream, int level)
}
static void
format_label (struct tree_print *tp, const char *label)
format_string_value (struct tree_print *tp, const char *str)
{
size_t size;
int quote;
char *p;
size = mu_argcv_quoted_length (label, &quote);
size = mu_argcv_quoted_length (str, &quote);
if (quote)
size += 2;
size++;
if (size > tp->bufsize)
{
p = realloc (tp->buf, size);
if (!p)
{
mu_stream_sequential_printf (tp->stream, "%s\n",
_("ERROR: not enough memory"));
return;
}
p = mu_realloc (tp->buf, size);
tp->bufsize = size;
tp->buf = p;
}
......@@ -72,10 +68,64 @@ format_label (struct tree_print *tp, const char *label)
p++;
}
tp->buf[size-1] = 0;
mu_argcv_quote_copy (p, label);
mu_argcv_quote_copy (p, str);
mu_stream_sequential_write (tp->stream, tp->buf, size - 1);
}
static void format_value (struct tree_print *tp, mu_config_value_t *val);
static void
format_list_value (struct tree_print *tp, mu_config_value_t *val)
{
int i;
mu_iterator_t itr;
mu_stream_sequential_write (tp->stream, "(", 1);
mu_list_get_iterator (val->v.list, &itr);
for (mu_iterator_first (itr), i = 0;
!mu_iterator_is_done (itr); mu_iterator_next (itr), i++)
{
mu_config_value_t *p;
mu_iterator_current (itr, (void**)&p);
if (i)
mu_stream_sequential_write (tp->stream, ", ", 2);
format_value (tp, p);
}
mu_iterator_destroy (&itr);
mu_stream_sequential_write (tp->stream, ")", 1);
}
static void
format_array_value (struct tree_print *tp, mu_config_value_t *val)
{
int i;
for (i = 0; i < val->v.arg.c; i++)
{
if (i)
mu_stream_sequential_write (tp->stream, " ", 1);
format_value (tp, &val->v.arg.v[i]);
}
}
static void
format_value (struct tree_print *tp, mu_config_value_t *val)
{
switch (val->type)
{
case MU_CFG_STRING:
format_string_value (tp, val->v.string);
break;
case MU_CFG_LIST:
format_list_value (tp, val);
break;
case MU_CFG_ARRAY:
format_array_value (tp, val);
}
}
static int
format_node (const mu_cfg_node_t *node, void *data)
{
......@@ -94,12 +144,12 @@ format_node (const mu_cfg_node_t *node, void *data)
case mu_cfg_node_tag:
{
mu_stream_sequential_write (tp->stream, node->tag_name,
strlen (node->tag_name));
if (node->tag_label)
mu_stream_sequential_write (tp->stream, node->tag,
strlen (node->tag));
if (node->label)
{
mu_stream_sequential_write (tp->stream, " ", 1);
format_label (tp, node->tag_label);
format_value (tp, node->label);
}
mu_stream_sequential_write (tp->stream, " {", 2);
tp->level++;
......@@ -107,12 +157,12 @@ format_node (const mu_cfg_node_t *node, void *data)
break;
case mu_cfg_node_param:
mu_stream_sequential_write (tp->stream, node->tag_name,
strlen (node->tag_name));
if (node->tag_label)
mu_stream_sequential_write (tp->stream, node->tag,
strlen (node->tag));
if (node->label)
{
mu_stream_sequential_write (tp->stream, " ", 1);
format_label (tp, node->tag_label);
format_value (tp, node->label);
mu_stream_sequential_write (tp->stream, ";", 1);
}
break;
......@@ -238,12 +288,20 @@ format_param (mu_stream_t stream, struct mu_cfg_param *param, int level)
mu_stream_sequential_printf (stream, "%s <%s>;\n",
param->ident,
gettext (param->argname));
else if (MU_CFG_IS_LIST (param->type))
mu_stream_sequential_printf
(stream, "%s <%s: list of %s>;\n",
param->ident,
gettext (param->argname ?
param->argname : N_("arg")),
gettext (mu_cfg_data_type_string (MU_CFG_TYPE (param->type))));
else
mu_stream_sequential_printf (stream, "%s <%s: %s>;\n",
param->ident,
gettext (param->argname ?
param->argname : N_("arg")),
gettext (mu_cfg_data_type_string (param->type)));
mu_stream_sequential_printf
(stream, "%s <%s: %s>;\n",
param->ident,
gettext (param->argname ?
param->argname : N_("arg")),
gettext (mu_cfg_data_type_string (param->type)));
}
static void format_container (mu_stream_t stream, struct mu_cfg_cont *cont,
......
/* cfg_lexer.c -- default lexer for Mailutils configuration files
Copyright (C) 2007, 2008 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.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <ctype.h>
#include <mailutils/errno.h>
#include <mailutils/error.h>
#include <mailutils/argcv.h>
#include <mailutils/nls.h>
#include <mailutils/cfg.h>
#include <mailutils/list.h>
#include "cfg_parser.h"
struct lexer_data
{
char *buffer;
char *curp;
mu_list_t mpool;
char *cbuf;
size_t cbufsize;
size_t cbuflevel;
};
#define CBUFINCR 256
static void
cbuf_grow (struct lexer_data *datp, const char *str, size_t len)
{
if (datp->cbufsize - datp->cbuflevel < len)
{
size_t n = ((datp->cbuflevel + len + CBUFINCR - 1) / CBUFINCR);
datp->cbufsize = n * CBUFINCR;
datp->cbuf = realloc (datp->cbuf, datp->cbufsize);
if (!datp->cbuf)
{
mu_error ("%s", mu_strerror (ENOMEM));
abort ();
}
}
memcpy (datp->cbuf + datp->cbuflevel, str, len);
datp->cbuflevel += len;
}
static void
cbuf_1grow (struct lexer_data *datp, char c)
{
cbuf_grow (datp, &c, 1);
}
static void
_mpool_destroy_item (void *p)
{
free (p);
}
static char *
cbuf_finish (struct lexer_data *datp)
{
char *p = malloc (datp->cbuflevel);
if (!p)
{
mu_error ("%s", mu_strerror (ENOMEM));
abort ();
}
memcpy (p, datp->cbuf, datp->cbuflevel);
datp->cbuflevel = 0;
if (!datp->mpool)
{
mu_list_create (&datp->mpool);
mu_list_set_destroy_item (datp->mpool, _mpool_destroy_item);
}
mu_list_append (datp->mpool, p);
return p;
}
static void
skipws (struct lexer_data *p)
{
while (*p->curp && isspace (*p->curp))
{
if (*p->curp == '\n')
mu_cfg_locus.line++;
p->curp++;
}
}
static void
skipline (struct lexer_data *p)
{
while (*p->curp && *p->curp != '\n')
p->curp++;
}
static int
continuation_line_p (struct lexer_data *p, int quote)
{
skipws (p);
return *p->curp == quote;
}
static void
copy_string0 (struct lexer_data *p, int unquote)
{
int quote;
do
{
quote = *p->curp++;
while (*p->curp)
{
if (*p->curp == '\\')
{
char c;
if (*++p->curp == 0)
{
cbuf_1grow (p, '\\');
break;
}
if (*p->curp == '\n')
{
p->curp++;
continue;
}
if (!unquote)
c = *p->curp;
else
c = mu_argcv_unquote_char (*p->curp);
cbuf_1grow (p, c);
p->curp++;
}
else if (*p->curp == quote)
{
p->curp++;
break;
}
else
{
cbuf_1grow (p, *p->curp);
p->curp++;
}
}
}
while (continuation_line_p (p, quote));
}
static char *
copy_string (struct lexer_data *p)
{
copy_string0 (p, 1);
cbuf_1grow (p, 0);
return cbuf_finish (p);
}
static char *
copy_to (struct lexer_data *p, const char *delim)
{
while (*p->curp)
{
if (*p->curp == '"' || *p->curp == '\'')
{
int quote = *p->curp;
cbuf_1grow (p, quote);
copy_string0 (p, 0);
cbuf_1grow (p, quote);
continue;
}
if (strchr (delim, *p->curp))
break;
if (*p->curp == '\n')
mu_cfg_locus.line++;
cbuf_1grow (p, *p->curp);
p->curp++;
}
cbuf_1grow (p, 0);
return cbuf_finish (p);
}
static int
isword (int c)
{
if (mu_cfg_tie_in)
return c && c != ';' && c != '{';
return isalnum (c) || c == '_' || c == '-' || c == '.';
}
static char *
copy_alpha (struct lexer_data *p)
{
do
{
if (mu_cfg_tie_in && (*p->curp == '"' || *p->curp == '\''))
{
int quote = *p->curp;
cbuf_1grow (p, quote);
copy_string0 (p, 0);
cbuf_1grow (p, quote);
continue;
}
if (*p->curp == '\n')
mu_cfg_locus.line++;
cbuf_1grow (p, *p->curp);
p->curp++;
} while (*p->curp && isword (*p->curp));
cbuf_1grow (p, 0);
return cbuf_finish (p);
}
#define LEX_DEBUG(tok, arg1, arg2) \
do \
{ \
if (mu_debug_check_level (dbg, MU_DEBUG_TRACE2)) \
{ \
mu_debug_set_locus (dbg, \
mu_cfg_locus.file, mu_cfg_locus.line); \
mu_cfg_format_error (dbg, MU_DEBUG_TRACE2, "TOKEN %s \"%s\" \"%s\"", \
tok, \
arg1 ? arg1 : "", \
arg2 ? arg2 : ""); \
} \
} \
while (0)
static void
rtrim (char *arg)
{
int len = strlen (arg);
while (len > 0 && strchr (" \t\n\r", arg[len-1]))
len--;
arg[len] = 0;
}
int
default_lexer (void *dp, mu_debug_t dbg)
{
struct lexer_data *p = dp;
char *save_start;
char *tag, *label;
extern int mu_cfg_yydebug;
again:
skipws (p);
if (*p->curp == '#')
{
const char *start = ++p->curp;
skipline (p);
if (strncmp (start, "debug=", 6) == 0)
{
mu_log_level_t lev;
if (p->curp[0] == '\n')
{
mu_cfg_locus.line++;
*p->curp++ = 0;
}
if (mu_debug_level_from_string (start + 6, &lev, dbg) == 0)
{
mu_debug_set_level (dbg, lev);
mu_cfg_yydebug = lev & MU_DEBUG_LEVEL_MASK (MU_DEBUG_TRACE1);
}
}
goto again;
}
if (*p->curp == '/' && p->curp[1] == '/')
{
skipline (p);
goto again;
}
if (*p->curp == '/' && p->curp[1] == '*')
{
int keep_line = mu_cfg_locus.line;
p->curp += 2;
do
{
while (*p->curp != '*')
{
if (*p->curp == 0)
{
mu_cfg_perror (&mu_cfg_locus,
_("unexpected EOF in comment started at line %d"),
keep_line);
return 0;
}
else if (*p->curp == '\n')
mu_cfg_locus.line++;
++p->curp;
}
} while (*++p->curp != '/');
++p->curp;
goto again;
}
if (*p->curp == 0)
{
LEX_DEBUG ("EOF", NULL, NULL);
return 0;
}
if (*p->curp == '"' || *p->curp == '\'')
{
mu_cfg_yylval.string = copy_string (p);
LEX_DEBUG ("STRING", mu_cfg_yylval.string, NULL);
return MU_CFG_STRING_TOKEN;
}
if (mu_cfg_tie_in)
{
mu_cfg_yylval.string = copy_alpha (p);
LEX_DEBUG ("STRING", mu_cfg_yylval.string, NULL);
return MU_CFG_STRING_TOKEN;
}
if (*p->curp == '}')
{
p->curp++;
memset (&mu_cfg_yylval.node, 0, sizeof mu_cfg_yylval.node);
mu_cfg_yylval.node.locus = mu_cfg_locus;
LEX_DEBUG ("END", NULL, NULL);
return MU_CFG_END_TOKEN;
}
if (*p->curp == ';')
{
p->curp++;
LEX_DEBUG ("EOL", NULL, NULL);
return MU_CFG_EOL_TOKEN;
}
tag = copy_alpha (p);
skipws (p);
if (*tag == '"')
{
mu_cfg_yylval.string = tag;
LEX_DEBUG ("STRING", mu_cfg_yylval.string, NULL);
return MU_CFG_STRING_TOKEN;
}
save_start = p->curp;
if (*p->curp != '{')
{
label = copy_to (p, ";{");
rtrim (label);
}
else
label = NULL;
if (*p->curp == '{')
{
p->curp++;
mu_cfg_yylval.node.tag_name = tag;
mu_cfg_yylval.node.locus = mu_cfg_locus;
mu_cfg_yylval.node.tag_label = label;
LEX_DEBUG ("START", tag, label);
return MU_CFG_START_TOKEN;
}
else
{
p->curp = save_start;
mu_cfg_yylval.string = tag;
}
LEX_DEBUG ("STRING", mu_cfg_yylval.string, NULL);
return MU_CFG_STRING_TOKEN;
}
int
mu_get_config (const char *file, const char *progname,
struct mu_cfg_param *progparam, int flags, void *target_ptr)
{
struct lexer_data data;
struct stat st;
int fd;
int rc;
mu_cfg_tree_t *parse_tree;
if (stat (file, &st))
{
if (errno != ENOENT)
mu_error (_("can't stat `%s': %s"), file, mu_strerror (errno));
return -1;
}
fd = open (file, O_RDONLY);
if (fd == -1)
{
mu_error (_("cannot open config file `%s': %s"), file,
mu_strerror (errno));
return -1;
}
if (flags & MU_PARSE_CONFIG_VERBOSE)
mu_error (_("Info: parsing file `%s'"), file);
memset (&data, 0, sizeof data);
data.buffer = malloc (st.st_size+1);
read (fd, data.buffer, st.st_size);
data.buffer[st.st_size] = 0;
close (fd);
data.curp = data.buffer;
/* Parse configuration */
mu_cfg_locus.file = (char*) file;
mu_cfg_locus.line = 1;
rc = mu_cfg_parse (&parse_tree,
&data,
default_lexer,
NULL,
NULL,
NULL);
if (rc == 0)
rc = mu_cfg_tree_reduce (parse_tree, progname, progparam, flags,
target_ptr);
mu_cfg_destroy_tree (&parse_tree);
mu_list_destroy (&data.mpool);
free (data.cbuf);
free (data.buffer);
if (flags & MU_PARSE_CONFIG_VERBOSE)
mu_error (_("Info: finished parsing file `%s'"), file);
return rc;
}
%{
/* cfg_lexer.l -- default lexer for Mailutils configuration files
Copyright (C) 2007, 2008 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.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <ctype.h>
#include <mailutils/errno.h>
#include <mailutils/error.h>
#include <mailutils/debug.h>
#include <mailutils/argcv.h>
#include <mailutils/alloc.h>
#include <mailutils/nls.h>
#include <mailutils/cfg.h>
#include <mailutils/list.h>
#include "cfg_parser.h"
void _mu_line_begin (void);
void _mu_line_add (char *text, size_t len);
char *_mu_line_finish (void);
static void _mu_line_add_unescape_last (char *text, size_t len);
static void multiline_begin (char *p);
static char *multiline_strip_tabs (char *text);
static void multiline_add (char *s);
static char *multiline_finish (void);
static char *multiline_delimiter;
static size_t multiline_delimiter_len;
static int multiline_unescape; /* Unescape here-document contents */
static int (*char_to_strip)(char); /* Strip matching characters of each
here-document line */
static int isemptystr(int off);
static mu_opool_t pool;
%}
%x COMMENT ML STR
WS [ \t\f][ \t\f]*
ID [a-zA-Z_][a-zA-Z_0-9-]+
P [1-9][0-9]*
%%
/* C-style comments */
"/*" BEGIN(COMMENT);
<COMMENT>[^*\n]* /* eat anything that's not a '*' */
<COMMENT>"*"+[^*/\n]* /* eat up '*'s not followed by '/'s */
<COMMENT>\n ++mu_cfg_locus.line;
<COMMENT>"*"+"/" BEGIN (INITIAL);
/* End-of-line comments */
#.*\n { mu_cfg_locus.line++; }
#.* /* end-of-file comment */;
"//".*\n { mu_cfg_locus.line++; }
"//".* /* end-of-file comment */;
/* Identifiers */
<INITIAL>{ID} {
_mu_line_begin ();
_mu_line_add (yytext, yyleng);
yylval.string = _mu_line_finish ();
return MU_TOK_IDENT; }
/* Strings */
[a-zA-Z0-9_\./:-]+ { _mu_line_begin ();
_mu_line_add (yytext, yyleng);
yylval.string = _mu_line_finish ();
return MU_TOK_STRING; }
/* Quoted strings */
\"[^\\"\n]*\" { _mu_line_begin ();
_mu_line_add (yytext + 1, yyleng - 2);
yylval.string = _mu_line_finish ();
return MU_TOK_QSTRING; }
\"[^\\"\n]*\\. |
\"[^\\"\n]*\\\n { BEGIN (STR);
_mu_line_begin ();
_mu_line_add_unescape_last (yytext + 1, yyleng - 1); }
<STR>[^\\"\n]*\\. |
<STR>\"[^\\"\n]*\\\n { _mu_line_add_unescape_last (yytext, yyleng); }
<STR>[^\\"\n]*\" { BEGIN (INITIAL);
if (yyleng > 1)
_mu_line_add (yytext, yyleng - 1);
yylval.string = _mu_line_finish ();
return MU_TOK_QSTRING; }
/* Multiline strings */
"<<"(-" "?)?\\?{ID}[ \t]*#.*\n |
"<<"(-" "?)?\\?{ID}[ \t]*"//".*\n |
"<<"(-" "?)?\\?{ID}[ \t]*\n |
"<<"(-" "?)?\"{ID}\"[ \t]*#.*\n |
"<<"(-" "?)?\"{ID}\"[ \t]*"//".*\n |
"<<"(-" "?)?\"{ID}\"[ \t]*\n {
BEGIN (ML);
multiline_begin (yytext+2);
mu_cfg_locus.line++;
}
<ML>.*\n { char *p = multiline_strip_tabs (yytext);
if (!strncmp (p, multiline_delimiter, multiline_delimiter_len)
&& isemptystr (p + multiline_delimiter_len - yytext))
{
free (multiline_delimiter);
multiline_delimiter = NULL;
BEGIN (INITIAL);
yylval.string = multiline_finish ();
return MU_TOK_MSTRING;
}
mu_cfg_locus.line++;
multiline_add (p); }
{WS} ;
/* Other tokens */
\n { mu_cfg_locus.line++; }
[,;{}()] return yytext[0];
. mu_cfg_perror (&mu_cfg_locus, _("stray character \\%03o"), yytext[0]);
%%
int
yywrap ()
{
return 1;
}
static void
unescape_to_line (int c)
{
if (c != '\n')
{
char t = mu_argcv_unquote_char (c);
if (t == c)
mu_cfg_perror (&mu_cfg_locus, _("unknown escape sequence '\\%c'"), c);
mu_opool_append_char (pool, t);
}
}
void
_mu_line_add (char *text, size_t len)
{
mu_opool_append (pool, text, len);
}
void
_mu_line_add_unescape_last (char *text, size_t len)
{
mu_opool_append (pool, text, len - 2);
unescape_to_line (text[len - 1]);
}
void
_mu_line_begin ()
{
if (!pool)
mu_opool_create (&pool, 1);
else
mu_opool_clear (pool);
}
char *
_mu_line_finish ()
{
mu_opool_append_char (pool, 0);
return mu_opool_finish (pool, NULL);
}
static int
is_tab (char c)
{
return c == '\t';
}
static int
is_ws (char c)
{
return c == '\t' || c == ' ';
}
static int
isemptystr (int off)
{
for (; yytext[off] && isspace (yytext[off]); off++)
;
if (yytext[off] == ';')
{
int i;
for (i = off + 1; yytext[i]; i++)
if (!isspace (yytext[i]))
return 0;
yyless (off);
return 1;
}
return yytext[off] == 0;
}
static void
multiline_begin (char *p)
{
if (*p == '-')
{
if (*++p == ' ')
{
char_to_strip = is_ws;
p++;
}
else
char_to_strip = is_tab;
}
else
char_to_strip = NULL;
if (*p == '\\')
{
p++;
multiline_unescape = 0;
}
else if (*p == '"')
{
char *q;
p++;
multiline_unescape = 0;
q = strchr (p, '"');
multiline_delimiter_len = q - p;
}
else
{
multiline_delimiter_len = strcspn (p, " \t");
multiline_unescape = 1;
}
/* Remove trailing newline */
multiline_delimiter_len--;
multiline_delimiter = mu_alloc (multiline_delimiter_len + 1);
memcpy (multiline_delimiter, p, multiline_delimiter_len);
multiline_delimiter[multiline_delimiter_len] = 0;
_mu_line_begin ();
}
static char *
multiline_strip_tabs (char *text)
{
if (char_to_strip)
for (; *text && char_to_strip (*text); text++)
;
return text;
}
static void
multiline_add (char *s)
{
if (multiline_unescape)
{
for (; *s; s++)
{
if (*s == '\\')
{
unescape_to_line (s[1]);
++s;
}
else
_mu_line_add (s, 1);
}
}
else
_mu_line_add (s, strlen (s));
}
static char *
multiline_finish ()
{
return _mu_line_finish ();
}
int
mu_get_config (const char *file, const char *progname,
struct mu_cfg_param *progparam, int flags, void *target_ptr)
{
struct stat st;
FILE *fp;
int rc;
mu_cfg_tree_t *parse_tree;
if (stat (file, &st))
{
if (errno != ENOENT)
mu_error (_("cannot stat `%s': %s"), file, mu_strerror (errno));
return -1;
}
fp = fopen (file, "r");
if (!fp)
{
mu_error (_("cannot open config file `%s': %s"), file,
mu_strerror (errno));
return -1;
}
if (flags & MU_PARSE_CONFIG_VERBOSE)
mu_error (_("Info: parsing file `%s'"), file);
yy_flex_debug = mu_debug_check_level (mu_cfg_get_debug (), MU_DEBUG_TRACE2);
/* Parse configuration */
mu_cfg_locus.file = (char*) file;
mu_cfg_locus.line = 1;
yyrestart (fp);
rc = mu_cfg_parse (&parse_tree);
if (rc == 0)
rc = mu_cfg_tree_reduce (parse_tree, progname, progparam, flags,
target_ptr);
mu_cfg_destroy_tree (&parse_tree);
if (flags & MU_PARSE_CONFIG_VERBOSE)
mu_error (_("Info: finished parsing file `%s'"), file);
return rc;
}
mu_opool_t
mu_cfg_lexer_pool ()
{
mu_opool_t p = pool;
pool = NULL;
return p;
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001, 2004, 2005,
2007 Free Software Foundation, Inc.
2007, 2008 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
......@@ -102,24 +102,26 @@ int
mu_debug_level_from_string (const char *string, mu_log_level_t *plev,
mu_debug_t debug)
{
char *p = string, *q;
char *q;
unsigned level = MU_DEBUG_INHERIT;
if (isdigit (*p))
if (isdigit (*string))
{
level = strtoul (p, &q, 0);
level = strtoul (string, &q, 0);
if (*q)
{
mu_cfg_format_error (debug, MU_DEBUG_ERROR,
_("invalid debugging specification `%s': "
"expected levels or number after `=', "
"but found `%s'"),
string, p);
string, string);
return MU_ERR_FAILURE;
}
}
else
{
char *p = strdup (string);
for (q = strtok (p, ","); q; q = strtok (NULL, ","))
{
int flag;
......@@ -156,6 +158,7 @@ mu_debug_level_from_string (const char *string, mu_log_level_t *plev,
level |= MU_DEBUG_LEVEL_MASK (flag);
}
}
free (p);
}
*plev = level;
return 0;
......
......@@ -161,6 +161,7 @@ mu_list_get_comparator (mu_list_t list, mu_list_comparator_t *comp)
if (!list)
return EINVAL;
*comp = list->comp;
return 0;
}
static int
......
......@@ -758,7 +758,7 @@ m_srv_conn (int fd, struct sockaddr *sa, int salen,
unsigned short
get_port (mu_debug_t debug, char *p)
get_port (mu_debug_t debug, const char *p)
{
if (p)
{
......@@ -787,7 +787,7 @@ get_port (mu_debug_t debug, char *p)
}
static int
get_family (char **pstr, sa_family_t *pfamily)
get_family (const char **pstr, sa_family_t *pfamily)
{
static struct family_tab
{
......@@ -807,7 +807,7 @@ get_family (char **pstr, sa_family_t *pfamily)
};
struct family_tab *fp;
char *str = *pstr;
const char *str = *pstr;
int len = strlen (str);
for (fp = ftab; fp->len; fp++)
{
......@@ -847,7 +847,7 @@ is_ip_addr (const char *arg)
}
int
_mu_m_server_parse_url (mu_debug_t debug, char *arg, union m_sockaddr *s,
_mu_m_server_parse_url (mu_debug_t debug, const char *arg, union m_sockaddr *s,
int *psalen, struct sockaddr *defsa)
{
char *p;
......@@ -948,7 +948,7 @@ mu_m_server_parse_url (mu_m_server_t msrv, char *arg,
}
static int
server_block_begin (mu_debug_t debug, char *arg, mu_m_server_t msrv,
server_block_begin (mu_debug_t debug, const char *arg, mu_m_server_t msrv,
void **pdata)
{
union m_sockaddr s;
......@@ -970,8 +970,10 @@ server_section_parser (enum mu_cfg_section_stage stage,
{
case mu_cfg_section_start:
{
if (node->label->type != MU_CFG_STRING)
return 1;
/* FIXME: should not modify 2nd arg, or it should not be const */
return server_block_begin (tree->debug, node->tag_label,
return server_block_begin (tree->debug, node->label->v.string,
*section_data, section_data);
}
break;
......@@ -988,14 +990,16 @@ server_section_parser (enum mu_cfg_section_stage stage,
}
static int
_cb_daemon_mode (mu_debug_t debug, void *data, char *arg)
_cb_daemon_mode (mu_debug_t debug, void *data, mu_config_value_t *val)
{
int *pmode = data;
if (strcmp (arg, "inetd") == 0
|| strcmp (arg, "interactive") == 0)
if (mu_cfg_assert_value_type (val, MU_CFG_STRING, debug))
return 1;
if (strcmp (val->v.string, "inetd") == 0
|| strcmp (val->v.string, "interactive") == 0)
*pmode = MODE_INTERACTIVE;
else if (strcmp (arg, "daemon") == 0)
else if (strcmp (val->v.string, "daemon") == 0)
*pmode = MODE_DAEMON;
else
{
......@@ -1006,11 +1010,14 @@ _cb_daemon_mode (mu_debug_t debug, void *data, char *arg)
}
static int
_cb_port (mu_debug_t debug, void *data, char *arg)
_cb_port (mu_debug_t debug, void *data, mu_config_value_t *val)
{
struct m_default_address *ap = data;
unsigned short num = get_port (debug, arg);
unsigned short num;
if (mu_cfg_assert_value_type (val, MU_CFG_STRING, debug))
return 1;
num = get_port (debug, val->v.string);
if (!num)
return 1;
ap->s.s_in.sin_family = AF_INET;
......
/* String-list functions for GNU Mailutils.
Copyright (C) 2007, 2008 Free Software Foundation, Inc.
Based on slist module from GNU Radius. Written by Sergey Poznyakoff.
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.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <mailutils/types.h>
#include <mailutils/alloc.h>
#include <mailutils/opool.h>
struct mu_opool_bucket
{
struct mu_opool_bucket *next;
char *buf;
size_t level;
size_t size;
};
struct _mu_opool
{
int memerr;
struct mu_opool_bucket *head, *tail;
struct mu_opool_bucket *free;
};
static struct mu_opool_bucket *
alloc_bucket (struct _mu_opool *opool, size_t size)
{
struct mu_opool_bucket *p = malloc (sizeof (*p) + size);
if (!p)
{
if (opool->memerr)
mu_alloc_die ();
}
else
{
p->buf = (char*)(p + 1);
p->level = 0;
p->size = size;
p->next = NULL;
}
return p;
}
static int
alloc_pool (mu_opool_t opool, size_t size)
{
struct mu_opool_bucket *p = alloc_bucket (opool, MU_OPOOL_BUCKET_SIZE);
if (!p)
return ENOMEM;
if (opool->tail)
opool->tail->next = p;
else
opool->head = p;
opool->tail = p;
return 0;
}
static int
copy_chars (mu_opool_t opool, const char *str, size_t n, size_t *psize)
{
size_t rest;
if (!opool->head || opool->tail->level == opool->tail->size)
if (alloc_pool (opool, MU_OPOOL_BUCKET_SIZE))
return ENOMEM;
rest = opool->tail->size - opool->tail->level;
if (n > rest)
n = rest;
memcpy (opool->tail->buf + opool->tail->level, str, n);
opool->tail->level += n;
*psize = n;
return 0;
}
int
mu_opool_create (mu_opool_t *pret, int memerr)
{
struct _mu_opool *x = malloc (sizeof (x[0]));
if (!x)
{
if (memerr)
mu_alloc_die ();
return ENOMEM;
}
x->memerr = memerr;
x->head = x->tail = x->free = 0;
*pret = x;
return 0;
}
void
mu_opool_clear (mu_opool_t opool)
{
if (!opool)
return;
if (opool->tail)
{
opool->tail->next = opool->free;
opool->free = opool->head;
opool->head = opool->tail = NULL;
}
}
void
mu_opool_destroy (mu_opool_t *popool)
{
struct mu_opool_bucket *p;
if (popool && *popool)
{
mu_opool_t opool = *popool;
mu_opool_clear (opool);
for (p = opool->free; p; )
{
struct mu_opool_bucket *next = p->next;
free (p);
p = next;
}
free (opool);
}
*popool = NULL;
}
int
mu_opool_append (mu_opool_t opool, const void *str, size_t n)
{
const char *ptr = str;
while (n)
{
size_t s;
if (copy_chars (opool, ptr, n, &s))
return ENOMEM;
ptr += s;
n -= s;
}
return 0;
}
int
mu_opool_append_char (mu_opool_t opool, char c)
{
return mu_opool_append (opool, &c, 1);
}
int
mu_opool_appendz (mu_opool_t opool, const char *str)
{
return mu_opool_append (opool, str, strlen (str))
|| mu_opool_append_char (opool, 0);
}
size_t
mu_opool_size (mu_opool_t opool)
{
size_t size = 0;
struct mu_opool_bucket *p;
for (p = opool->head; p; p = p->next)
size += p->level;
return size;
}
int
mu_opool_coalesce (mu_opool_t opool, size_t *psize)
{
size_t size;
if (opool->head && opool->head->next == NULL)
size = opool->head->level;
else {
struct mu_opool_bucket *bucket;
struct mu_opool_bucket *p;
size = mu_opool_size (opool);
bucket = alloc_bucket (opool, size);
if (!bucket)
return ENOMEM;
for (p = opool->head; p; )
{
struct mu_opool_bucket *next = p->next;
memcpy (bucket->buf + bucket->level, p->buf, p->level);
bucket->level += p->level;
free (p);
p = next;
}
opool->head = opool->tail = bucket;
}
if (psize)
*psize = size;
return 0;
}
void *
mu_opool_head (mu_opool_t opool, size_t *psize)
{
if (*psize)
*psize = opool->head ? opool->head->level : 0;
return opool->head ? opool->head->buf : NULL;
}
void *
mu_opool_finish (mu_opool_t opool, size_t *psize)
{
if (mu_opool_coalesce (opool, psize))
return NULL;
mu_opool_clear (opool);
return opool->free->buf;
}
......@@ -21,6 +21,7 @@
#include <string.h>
#include <mailutils/diag.h>
#include <mailutils/kwd.h>
#include <mailutils/syslog.h>
static mu_kwd_t kw_facility[] = {
{ "USER", LOG_USER },
......@@ -41,7 +42,7 @@ static mu_kwd_t kw_facility[] = {
};
static int
syslog_to_n (mu_kwd_t *kw, char *str, int *pint)
syslog_to_n (mu_kwd_t *kw, const char *str, int *pint)
{
if (strncasecmp (str, "LOG_", 4) == 0)
str += 4;
......@@ -49,7 +50,7 @@ syslog_to_n (mu_kwd_t *kw, char *str, int *pint)
}
int
mu_string_to_syslog_facility (char *str, int *pfacility)
mu_string_to_syslog_facility (const char *str, int *pfacility)
{
return syslog_to_n (kw_facility, str, pfacility);
}
......@@ -75,7 +76,7 @@ static mu_kwd_t kw_prio[] = {
};
int
mu_string_to_syslog_priority (char *str, int *pprio)
mu_string_to_syslog_priority (const char *str, int *pprio)
{
return syslog_to_n (kw_prio, str, pprio);
}
......
......@@ -69,7 +69,7 @@ char *mimeview_file; /* Name of the file to view */
FILE *mimeview_fp; /* Its descriptor */
static void
set_debug_flags (mu_debug_t debug, char *arg)
set_debug_flags (mu_debug_t debug, const char *arg)
{
for (; *arg; arg++)
{
......@@ -152,16 +152,11 @@ static struct argp argp = {
static int
cb_debug (mu_debug_t debug, void *data, char *arg)
cb_debug (mu_debug_t debug, void *data, mu_config_value_t *val)
{
set_debug_flags (debug, arg);
return 0;
}
static int
cb_metamail (mu_debug_t debug, void *data, char *arg)
{
metamail = strdup ("metamail");
if (mu_cfg_assert_value_type (val, MU_CFG_STRING, debug))
return 1;
set_debug_flags (debug, val->v.string);
return 0;
}
......@@ -172,7 +167,7 @@ struct mu_cfg_param mimeview_cfg_param[] = {
{ "mimetypes", mu_cfg_string, &mimetypes_config, 0, NULL,
N_("Use this mime.types file."),
N_("file") },
{ "metamail", mu_cfg_string, NULL, 0, cb_metamail,
{ "metamail", mu_cfg_string, &metamail, 0, NULL,
N_("Use this program to display files."),
N_("prog") },
{ NULL }
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2007 Free Software Foundation, Inc.
Copyright (C) 2007, 2008 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
......@@ -22,7 +22,7 @@ static char *bulletin_mbox_name;
static char *bulletin_db_name;
void
set_bulletin_db (char *file)
set_bulletin_db (const char *file)
{
bulletin_db_name = strdup (file);
}
......@@ -65,7 +65,7 @@ open_bulletin_mailbox (mu_mailbox_t *pmbox)
}
int
set_bulletin_source (char *source)
set_bulletin_source (const char *source)
{
bulletin_mbox_name = strdup (source);
return 0;
......
......@@ -31,6 +31,7 @@ mu_m_server_t server;
unsigned int idle_timeout;
int pop3d_transcript;
int debug_mode;
int tls_required;
#ifdef WITH_TLS
int tls_available;
......@@ -107,26 +108,21 @@ static struct argp_option options[] = {
{NULL, 0, NULL, 0, NULL, 0}
};
#ifdef WITH_TLS
static int
cb_tls_required (mu_debug_t debug, void *data, char *arg)
{
initial_state = INITIAL;
return 0;
}
#endif
static int
cb_bulletin_source (mu_debug_t debug, void *data, char *arg)
cb_bulletin_source (mu_debug_t debug, void *data, mu_config_value_t *val)
{
set_bulletin_source (arg); /* FIXME: Error reporting? */
if (mu_cfg_assert_value_type (val, MU_CFG_STRING, debug))
return 1;
set_bulletin_source (val->v.string); /* FIXME: Error reporting? */
return 0;
}
static int
cb_bulletin_db (mu_debug_t debug, void *data, char *arg)
cb_bulletin_db (mu_debug_t debug, void *data, mu_config_value_t *val)
{
set_bulletin_db (arg); /* FIXME: Error reporting? */
if (mu_cfg_assert_value_type (val, MU_CFG_STRING, debug))
return 1;
set_bulletin_db (val->v.string); /* FIXME: Error reporting? */
return 0;
}
......@@ -139,7 +135,7 @@ static struct mu_cfg_param pop3d_cfg_param[] = {
{ "delete-expired", mu_cfg_int, &expire_on_exit, 0, NULL,
N_("Delete expired messages upon closing the mailbox.") },
#ifdef WITH_TLS
{ "tls-required", mu_cfg_callback, NULL, 0, cb_tls_required,
{ "tls-required", mu_cfg_bool, &tls_required, 0, NULL,
N_("Always require STLS before entering authentication phase.") },
#endif
#ifdef ENABLE_LOGIN_DELAY
......@@ -493,6 +489,9 @@ main (int argc, char **argv)
argc, argv, 0, NULL, server))
exit (EX_CONFIG); /* FIXME: No way to discern from EX_USAGE? */
if (tls_required)
initial_state = INITIAL;
if (expire == 0)
expire_on_exit = 1;
......
......@@ -287,8 +287,8 @@ extern void pop3d_unmark_retr (mu_attribute_t attr);
extern void expire_mark_message (mu_message_t msg, char **value);
extern void deliver_pending_bulletins (void);
extern void set_bulletin_db (char *file);
extern int set_bulletin_source (char *source);
extern void set_bulletin_db (const char *file);
extern int set_bulletin_source (const char *source);
extern int pop3d_begin_session (void);
......
......@@ -261,16 +261,20 @@ static struct argp argp =
static int
cb_debug (mu_debug_t debug, void *data, char *arg)
cb_debug (mu_debug_t debug, void *data, mu_config_value_t *val)
{
set_debug_level (debug, arg);
if (mu_cfg_assert_value_type (val, MU_CFG_STRING, debug))
return 1;
set_debug_level (debug, val->v.string);
return 0;
}
static int
cb_email (mu_debug_t debug, void *data, char *arg)
cb_email (mu_debug_t debug, void *data, mu_config_value_t *val)
{
int rc = mu_set_user_email (arg);
if (mu_cfg_assert_value_type (val, MU_CFG_STRING, debug))
return 1;
int rc = mu_set_user_email (val->v.string);
if (rc)
mu_cfg_format_error (debug, MU_DEBUG_ERROR, _("Invalid email: %s"),
mu_strerror (rc));
......@@ -278,10 +282,12 @@ cb_email (mu_debug_t debug, void *data, char *arg)
}
static int
cb_ticket (mu_debug_t debug, void *data, char *arg)
cb_ticket (mu_debug_t debug, void *data, mu_config_value_t *val)
{
if (mu_cfg_assert_value_type (val, MU_CFG_STRING, debug))
return 1;
free (tickets);
tickets = mu_tilde_expansion (arg, "/", NULL);
tickets = mu_tilde_expansion (val->v.string, "/", NULL);
tickets_default = 0;
return 0;
}
......