diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2008-11-12 14:45:00 +0000 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2008-11-12 14:45:00 +0000 |
commit | f2104f12be8f330f4a6f8164a3698fb06053e1ad (patch) | |
tree | 59db3d2d50bf67c29e9c1ab989a65422bedbd215 /pies | |
parent | 0af7127c5084ffc3550de8d98e00582975eb6113 (diff) | |
download | pies-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.am | 13 | ||||
-rw-r--r-- | pies/meta1gram.y | 405 | ||||
-rw-r--r-- | pies/meta1lex.h | 31 | ||||
-rw-r--r-- | pies/meta1lex.l | 231 | ||||
-rw-r--r-- | pies/pies.c | 67 | ||||
-rw-r--r-- | pies/pies.h | 2 | ||||
-rw-r--r-- | pies/progman.c | 16 |
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)); |