From 61cc2fe261b24ec3a5f2a21d76fd331711cb84f4 Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Sat, 9 Jan 2016 13:54:55 +0200 Subject: Use grecs meta1 parser * configure.ac (GRECS_SETUP): Require parser-meta1 * grecs: Upgrade. * po/POTFILES.in: Update. * src/Makefile.am: Remove meta1gram.y and meta1lex.l Add meta1parse.c and meta1parse.h * src/meta1gram.y: Remove. * src/meta1lex.l: Remove. * src/meta1parse.c: New file. * src/meta1parse.h: New file. * src/pies.c: Include meta1parse.h instead of meta1lex.h --- configure.ac | 2 +- grecs | 2 +- po/POTFILES.in | 5 +- src/Makefile.am | 11 +- src/meta1gram.y | 406 ------------------------------------------------------- src/meta1lex.l | 232 ------------------------------- src/meta1parse.c | 360 ++++++++++++++++++++++++++++++++++++++++++++++++ src/meta1parse.h | 3 + src/pies.c | 2 +- 9 files changed, 371 insertions(+), 652 deletions(-) delete mode 100644 src/meta1gram.y delete mode 100644 src/meta1lex.l create mode 100644 src/meta1parse.c create mode 100644 src/meta1parse.h diff --git a/configure.ac b/configure.ac index 114fc07..b99f6f5 100644 --- a/configure.ac +++ b/configure.ac @@ -72,7 +72,7 @@ AC_CHECK_FUNCS([alarm dup2 gethostbyname memmove memset select setenv socket str gl_INIT # Grecs -GRECS_SETUP([grecs],[tests git2chg getopt json sockaddr-list]) +GRECS_SETUP([grecs],[tests git2chg getopt json sockaddr-list parser-meta1]) GRECS_HOST_PROJECT_INCLUDES='-I$(top_srcdir)/gnu -I$(top_builddir)/gnu' # Test for setproctitle diff --git a/grecs b/grecs index 3df291f..ca94270 160000 --- a/grecs +++ b/grecs @@ -1 +1 @@ -Subproject commit 3df291f812208a8ce07a2878784a0a73e4587193 +Subproject commit ca94270a5e30add9b364d32220fb38d457ebd3f2 diff --git a/po/POTFILES.in b/po/POTFILES.in index acc6127..6e62a76 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -17,12 +17,13 @@ src/acl.c lib/addrfmt.c +src/ctl.c src/depmap.c src/diag.c src/limits.c -src/meta1gram.y -src/meta1lex.l +src/meta1parse.c src/pies.c +src/piesctl.c src/progman.c src/socket.c lib/url.c diff --git a/src/Makefile.am b/src/Makefile.am index a2400fb..3f29b4e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -25,8 +25,7 @@ pies_SOURCES = \ inetd.c\ inetd-bi.c\ limits.c\ - meta1gram.y\ - meta1lex.l\ + meta1parse.c\ pies.c\ progman.c\ socket.c\ @@ -38,14 +37,11 @@ pies_SOURCES = \ noinst_HEADERS = \ acl.h\ cmdline.h\ - meta1gram.h\ - meta1lex.h\ + meta1parse.h\ pies.h\ prog.h\ piesctl-cl.h -meta1lex.c: meta1gram.h - BUILT_SOURCES=cmdline.h piesctl-cl.h incdir=$(pkgdatadir)/$(VERSION)/include @@ -89,9 +85,6 @@ AM_CPPFLAGS=\ -DDEFAULT_PIES_CONTROL_URL='"$(DEFAULT_PIES_CONTROL_URL)"'\ -DDEFAULT_INIT_CONTROL_URL='"$(DEFAULT_INIT_CONTROL_URL)"' -AM_YFLAGS=-dvt -pmeta1 -AM_LFLAGS=-dvp -Pmeta1 -olex.yy.c - EXTRA_SCRIPTS = inetd sbin_SCRIPTS = @INETD@ diff --git a/src/meta1gram.y b/src/meta1gram.y deleted file mode 100644 index 3e19a12..0000000 --- a/src/meta1gram.y +++ /dev/null @@ -1,406 +0,0 @@ -%{ -/* MeTA1 configuration parser for GNU Pies. - Copyright (C) 2008, 2009, 2010, 2011, 2013 Sergey Poznyakoff - - GNU Pies is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. - - GNU Pies is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNU Pies. If not, see . */ - -/* 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 "grecs-locus.h" -#include "meta1lex.h" -#include "meta1gram.h" - -#define META1_QUEUE_DIR() \ - (meta1_queue_dir ? meta1_queue_dir : "/var/spool/meta1") - -enum meta1_stmt_type -{ - meta1_simple, - meta1_block -}; - -struct meta1_stmt -{ - struct meta1_stmt *next; - grecs_locus_t locus; - enum meta1_stmt_type type; - const char *ident; - union - { - grecs_value_t *value; - struct meta1_stmt *list; - } v; -}; - -struct meta1_stmt * -meta1_stmt_create (enum meta1_stmt_type type, const char *ident) -{ - struct meta1_stmt *p = grecs_malloc (sizeof (*p)); - p->next = NULL; - p->type = type; - p->ident = ident; - p->locus = meta1lloc; - return p; -} - -static struct meta1_stmt * -_reverse (struct meta1_stmt *list, struct meta1_stmt **root) -{ - struct meta1_stmt *next; - - if (list->next == NULL) - { - *root = list; - return list; - } - next = _reverse (list->next, root); - next->next = list; - list->next = NULL; - return list; -} - -static struct meta1_stmt * -reverse (struct meta1_stmt *in) -{ - struct meta1_stmt *root; - if (!in) - return in; - _reverse (in, &root); - return root; -} - -static void meta1_translate (struct meta1_stmt *); -%} - -%error-verbose -%locations - -%union { - char *string; - struct grecs_list *list; - grecs_value_t *value; - struct meta1_stmt *stmt; -} - -%token META1_IDENT META1_STRING META1_NUMBER -%type slist values list -%type value -%type string ident tag -%type stmtlist stmt simple block -%% - -input : stmtlist - { - struct meta1_stmt *stmt; - for (stmt = $1; stmt; stmt = stmt->next) - meta1_translate (stmt); - } - ; - -stmtlist: stmt - { - $$ = $1; - } - | stmtlist stmt - { - $2->next = $1; - $$ = $2; - } - ; - -stmt : simple - | block - ; - -simple : ident '=' value opt_sc - { - $$ = meta1_stmt_create (meta1_simple, $1); - $$->v.value = $3; - } - ; - -block : ident tag '{' stmtlist '}' opt_sc - { - $$ = meta1_stmt_create (meta1_block, $2 ? $2 : $1); - $$->v.list = reverse ($4); - } - ; - -tag : /* empty */ - { - $$ = NULL; - } - | META1_IDENT - ; - -ident : META1_IDENT - ; - -value : string - { - $$ = grecs_malloc (sizeof (*$$)); - $$->type = GRECS_TYPE_STRING; - $$->v.string = $1; - } - | list - { - $$ = grecs_malloc (sizeof (*$$)); - $$->type = GRECS_TYPE_LIST; - $$->v.list = $1; - } - | META1_NUMBER - { - $$ = grecs_malloc (sizeof (*$$)); - $$->type = GRECS_TYPE_STRING; - $$->v.string = $1; - } - ; - -string : META1_IDENT - | slist - { - struct grecs_list_entry *ep; - meta1_line_begin (); - for (ep = $1->head; ep; ep = ep->next) - { - const char *p = ep->data; - meta1_line_add (p, strlen (p)); - } - $$ = meta1_line_finish (); - } - ; - -slist : META1_STRING - { - $$ = grecs_list_create (); - grecs_list_append ($$, $1); - } - | slist META1_STRING - { - grecs_list_append ($1, $2); - $$ = $1; - } - ; - -list : '{' values '}' - { - $$ = $2; - } - | '{' values ',' '}' - { - $$ = $2; - } - ; - -values : value - { - $$ = grecs_list_create (); - grecs_list_append ($$, $1); - } - | values ',' value - { - grecs_list_append ($1, $3); - $$ = $1; - } - ; - -opt_sc : /* empty */ - | ';' - ; - -%% -int -yyerror (char const *s) -{ - grecs_error (&yylloc, 0, "%s", s); - return 0; -} - -void -meta1_parser_set_debug () -{ - char *p = getenv ("META1_DEBUG_YACC"); - yydebug = p && (*p - '0') > 0; -} - -static struct meta1_stmt * -find_stmt (struct meta1_stmt *stmt, const char *ident) -{ - for (; stmt; stmt = stmt->next) - if (strcmp (stmt->ident, ident) == 0) - break; - return stmt; -} - - -struct node_trans -{ - char *name; - char *new_name; - int (*xlat) (struct meta1_stmt *stmt, struct component *comp); -}; - -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 int -xlat_listen_socket (struct meta1_stmt *stmt, struct component *comp) -{ - struct meta1_stmt *p; - grecs_value_t *val; - - p = find_stmt (stmt->v.list, "type"); - if (!p || !p->v.value || p->v.value->type != GRECS_TYPE_STRING) - return 1; - meta1_line_begin (); - meta1_line_add (p->v.value->v.string, strlen (p->v.value->v.string)); - meta1_line_add ("://", 3); - if (strcmp (p->v.value->v.string, "inet") == 0) - { - const char *addr; - p = find_stmt (stmt->v.list, "address"); - if (p) - { - if (p->v.value->type != GRECS_TYPE_STRING) - return 1; - addr = p->v.value->v.string; - } - else - addr = "0.0.0.0"; - meta1_line_add (addr, strlen (addr)); - meta1_line_add (":", 1); - p = find_stmt (stmt->v.list, "port"); - if (p->v.value->type != GRECS_TYPE_STRING) - return 1; - meta1_line_add (p->v.value->v.string, strlen (p->v.value->v.string)); - } - else if (strcmp (p->v.value->v.string, "unix") == 0) - { - /* listen_socket { - type=unix; - path = /tmp/socket; - umask = 077; - user = user; - group = group; - } - */ - p = find_stmt (stmt->v.list, "path"); - if (!p || p->v.value->type != GRECS_TYPE_STRING) - return 1; - meta1_line_add (p->v.value->v.string, strlen (p->v.value->v.string)); - - p = find_stmt (stmt->v.list, "user"); - if (p && p->v.value->type == GRECS_TYPE_STRING) - { - meta1_line_add (";user=", 6); - meta1_line_add (p->v.value->v.string, strlen (p->v.value->v.string)); - } - - p = find_stmt (stmt->v.list, "group"); - if (p && p->v.value->type == GRECS_TYPE_STRING) - { - meta1_line_add (";group=", 7); - meta1_line_add (p->v.value->v.string, strlen (p->v.value->v.string)); - } - - p = find_stmt (stmt->v.list, "umask"); - if (p && p->v.value->type == GRECS_TYPE_STRING) - { - meta1_line_add (";umask=", 7); - meta1_line_add (p->v.value->v.string, strlen (p->v.value->v.string)); - } - } - val = grecs_malloc (sizeof (*val)); - val->type = GRECS_TYPE_STRING; - val->v.string = meta1_line_finish (); - stmt->type = meta1_simple; - stmt->v.value = val; - return 0; -} - -static int -xlat_start_action (struct meta1_stmt *stmt, struct component *comp) -{ - if (strcmp (stmt->v.value->v.string, "wait") == 0) - { - meta1_line_begin (); - meta1_line_add ("exec", 4); - stmt->v.value->v.string = meta1_line_finish (); - } - return 0; -} - -static struct node_trans root_node_trans[] = { - { "listen_socket", "socket", xlat_listen_socket }, - { "start_action", "mode", xlat_start_action }, - { "pass_fd_socket", "pass-fd-socket" }, - { "user", "user" }, - { "path", "program" }, - { "arguments", "command" }, - { "restart_dependencies", "dependents", }, - { NULL } -}; - -static void -meta1_translate_stmt (struct meta1_stmt *stmt, struct component *comp) -{ - struct grecs_keyword *kwp; - - struct node_trans *nt = find_node_trans (root_node_trans, stmt->ident); - if (!nt) - return; - - kwp = find_component_keyword (nt->new_name); - if (!kwp) - abort (); - - if (nt->xlat && nt->xlat (stmt, comp)) - return; - - grecs_process_ident (kwp, stmt->v.value, comp, &stmt->locus); -} - -static void -meta1_translate (struct meta1_stmt *stmt) -{ - struct component *comp; - struct meta1_stmt *p; - size_t len; - - if (stmt->type != meta1_block) - return; - - comp = component_create (stmt->ident); - for (p = stmt->v.list; p; p = p->next) - { - meta1_translate_stmt (p, comp); - } - comp->privs.allgroups = 1; - comp->dir = META1_QUEUE_DIR (); - comp->redir[RETR_ERR].type = redir_file; - comp->redir[RETR_ERR].v.file = NULL; - len = 0; - grecs_asprintf (&comp->redir[RETR_ERR].v.file, &len, - "%s/%s.log", META1_QUEUE_DIR (), comp->tag); - component_finish (comp, &stmt->locus); -} diff --git a/src/meta1lex.l b/src/meta1lex.l deleted file mode 100644 index a074a8d..0000000 --- a/src/meta1lex.l +++ /dev/null @@ -1,232 +0,0 @@ -/* MeTA1 configuration lexer for GNU Pies. -*- c -*- */ -%option nounput -%option noinput -%top { -/* MeTA1 configuration lexer for GNU Pies. - Copyright (C) 2008, 2009, 2010, 2011, 2013 Sergey Poznyakoff - - GNU Pies is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. - - GNU Pies is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNU Pies. If not, see . */ - -/* This file implements a lexical analyzer for MeTA1 main configuration file. - */ - -#ifdef HAVE_CONFIG_H -# include -#endif -} - -%{ -#include "pies.h" -#include "grecs-locus.h" -#include "meta1gram.h" -#include "meta1lex.h" - -static struct grecs_locus_point meta1_locus_point; -static struct grecs_txtacc *meta1_txtacc; -char *meta1_queue_dir; -#define yylval meta1lval - -#define YY_USER_ACTION do \ - { \ - if (YYSTATE == 0) \ - { \ - meta1lloc.beg = meta1_locus_point; \ - meta1lloc.beg.col++; \ - } \ - meta1_locus_point.col += yyleng; \ - meta1lloc.end = meta1_locus_point; \ - } \ - while (0); -%} - -%x COMMENT STR -X [0-9a-fA-F] -%% - /* C-style comments */ -"/*" BEGIN (COMMENT); -[^*\n]* /* eat anything that's not a '*' */ -"*"+[^*/\n]* /* eat up '*'s not followed by '/'s */ -\n grecs_locus_point_advance_line(meta1_locus_point); -"*"+"/" BEGIN (INITIAL); - /* End-of-line comments */ -#.*\n grecs_locus_point_advance_line(meta1_locus_point); -#.* /* 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); } -[^\\"\n]*\\x{X}{1,2} { meta1_line_add_unescape_hex (yytext, yyleng); } -[^\\"\n]*\\. { meta1_line_add_unescape_last (yytext, yyleng); } -[^\\"\n]*\" { BEGIN (INITIAL); - if (yyleng > 1) - meta1_line_add (yytext, yyleng - 1); - yylval.string = meta1_line_finish (); - return META1_STRING; } -[^\\"\n]*\n { BEGIN (INITIAL); - grecs_error (&meta1lloc, 0, _("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 grecs_locus_point_advance_line(meta1_locus_point); -[,;{}=] return yytext[0]; -. { if (isascii (yytext[0]) && isprint (yytext[0])) - grecs_error (&meta1lloc, 0, _("stray character %c"), yytext[0]); - else - grecs_error (&meta1lloc, 0, _("stray character \\%03o"), - (unsigned char) yytext[0]); } -%% - -int -yywrap () -{ - return 1; -} - -void -meta1_line_add (const char *text, size_t len) -{ - grecs_txtacc_grow (meta1_txtacc, text, len); -} - -static char quote_transtab[] = "\\\\\"\"a\ab\bf\fn\nr\rt\tv\v"; - -static int -unescape_char (int c) -{ - char *p; - - for (p = quote_transtab; *p; p += 2) - { - if (*p == c) - return p[1]; - } - return c; -} - -static void -unescape_to_line (int c) -{ - char t; - - if (c == 'v') - t = '\v'; - else - { - t = unescape_char (c); - if (t == c && t != '\\' && t != '\"') - grecs_error (&meta1lloc, 0, _("unknown escape sequence '\\%c'"), c); - } - grecs_txtacc_grow_char (meta1_txtacc, t); -} - -void -meta1_line_add_unescape_last (const char *text, size_t len) -{ - grecs_txtacc_grow (meta1_txtacc, 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--) - ; - grecs_txtacc_grow (meta1_txtacc, text, len - 2); - grecs_txtacc_grow_char (meta1_txtacc, (char) strtoul (text + len, NULL, 16)); -} - -void -meta1_line_begin () -{ - if (!meta1_txtacc) - meta1_txtacc = grecs_txtacc_create(); -} - -char * -meta1_line_finish () -{ - grecs_txtacc_grow_char (meta1_txtacc, 0); - return grecs_txtacc_finish (meta1_txtacc, 0); -} - -char * -meta1_string (const char *str, size_t len) -{ - meta1_line_begin (); - meta1_line_add (str, len); - return meta1_line_finish (); -} - -void -meta1_lexer_set_debug () -{ - char *p = getenv ("META1_DEBUG_LEX"); - yy_flex_debug = p && (*p - '0') > 0; -} - -/* 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) - { - logmsg (LOG_ERR, - _("%s: cannot open file: %s"), name, strerror (errno)); - return 1; - } - meta1_locus_point.file = meta1_string (name, strlen (name)); - meta1_locus_point.line = 1; - meta1_locus_point.col = 0; - meta1_lexer_set_debug (); - meta1_parser_set_debug (); - - yyrestart (fp); - grecs_error_count = 0; - rc = meta1parse (); - fclose (fp); - if (grecs_error_count) - rc = 1; - return rc; -} - - - - diff --git a/src/meta1parse.c b/src/meta1parse.c new file mode 100644 index 0000000..059ea54 --- /dev/null +++ b/src/meta1parse.c @@ -0,0 +1,360 @@ +/* This file is part of GNU Pies. + Copyright (C) 2016 Sergey Poznyakoff + + GNU Pies is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GNU Pies is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNU Pies. If not, see . */ + +#include "pies.h" + +char *meta1_queue_dir; + +#define META1_QUEUE_DIR() \ + (meta1_queue_dir ? meta1_queue_dir : "/var/spool/meta1") + +static void +setflag (int *flag, char const *var, int bit) +{ + char *p = getenv (var); + if (p && (*p - '0') > 0) + *flag |= bit; +} + + +static enum grecs_tree_recurse_res +freeproc (enum grecs_tree_recurse_op op, struct grecs_node *node, void *data) +{ + switch (op) + { + case grecs_tree_recurse_set: + case grecs_tree_recurse_post: + grecs_node_unlink (node); + grecs_node_free (node); + break; + case grecs_tree_recurse_pre: + /* descend into the subtree */ + break; + } + return grecs_tree_recurse_ok; +} + +int +grecs_subtree_free (struct grecs_node *node) +{ + if (!node) + return 0; + if (node->type != grecs_node_block) + { + errno = EINVAL; + return 1; + } + grecs_tree_recurse (node, freeproc, node); + return 0; +} + + +static int +xlat_start_action (struct grecs_node *node) +{ + if (node->type != grecs_node_stmt) + return -1; + if (strcmp (node->v.value->v.string, "wait") == 0) + { + node->v.value->v.string = grecs_strdup ("exec"); + } + return 0; +} + +enum substatement_status + { + substatement_success, + substatement_error, + substatement_not_found + }; + +static struct grecs_node * +simple_find_node (struct grecs_node *node, char const *name) +{ + for (node = node->down; node; node = node->next) + if (strcmp (node->ident, name) == 0) + break; + return node; +} + +static enum substatement_status +substatement_find (struct grecs_node *node, char const *name, int type, + int req, grecs_value_t **ret) +{ + struct grecs_node *np; + + np = simple_find_node (node, name); + if (!np) + { + if (req) + grecs_error (&node->locus, 0, _("no \"%s\" statement in block"), + name); + return substatement_not_found; + } + + if (node->type != grecs_node_block) + { + grecs_error (&node->locus, 0, _("unexpected scalar statement")); + return substatement_error; + } + + if (assert_grecs_value_type (&np->v.value->locus, np->v.value, type)) + return substatement_error; + + *ret = np->v.value; + + return substatement_success; +} + +static int +translate_url_param (struct grecs_node *node, char const *name, + struct grecs_txtacc *acc) +{ + struct grecs_value *np; + + switch (substatement_find (node, name, GRECS_TYPE_STRING, 0, &np)) + { + case substatement_success: + grecs_txtacc_grow_char (acc, ';'); + grecs_txtacc_grow_string (acc, name + 1); + grecs_txtacc_grow_char (acc, '='); + grecs_txtacc_grow_string (acc, np->v.string); + break; + + case substatement_not_found: + break; + + case substatement_error: + return -1; + } + return 0; +} + +static int +xlat_listen_socket_i (struct grecs_node *node, char const *type, + struct grecs_txtacc *acc) +{ + struct grecs_value *val, *vp; + char *url; + + grecs_txtacc_grow_string (acc, type); + grecs_txtacc_grow (acc, "://", 3); + + if (strcmp (type, "inet") == 0) + { + const char *addr; + + switch (substatement_find (node, "address", GRECS_TYPE_STRING, 0, &vp)) + { + case substatement_success: + addr = vp->v.string; + break; + + case substatement_not_found: + addr = "0.0.0.0"; + break; + + case substatement_error: + return -1; + } + + grecs_txtacc_grow_string (acc, addr); + grecs_txtacc_grow_char (acc, ':'); + + if (substatement_find (node, "port", GRECS_TYPE_STRING, 1, &vp) != + substatement_success) + return -1; + grecs_txtacc_grow_string (acc, vp->v.string); + } + else if (strcmp (type, "unix") == 0) + { + /* listen_socket { + type=unix; + path = /tmp/socket; + umask = 077; + user = user; + group = group; + } + */ + if (substatement_find (node, "path", GRECS_TYPE_STRING, 1, &vp) != + substatement_success) + return -1; + + grecs_txtacc_grow_string (acc, vp->v.string); + if (translate_url_param (node, "user", acc)) + return -1; + if (translate_url_param (node, "group", acc)) + return -1; + if (translate_url_param (node, "umask", acc)) + return -1; + } + else + { + grecs_error (&node->locus, 0, _("unsupported type")); + return -1; + } + + grecs_txtacc_grow_char (acc, 0); + url = grecs_txtacc_finish (acc, 1); + + val = grecs_malloc (sizeof(*val)); + val->type = GRECS_TYPE_STRING; + val->locus = node->locus; + val->v.string = url; + + grecs_subtree_free (node->down); + + node->type = grecs_node_stmt; + node->v.value = val; + return 0; +} + +static int +xlat_listen_socket (struct grecs_node *node) +{ + int rc; + struct grecs_value *val; + struct grecs_txtacc *acc; + + if (node->type != grecs_node_block) + return -1; + + if (substatement_find (node, "type", GRECS_TYPE_STRING, 1, &val) != + substatement_success) + return -1; + acc = grecs_txtacc_create (); + rc = xlat_listen_socket_i (node, val->v.string, acc); + grecs_txtacc_free (acc); + return rc; +} + + +struct meta1_translator +{ + char const *old_name; + char const *new_name; + int (*translate) (struct grecs_node *); +}; + +static struct meta1_translator transtab[] = { + { "start_action", "mode", xlat_start_action }, + { "listen_socket", "socket", xlat_listen_socket }, + { "pass_fd_socket", "pass-fd-socket" }, + { "user", "user" }, + { "path", "program" }, + { "arguments", "command" }, + { "restart_dependencies", "dependents", }, + { NULL } +}; + +static struct meta1_translator * +meta1_translator_lookup (const char *name) +{ + struct meta1_translator *p; + + for (p = transtab; p->old_name; p++) + if (strcmp (p->old_name, name) == 0) + return p; + return NULL; +} + +static int +meta1_translate_stmt (struct grecs_node *stmt, struct component *comp) +{ + struct meta1_translator *trans = meta1_translator_lookup (stmt->ident); + struct grecs_keyword *kwp; + + if (!trans) + return 0; + if (trans->translate && trans->translate (stmt)) + return -1; + if (stmt->type != grecs_node_stmt) + return -1; + + kwp = find_component_keyword (trans->new_name); + grecs_process_ident (kwp, stmt->v.value, comp, &stmt->locus); + return 0; +} + +static int +meta1_translate_node (struct grecs_node *node) +{ + struct component *comp; + struct grecs_node *stmt; + size_t len; + int err = 0; + + comp = component_create (node->ident); + for (stmt = node->down; stmt; stmt = stmt->next) + { + if (meta1_translate_stmt (stmt, comp)) + ++err; + } + if (err) + { + component_free (comp); + return -1; + } + + comp->privs.allgroups = 1; + comp->dir = META1_QUEUE_DIR (); + comp->redir[RETR_ERR].type = redir_file; + comp->redir[RETR_ERR].v.file = NULL; + len = 0; + grecs_asprintf (&comp->redir[RETR_ERR].v.file, &len, + "%s/%s.log", META1_QUEUE_DIR (), comp->tag); + component_finish (comp, &node->locus); + return 0; +} + +static int +meta1_translate_node_list (struct grecs_node *node) +{ + int err = 0; + while (node) + { + if (meta1_translate_node (node)) + ++err; + node = node->next; + } + return err; +} + +int +meta1_config_parse (const char *name) +{ + struct grecs_node *subtree; + int traceflags = 0; + int rc; + + setflag (&traceflags, "META1_DEBUG_YACC", GRECS_TRACE_GRAM); + setflag (&traceflags, "META1_DEBUG_LEX", GRECS_TRACE_LEX); + + grecs_error_count = 0; + grecs_current_locus_point.file = grecs_install_text (name); + grecs_current_locus_point.line = 1; + grecs_current_locus_point.col = 0; + subtree = grecs_meta1_parser (name, traceflags); + + if (!subtree) + return -1; + + rc = meta1_translate_node_list (subtree->down); + + grecs_node_free (subtree); + + return rc; +} diff --git a/src/meta1parse.h b/src/meta1parse.h new file mode 100644 index 0000000..6c64e6c --- /dev/null +++ b/src/meta1parse.h @@ -0,0 +1,3 @@ +extern char *meta1_queue_dir; +int meta1_config_parse (const char *name); + diff --git a/src/pies.c b/src/pies.c index 089dd17..4fcb9b3 100644 --- a/src/pies.c +++ b/src/pies.c @@ -17,7 +17,7 @@ #include "pies.h" #include #include -#include "meta1lex.h" +#include "meta1parse.h" #include "identity.h" #include "grecsasrt.h" -- cgit v1.2.1