aboutsummaryrefslogtreecommitdiff
path: root/pies
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2008-11-12 14:45:00 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2008-11-12 14:45:00 +0000
commitf2104f12be8f330f4a6f8164a3698fb06053e1ad (patch)
tree59db3d2d50bf67c29e9c1ab989a65422bedbd215 /pies
parent0af7127c5084ffc3550de8d98e00582975eb6113 (diff)
downloadpies-f2104f12be8f330f4a6f8164a3698fb06053e1ad.tar.gz
pies-f2104f12be8f330f4a6f8164a3698fb06053e1ad.tar.bz2
Implement MeTA1 configuration file parser.
* configure.ac: Require Mailutils 1.9.93 * doc/mailfromd.texi, NEWS: Update. * pies/pies.c (_cb_depend): Accept list argument. (component_cfg_param): New statement: program. (pies_cfg_param): New statements: include-meta1 and meta1-queue-dir. (parse_meta1_conf, pies_cfg_verifier): New functions. (main): Set mu_app_cfg_verifier. Call parse_meta1_conf. * pies/progman.c (progman_lookup_component): New function. (prog_start): Pass program name (eventually differing from argv[0]). * pies/pies.h (struct component): New member `program'. (progman_lookup_component): New prototype. * pies/meta1gram.y, pies/meta1lex.h, pies/meta1lex.l: New files. * pies/Makefile.am (pies_SOURCES): Add meta1gram.y and pies/meta1lex.h. (noinst_HEADERS, AM_YFLAGS, AM_LFLAGS): New variables.
Diffstat (limited to 'pies')
-rw-r--r--pies/Makefile.am13
-rw-r--r--pies/meta1gram.y405
-rw-r--r--pies/meta1lex.h31
-rw-r--r--pies/meta1lex.l231
-rw-r--r--pies/pies.c67
-rw-r--r--pies/pies.h2
-rw-r--r--pies/progman.c16
7 files changed, 759 insertions, 6 deletions
diff --git a/pies/Makefile.am b/pies/Makefile.am
index 70c33cd..12a4f4d 100644
--- a/pies/Makefile.am
+++ b/pies/Makefile.am
@@ -19,17 +19,25 @@ sbin_PROGRAMS = pies
pies_SOURCES = \
depmap.c\
limits.c\
+ meta1gram.y\
+ meta1lex.l\
pies.c\
progman.c\
- pies.h\
socket.c
+noinst_HEADERS = \
+ meta1gram.h\
+ meta1lex.h\
+ pies.h
+
EXTRA_DIST = pies.rcin
noinst_DATA = pies.rc
DISTCLEANFILES = pies.rc
.rcin.rc:
sed 's|SBINDIR|$(sbindir)|g' $< > $@
+meta1lex.c: meta1gram.h
+
INCLUDES = \
$(MAILUTILS_INCLUDES)\
$(MU_COMMON_INCLUDES)\
@@ -44,3 +52,6 @@ LDADD = \
AM_CPPFLAGS=-DSYSCONFDIR=\"$(sysconfdir)\"\
-DSTATEDIR=\"$(localstatedir)\"
+
+AM_YFLAGS=-dvt -pmeta1
+AM_LFLAGS=-dvp -Pmeta1 -olex.yy.c
diff --git a/pies/meta1gram.y b/pies/meta1gram.y
new file mode 100644
index 0000000..460916e
--- /dev/null
+++ b/pies/meta1gram.y
@@ -0,0 +1,405 @@
+%{
+/* MeTA1 configuration parser for Mailfromd.
+ Copyright (C) 2008 Sergey Poznyakoff
+
+ This program 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/>. */
+
+/* This file implements a grammar for parsing MeTA1 main configuration file,
+ and a set of functions for converting its statements into Pies
+ configuration statements. */
+
+#include "pies.h"
+#include "meta1lex.h"
+
+/* FIXME: Use mu_opool_alloc? */
+static mu_config_value_t *
+create_value (int type)
+{
+ mu_config_value_t *val = mu_alloc (sizeof (*val));
+ val->type = type;
+ return val;
+}
+
+static mu_config_value_t *
+config_value_dup (mu_config_value_t *src)
+{
+ if (!src)
+ return NULL;
+ else
+ {
+ mu_config_value_t *val = mu_alloc (sizeof (*val));
+ *val = *src;
+ return val;
+ }
+}
+
+static mu_cfg_node_t *
+alloc_node (enum mu_cfg_node_type type, mu_cfg_locus_t *loc,
+ const char *tag, mu_config_value_t *label,
+ mu_cfg_node_t *node)
+{
+ char *p;
+ mu_cfg_node_t *np;
+ size_t size = sizeof *np + strlen (tag) + 1;
+ np = mu_alloc (size);
+ np->type = type;
+ np->locus = *loc;
+ p = (char*) (np + 1);
+ np->tag = p;
+ strcpy (p, tag);
+ np->label = label;
+ np->node = node;
+ np->next = NULL;
+ return np;
+}
+
+static mu_cfg_node_t *translate_component (mu_cfg_node_t *);
+
+mu_cfg_node_t *meta1_parse_head;
+
+%}
+
+%union {
+ mu_cfg_node_t node;
+ mu_cfg_node_t *pnode;
+ mu_config_value_t *value;
+ struct { mu_cfg_node_t *head, *tail; } nodelist;
+ char *string;
+ unsigned long number;
+ mu_list_t list;
+}
+
+%token <string> META1_IDENT META1_STRING META1_NUMBER
+
+%type <nodelist> stmtlist
+%type <pnode> stmt simple block
+%type <list> slist list values
+%type <string> string ident
+%type <value> value
+
+%%
+
+input : stmtlist
+ {
+ mu_cfg_node_t *node;
+ meta1_parse_head = NULL;
+ for (node = $1.head; node; node = node->next)
+ {
+ mu_cfg_node_t *new_node = translate_component (node);
+ if (new_node)
+ {
+ new_node->next = meta1_parse_head;
+ meta1_parse_head = new_node;
+ }
+ }
+ }
+ ;
+
+stmtlist: stmt
+ {
+ $$.head = $$.tail = $1;
+ }
+ | stmtlist stmt
+ {
+ $$ = $1;
+ $$.tail->next = $2;
+ $$.tail = $2;
+ }
+ ;
+
+stmt : simple
+ | block
+ ;
+
+simple : ident '=' value ';'
+ {
+ $$ = alloc_node (mu_cfg_node_param, &meta1_locus,
+ $1, $3,
+ NULL);
+ }
+ ;
+
+block : ident tag '{' stmtlist '}' opt_sc
+ {
+ /* FIXME: tag is currently ignored */
+ $$ = alloc_node (mu_cfg_node_tag, &meta1_locus,
+ $1, NULL,
+ $4.head);
+ }
+ ;
+
+tag : /* empty */
+ | META1_IDENT
+ ;
+
+ident : META1_IDENT
+ ;
+
+value : string
+ {
+ $$ = create_value (MU_CFG_STRING);
+ $$->v.string = $1;
+ }
+ | list
+ {
+ $$ = create_value (MU_CFG_LIST);
+ $$->v.list = $1;
+ }
+ | META1_NUMBER
+ {
+ $$ = create_value (MU_CFG_STRING);
+ $$->v.string = $1;
+ }
+ ;
+
+string : META1_IDENT
+ | slist
+ {
+ mu_iterator_t itr;
+ mu_list_get_iterator ($1, &itr);
+
+ meta1_line_begin ();
+ for (mu_iterator_first (itr);
+ !mu_iterator_is_done (itr); mu_iterator_next (itr))
+ {
+ char *p;
+ mu_iterator_current (itr, (void**)&p);
+ meta1_line_add (p, strlen (p));
+ }
+ $$ = meta1_line_finish ();
+ mu_iterator_destroy (&itr);
+ mu_list_destroy (&$1);
+ }
+ ;
+
+slist : META1_STRING
+ {
+ mu_list_create (&$$);
+ mu_list_append ($$, $1);
+ }
+ | slist META1_STRING
+ {
+ mu_list_append ($1, $2);
+ $$ = $1;
+ }
+ ;
+
+list : '{' values '}'
+ {
+ $$ = $2;
+ }
+ ;
+
+values : value
+ {
+ mu_list_create (&$$);
+ mu_list_append ($$, $1);
+ }
+ | values ',' value
+ {
+ mu_list_append ($1, $3);
+ $$ = $1;
+ }
+ ;
+
+opt_sc : /* empty */
+ | ';'
+ ;
+
+%%
+int
+yyerror (char *s)
+{
+ meta1_parse_error ("%s", s);
+}
+
+void
+meta1_parser_set_debug ()
+{
+ mu_log_level_t lev = mu_global_debug_level ("meta1");
+ if (lev & MU_DEBUG_LEVEL_MASK (MU_DEBUG_TRACE7))
+ yydebug = 1;
+}
+
+struct node_trans
+{
+ char *name;
+ char *new_name;
+ mu_cfg_node_t *(*fun) (const char *, mu_cfg_node_t *);
+};
+
+
+static struct node_trans *
+find_node_trans (struct node_trans *tab, const char *name)
+{
+ for (; tab->name; tab++)
+ if (strcmp (tab->name, name) == 0)
+ return tab;
+ return NULL;
+}
+
+static mu_cfg_node_t *
+find_node (mu_cfg_node_t *list, const char *name)
+{
+ for (; list; list = list->next)
+ {
+ if (strcmp (list->tag, name) == 0)
+ return list;
+ }
+ return NULL;
+}
+
+static mu_cfg_node_t *
+xlat_listen_socket (const char *name, mu_cfg_node_t *src)
+{
+ mu_cfg_node_t *p;
+ mu_config_value_t *val;
+
+ meta1_line_begin ();
+ p = find_node (src->node, "type");
+ if (!p || !p->label || p->label->type != MU_CFG_STRING)
+ return NULL;
+ meta1_line_add (p->label->v.string, strlen (p->label->v.string));
+ meta1_line_add ("://", 3);
+ if (strcmp (p->label->v.string, "inet") == 0)
+ {
+ const char *addr;
+ p = find_node (src->node, "address");
+ if (p)
+ {
+ if (p->label->type != MU_CFG_STRING)
+ return NULL;
+ addr = p->label->v.string;
+ }
+ else
+ addr = "0.0.0.0";
+ meta1_line_add (addr, strlen (addr));
+ meta1_line_add (":", 1);
+ p = find_node (src->node, "port");
+ if (p->label->type != MU_CFG_STRING)
+ return NULL;
+ meta1_line_add (p->label->v.string, strlen (p->label->v.string));
+ }
+ else if (strcmp (p->label->v.string, "unix") == 0)
+ {
+ p = find_node (src->node, "path");
+ if (!p || p->label->type != MU_CFG_STRING)
+ return NULL;
+ meta1_line_add (p->label->v.string, strlen (p->label->v.string));
+ /* FIXME: Other substatements:
+ listen_socket {
+ type=unix;
+ path = /tmp/socket;
+ umask = 077;
+ user = user;
+ group = group;
+ }
+ */
+ }
+ val = create_value (MU_CFG_STRING);
+ val->v.string = meta1_line_finish ();
+ return alloc_node (mu_cfg_node_param, &src->locus, "socket", val, NULL);
+}
+
+static struct node_trans root_node_trans[] = {
+ { "listen_socket", "socket", xlat_listen_socket },
+ { "start_action", "mode" },
+ { "pass_fd_socket", "pass-fd-socket" },
+ { "user", "user" },
+ { "path", "program" },
+ { "arguments", "command" },
+ /* FIXME: */
+ /* { "restart_dependencies", "depend", },*/
+ { NULL }
+};
+
+static mu_cfg_node_t *
+create_string_node (const char *tag, const char *str, mu_cfg_locus_t *locus)
+{
+ mu_config_value_t *val = create_value (MU_CFG_STRING);
+
+ val->v.string = meta1_string (str, strlen (str));
+ return alloc_node (mu_cfg_node_param, locus, tag, val, NULL);
+}
+
+static mu_cfg_node_t *
+translate_node (mu_cfg_node_t *src)
+{
+ mu_cfg_node_t *dst = NULL;
+ struct node_trans *nt = find_node_trans (root_node_trans, src->tag);
+
+ if (nt)
+ {
+ if (nt->fun)
+ dst = nt->fun (nt->new_name, src);
+ else
+ dst = alloc_node (mu_cfg_node_param, &src->locus,
+ nt->new_name, config_value_dup (src->label),
+ NULL);
+ }
+ return dst;
+}
+
+static mu_cfg_node_t *
+translate_node_list (mu_cfg_node_t *src)
+{
+ mu_cfg_node_t *head = NULL, *tail = NULL;
+ mu_cfg_locus_t *locus = &src->locus;
+
+ for (; src; src = src->next)
+ {
+ mu_cfg_node_t *dst = translate_node (src);
+ if (dst)
+ {
+ if (tail)
+ tail->next = dst;
+ else
+ head = dst;
+ tail = dst;
+ }
+ }
+ if (head)
+ {
+ /* Add common statements: */
+ mu_cfg_node_t *node;
+
+ node = create_string_node ("allgroups", "yes", locus);
+ tail->next = node;
+ tail = node;
+
+ node = create_string_node ("chdir",
+ meta1_queue_dir ?
+ meta1_queue_dir : "/var/spool/meta1",
+ locus);
+ tail->next = node;
+ tail = node;
+ }
+ return head;
+}
+
+static mu_cfg_node_t *
+translate_component (mu_cfg_node_t *src)
+{
+ mu_cfg_node_t *dst = NULL;
+ if (src->type == mu_cfg_node_tag)
+ {
+ mu_config_value_t *val = create_value (MU_CFG_STRING);
+ val->v.string = meta1_string (src->tag, strlen (src->tag));
+ dst = alloc_node (mu_cfg_node_tag, &src->locus,
+ "component", val,
+ translate_node_list (src->node));
+ }
+ return dst;
+}
+
diff --git a/pies/meta1lex.h b/pies/meta1lex.h
new file mode 100644
index 0000000..8db32f9
--- /dev/null
+++ b/pies/meta1lex.h
@@ -0,0 +1,31 @@
+/* This file is part of Mailfromd.
+ Copyright (C) 2008 Sergey Poznyakoff
+
+ This program 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/>. */
+
+extern mu_cfg_locus_t meta1_locus;
+extern size_t meta1_error_count;
+extern mu_cfg_node_t *meta1_parse_head;
+extern mu_cfg_tree_t *meta1_parse_tree;
+extern char *meta1_queue_dir;
+
+char *meta1_string (const char *str, size_t len);
+void meta1_line_add (const char *text, size_t len);
+void meta1_line_add_unescape_last (const char *text, size_t len);
+void meta1_line_add_unescape_hex (const char *text, size_t len);
+void meta1_line_begin (void);
+char *meta1_line_finish ();
+void meta1_parse_error (const char *fmt, ...);
+int meta1_config_parse (const char *name);
+
diff --git a/pies/meta1lex.l b/pies/meta1lex.l
new file mode 100644
index 0000000..4d8b9d0
--- /dev/null
+++ b/pies/meta1lex.l
@@ -0,0 +1,231 @@
+%{
+/* MeTA1 configuration lexer for Mailfromd.
+ Copyright (C) 2008 Sergey Poznyakoff
+
+ This program 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/>. */
+
+/* This file implements a lexical analyzer for MeTA1 main configuration file.
+ */
+
+#include "pies.h"
+#include "meta1gram.h"
+#include "meta1lex.h"
+
+mu_cfg_locus_t meta1_locus;
+size_t meta1_error_count;
+mu_opool_t meta1_pool;
+char *meta1_queue_dir;
+
+#define yylval meta1lval
+%}
+
+%x COMMENT STR
+X [0-9a-fA-F]
+%%
+ /* C-style comments */
+"/*" BEGIN (COMMENT);
+<COMMENT>[^*\n]* /* eat anything that's not a '*' */
+<COMMENT>"*"+[^*/\n]* /* eat up '*'s not followed by '/'s */
+<COMMENT>\n ++meta1_locus.line;
+<COMMENT>"*"+"/" BEGIN (INITIAL);
+ /* End-of-line comments */
+#.*\n { meta1_locus.line++; }
+#.* /* end-of-file comment */;
+ /* Number */
+0[xX]{X}+ |
+0[0-7]+ |
+[1-9][0-9]+ { meta1_line_begin ();
+ meta1_line_add (yytext, yyleng);
+ yylval.string = meta1_line_finish ();
+ return META1_NUMBER; }
+ /* Identifiers (unquoted strings) */
+[a-zA-Z0-9_\./:\*-]+ { meta1_line_begin ();
+ meta1_line_add (yytext, yyleng);
+ yylval.string = meta1_line_finish ();
+ return META1_IDENT; }
+ /* Quoted strings */
+\"[^\\"\n]*\" { meta1_line_begin ();
+ meta1_line_add (yytext + 1, yyleng - 2);
+ yylval.string = meta1_line_finish ();
+ return META1_STRING; }
+\"[^\\"\n]*\\x{X}{1,2} { BEGIN(STR);
+ meta1_line_begin ();
+ meta1_line_add_unescape_hex (yytext + 1, yyleng - 1);
+ }
+\"[^\\"\n]*\\. { BEGIN(STR);
+ meta1_line_begin ();
+ meta1_line_add_unescape_last (yytext + 1, yyleng - 1); }
+<STR>[^\\"\n]*\\x{X}{1,2} { meta1_line_add_unescape_hex (yytext, yyleng); }
+<STR>[^\\"\n]*\\. { meta1_line_add_unescape_last (yytext, yyleng); }
+<STR>[^\\"\n]*\" { BEGIN (INITIAL);
+ if (yyleng > 1)
+ meta1_line_add (yytext, yyleng - 1);
+ yylval.string = meta1_line_finish ();
+ return META1_STRING; }
+<STR>[^\\"\n]*\n { BEGIN (INITIAL);
+ meta1_parse_error (_("newline in a string"));
+ meta1_line_add (yytext, yyleng - 1);
+ yylval.string = meta1_line_finish ();
+ return META1_STRING; }
+ /* Other tokens */
+[ \t\f][ \t\f]* ;
+\n { meta1_locus.line++; }
+[,;{}=] return yytext[0];
+. { if (isascii (yytext[0]) && isprint (yytext[0]))
+ meta1_parse_error (_("stray character %c"), yytext[0]);
+ else
+ meta1_parse_error (_("stray character \\%03o"),
+ (unsigned char) yytext[0]); }
+%%
+
+int
+yywrap ()
+{
+ return 1;
+}
+
+void
+meta1_line_add (const char *text, size_t len)
+{
+ mu_opool_append (meta1_pool, text, len);
+}
+
+static void
+unescape_to_line (int c)
+{
+ char t;
+
+ if (c == 'v')
+ t = '\v';
+ else
+ {
+ t = mu_argcv_unquote_char (c);
+ if (t == c && t != '\\' && t != '\"')
+ meta1_parse_error (_("unknown escape sequence '\\%c'"), c);
+ }
+ mu_opool_append_char (meta1_pool, t);
+}
+
+void
+meta1_line_add_unescape_last (const char *text, size_t len)
+{
+ mu_opool_append (meta1_pool, text, len - 2);
+ unescape_to_line (text[len - 1]);
+}
+
+void
+meta1_line_add_unescape_hex (const char *text, size_t len)
+{
+ for (; text[len-1] != 'x' && len > 0; len--)
+ ;
+ mu_opool_append (meta1_pool, text, len - 2);
+ mu_opool_append_char (meta1_pool, (char) strtoul (text + len, NULL, 16));
+}
+
+void
+meta1_line_begin ()
+{
+ if (!meta1_pool)
+ mu_opool_create (&meta1_pool, 1);
+ else
+ mu_opool_clear (meta1_pool);
+}
+
+char *
+meta1_line_finish ()
+{
+ mu_opool_append_char (meta1_pool, 0);
+ return mu_opool_finish (meta1_pool, NULL);
+}
+
+char *
+meta1_string (const char *str, size_t len)
+{
+ meta1_line_begin ();
+ meta1_line_add (str, len);
+ return meta1_line_finish ();
+}
+
+void
+meta1_parse_error (const char *fmt, ...)
+{
+ va_list ap;
+ mu_debug_t debug;
+
+ mu_diag_get_debug (&debug);
+ mu_debug_printf (debug, 0, "%s:%lu: ", meta1_locus.file,
+ (unsigned long) meta1_locus.line);
+ va_start (ap, fmt);
+ mu_debug_vprintf (debug, 0, fmt, ap);
+ mu_debug_printf (debug, 0, "\n");
+ va_end (ap);
+ meta1_error_count++;
+}
+
+void
+meta1_lexer_set_debug ()
+{
+ mu_log_level_t lev = mu_global_debug_level ("meta1");
+ yy_flex_debug = (lev & MU_DEBUG_LEVEL_MASK (MU_DEBUG_TRACE2));
+}
+
+static int
+_cfg_default_printer (void *unused, mu_log_level_t level, const char *str)
+{
+ fprintf (stderr, "%s", str);
+ return 0;
+}
+
+mu_cfg_tree_t *meta1_parse_tree;
+
+/* Parse MeTA1 configuration file `name'. Populate `meta1_parse_tree' with
+ the parse tree. */
+int
+meta1_config_parse (const char *name)
+{
+ int rc;
+ FILE *fp;
+
+ fp = fopen (name, "r");
+ if (!fp)
+ {
+ mu_error (_("%s: cannot open file: %s"), name, mu_strerror (errno));
+ return 1;
+ }
+ meta1_locus.file = meta1_string (name, strlen (name));
+ meta1_locus.line = 1;
+ meta1_lexer_set_debug ();
+ meta1_parser_set_debug ();
+
+ yyrestart (fp);
+ rc = meta1parse ();
+ fclose (fp);
+ if (meta1_error_count)
+ rc = 1;
+ if (rc == 0)
+ {
+ meta1_parse_tree = mu_alloc (sizeof (*meta1_parse_tree));
+ mu_debug_create (&meta1_parse_tree->debug, NULL);
+ mu_debug_set_print (meta1_parse_tree->debug, _cfg_default_printer, NULL);
+ mu_debug_set_level (meta1_parse_tree->debug,
+ mu_global_debug_level ("meta1"));
+ meta1_parse_tree->node = meta1_parse_head;
+ meta1_parse_tree->pool = meta1_pool;
+ }
+ return rc;
+}
+
+
+
+
diff --git a/pies/pies.c b/pies/pies.c
index 9fc7a81..7d70ebd 100644
--- a/pies/pies.c
+++ b/pies/pies.c
@@ -15,6 +15,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "pies.h"
+#include "meta1lex.h"
int log_to_stderr; /* Use stderr for logging */
char *log_tag; /* override mu_log_tag */
@@ -385,12 +386,14 @@ _cb_command (mu_debug_t debug, void *data, mu_config_value_t *val)
*pargv = argv;
return 0;
}
-
+
static int
_cb_depend (mu_debug_t debug, void *data, mu_config_value_t *val)
{
char ***pargv = data;
char **argv;
+ size_t count;
+ mu_iterator_t itr;
switch (val->type)
{
@@ -405,8 +408,23 @@ _cb_depend (mu_debug_t debug, void *data, mu_config_value_t *val)
break;
case MU_CFG_LIST:
- mu_cfg_format_error (debug, MU_DEBUG_ERROR, _("unexpected list"));
- return 1;
+ mu_list_count (val->v.list, &count);
+ if (mu_list_get_iterator (val->v.list, &itr))
+ return 1;
+
+ argv = xcalloc (count + 1, sizeof (argv[0]));
+
+ for (mu_iterator_first (itr), count = 0;
+ !mu_iterator_is_done (itr); mu_iterator_next (itr), count++)
+ {
+ mu_config_value_t *p;
+ mu_iterator_current (itr, (void**)&p);
+ if (mu_cfg_assert_value_type (p, MU_CFG_STRING, debug))
+ return 1;
+ argv[count] = xstrdup (p->v.string);
+ }
+ mu_iterator_destroy (&itr);
+ break;
}
*pargv = argv;
return 0;
@@ -578,6 +596,9 @@ struct mu_cfg_param component_cfg_param[] = {
translate them. */
N_("mode: {exec | wait | accept | inetd | nostartaccept | pass-fd | pass}")
},
+ { "program", mu_cfg_string, NULL,
+ mu_offsetof (struct component, program), NULL,
+ N_("Full name of the program.") },
{ "command", mu_cfg_callback, NULL,
mu_offsetof (struct component, argv), _cb_command,
N_("Command line.") },
@@ -769,6 +790,17 @@ _cb_debug (mu_debug_t debug, void *data, mu_config_value_t *arg)
return 0;
}
+static int
+_cm_include_meta1 (mu_debug_t debug, void *data, mu_config_value_t *arg)
+{
+ int rc;
+
+ if (mu_cfg_assert_value_type (arg, MU_CFG_STRING, debug))
+ return 1;
+ meta1_config_parse (arg->v.string);
+ return 0;
+}
+
struct mu_cfg_param pies_cfg_param[] = {
{ "component", mu_cfg_section },
{ "debug", mu_cfg_callback, NULL, 0, _cb_debug,
@@ -794,6 +826,11 @@ struct mu_cfg_param pies_cfg_param[] = {
{ "return-code", mu_cfg_section, &default_component },
{ "acl", mu_cfg_section, &pies_acl, 0, NULL,
N_("Global access control list") },
+ { "include-meta1", mu_cfg_callback, NULL, 0, _cm_include_meta1,
+ N_("Include components from the specified MeTA1 configuration file."),
+ N_("file: string") },
+ { "meta1-queue-dir", mu_cfg_string, &meta1_queue_dir, 0, NULL,
+ N_("Set name of MeTA1 queue directory (default /var/spool/meta1).") },
{ NULL }
};
@@ -1204,6 +1241,27 @@ pies_stop ()
}
+static int
+parse_meta1_conf ()
+{
+ int flags = 0;
+
+ if (mu_cfg_parser_verbose)
+ flags |= MU_PARSE_CONFIG_VERBOSE;
+ if (mu_cfg_parser_verbose > 1)
+ flags |= MU_PARSE_CONFIG_DUMP;
+ return mu_cfg_tree_reduce (meta1_parse_tree, mu_program_name, pies_cfg_param,
+ flags, NULL);
+}
+
+static int
+pies_cfg_verifier ()
+{
+ int rc = parse_meta1_conf ();
+ rc += progman_build_depmap ();
+ return rc;
+}
+
int
main (int argc, char **argv)
{
@@ -1219,9 +1277,12 @@ main (int argc, char **argv)
mu_acl_cfg_init ();
return_code_cfg_init ();
component_cfg_init ();
+ mu_app_cfg_verifier = pies_cfg_verifier;
mu_argp_init (program_version, package_bugreport);
mu_register_all_mailer_formats ();
rc = mu_app_init (&argp, capa, pies_cfg_param, argc, argv, 0, &index, NULL);
+ if (rc == 0)
+ rc = parse_meta1_conf ();
if (rc)
exit (EX_CONFIG);
diff --git a/pies/pies.h b/pies/pies.h
index 4930de4..db0f4c7 100644
--- a/pies/pies.h
+++ b/pies/pies.h
@@ -102,6 +102,7 @@ struct component
{
enum pies_comp_mode mode;
char *tag; /* Entry tag (for diagnostics purposes) */
+ char *program; /* Program name */
char **argv; /* Program command line */
char **env; /* Program environment */
char *dir; /* Working directory */
@@ -140,6 +141,7 @@ void progman_stop_component (const char *name);
void progman_dump_stats (const char *filename);
int progman_accept (int socket);
int progman_build_depmap (void);
+struct component *progman_lookup_component (const char *tag);
void log_setup (int want_stderr);
void signal_setup (RETSIGTYPE (*sf)(int));
diff --git a/pies/progman.c b/pies/progman.c
index c93ed9c..8ed9733 100644
--- a/pies/progman.c
+++ b/pies/progman.c
@@ -95,7 +95,17 @@ prog_lookup_by_tag (const char *tag)
break;
return prog;
}
-
+
+struct component *
+progman_lookup_component (const char *tag)
+{
+ struct prog *prog;
+ for (prog = proghead; prog; prog = prog->next)
+ if (IS_PROG (prog) && strcmp (prog->tag, tag) == 0)
+ return prog->v.p.comp;
+ return NULL;
+}
+
struct prog *
prog_lookup_by_idx (unsigned idx)
{
@@ -692,7 +702,9 @@ prog_start (struct prog *prog)
close (i);
}
- execvp (prog->v.p.comp->argv[0], prog->v.p.comp->argv);
+ execvp (prog->v.p.comp->program ?
+ prog->v.p.comp->program : prog->v.p.comp->argv[0],
+ prog->v.p.comp->argv);
openlog (MU_LOG_TAG (), LOG_PID, mu_log_facility);
syslog (LOG_CRIT, _("cannot start `%s': %s"), prog->tag,
mu_strerror (errno));

Return to:

Send suggestions and report system problems to the System administrator.