summaryrefslogtreecommitdiff
path: root/mh/mh_alias_gram.y
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2017-06-13 14:44:58 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2017-06-13 15:03:55 +0300
commitfa5d4812fc4936dd470ded17116c9d966d0d645e (patch)
treef0efda476ed06795f3de233c440e4e8d87f2b60a /mh/mh_alias_gram.y
parent3a78309aa59c245c14e29d3e7eb953c6a2ea1035 (diff)
downloadmailutils-fa5d4812fc4936dd470ded17116c9d966d0d645e.tar.gz
mailutils-fa5d4812fc4936dd470ded17116c9d966d0d645e.tar.bz2
Rewrite Makefile rules for lex and bison
The aim is to get rid of the explicit rules and use the Autmake framework as much as possible, without hurting the flexibility. To this effect, the gylwrap tool is rewritten from scratch (in Perl). In compatibility mode it takes the same arguments as the standard ylwrap. Additional configuration is supplied in the configuration file gylwrap.conf, located in the directory where the input file resides. * mu-aux/gylwrap: Rewrite from scratch. * configure.ac (MU_YLWRAP): New subst variable. * libmailutils/base/.gitignore: Update. * libmailutils/base/Makefile.am: Update. * libmailutils/base/gylwrap.conf: New file. * libmailutils/cfg/.gitignore: Update. * libmailutils/cfg/Makefile.am: Use new YLWRAP * libmailutils/cfg/cfg.h: Remove. * libmailutils/cfg/gylwrap.conf: New file. * libmailutils/cfg/lexer.l: Include mailutils/yyloc.h directly. * libmailutils/cfg/parser.y: Likewise. * libmu_sieve/Makefile.am: Use new YLWRAP * libmu_sieve/gylwrap.conf: New file. * libmu_sieve/sieve.y: Rename to libmu_sieve/sieve-gram.y * libmu_sieve/sieve.l: Rename to libmu_sieve/sieve-lex.l * mail/Makefile.am: Use new YLWRAP * mh/.gitignore: Update. * mh/Makefile.am: Use new YLWRAP * mh/gylwrap.conf: New file. * mh/mh_alias.y: Rename to mh/mh_alias_gram.y * mh/mh_alias.l: Rename to mh/mh_alias_lex.l * mh/pick.y: Rename to mh/pick-gram.y * mimeview/.gitignore: Update. * mimeview/Makefile.am: Use new YLWRAP * mimeview/mimetypes.y: Rename to mimeview/grammar.y * mimeview/gylwrap.conf: New file. * mimeview/mimetypes.l: Rename to mimeview/lexer.l * po/POTFILES.in: Update
Diffstat (limited to 'mh/mh_alias_gram.y')
-rw-r--r--mh/mh_alias_gram.y516
1 files changed, 516 insertions, 0 deletions
diff --git a/mh/mh_alias_gram.y b/mh/mh_alias_gram.y
new file mode 100644
index 000000000..0d6bffcc2
--- /dev/null
+++ b/mh/mh_alias_gram.y
@@ -0,0 +1,516 @@
+%{
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 2003-2007, 2010-2012, 2014-2017 Free Software
+ Foundation, Inc.
+
+ GNU Mailutils is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GNU Mailutils is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <mh.h>
+#include <pwd.h>
+#include <grp.h>
+#include <sys/types.h>
+
+struct mh_alias
+{
+ char *name;
+ mu_list_t rcpt_list;
+ int inclusive;
+};
+
+static mu_list_t alias_list;
+
+static mu_list_t
+list_create_or_die ()
+{
+ int status;
+ mu_list_t list;
+
+ status = mu_list_create (&list);
+ if (status)
+ {
+ ali_parse_error (_("can't create list: %s"), mu_strerror (status));
+ exit (1);
+ }
+ return list;
+}
+
+static char *
+ali_list_to_string (mu_list_t *plist)
+{
+ size_t n;
+ char *string;
+
+ mu_list_count (*plist, &n);
+ if (n == 1)
+ {
+ mu_list_get (*plist, 0, (void **)&string);
+ }
+ else
+ {
+ char *p;
+ size_t length = 0;
+ mu_iterator_t itr;
+ mu_list_get_iterator (*plist, &itr);
+ for (mu_iterator_first (itr); !mu_iterator_is_done (itr); mu_iterator_next(itr))
+ {
+ char *s;
+ mu_iterator_current (itr, (void**) &s);
+ length += strlen (s) + 1;
+ }
+
+ string = mu_alloc (length + 1);
+ p = string;
+ for (mu_iterator_first (itr); !mu_iterator_is_done (itr); mu_iterator_next(itr))
+ {
+ char *s;
+ mu_iterator_current (itr, (void**) &s);
+ strcpy (p, s);
+ p += strlen (s);
+ *p++ = ' ';
+ }
+ *--p = 0;
+ mu_iterator_destroy (&itr);
+ }
+ mu_list_destroy (plist);
+ return string;
+}
+
+static mu_list_t unix_group_to_list (char *name);
+static mu_list_t unix_gid_to_list (char *name);
+static mu_list_t unix_passwd_to_list (void);
+
+int yyerror (char *s);
+int yylex (void);
+
+%}
+
+%union {
+ char *string;
+ mu_list_t list;
+ struct mh_alias *alias;
+}
+
+%token <string> STRING
+%type <list> address_list address_group string_list
+%type <string> address
+%type <alias> alias
+
+%%
+
+input : /* empty */
+ | alias_list
+ | alias_list nl
+ | nl alias_list
+ | nl alias_list nl
+ ;
+
+alias_list : alias
+ {
+ if (!alias_list)
+ alias_list = list_create_or_die ();
+ mu_list_append (alias_list, $1);
+ }
+ | alias_list nl alias
+ {
+ mu_list_append (alias_list, $3);
+ }
+ ;
+
+nl : '\n'
+ | nl '\n'
+ ;
+
+alias : STRING ':' { ali_verbatim (1); } address_group
+ {
+ ali_verbatim (0);
+ $$ = mu_alloc (sizeof (*$$));
+ $$->name = $1;
+ $$->rcpt_list = $4;
+ $$->inclusive = 0;
+ }
+ | STRING ';' { ali_verbatim (1); } address_group
+ {
+ ali_verbatim (0);
+ $$ = mu_alloc (sizeof (*$$));
+ $$->name = $1;
+ $$->rcpt_list = $4;
+ $$->inclusive = 1;
+ }
+ ;
+
+address_group: address_list
+ | '=' STRING
+ {
+ $$ = unix_group_to_list ($2);
+ free ($2);
+ }
+ | '+' STRING
+ {
+ $$ = unix_gid_to_list ($2);
+ free ($2);
+ }
+ | '*'
+ {
+ $$ = unix_passwd_to_list ();
+ }
+ ;
+
+address_list : address
+ {
+ $$ = list_create_or_die ();
+ mu_list_append ($$, $1);
+ }
+ | address_list ',' address
+ {
+ mu_list_append ($1, $3);
+ $$ = $1;
+ }
+ ;
+
+address : string_list
+ {
+ $$ = ali_list_to_string (&$1);
+ }
+ ;
+
+string_list : STRING
+ {
+ mu_list_create(&$$);
+ mu_list_append($$, $1);
+ }
+ | string_list STRING
+ {
+ mu_list_append($1, $2);
+ $$ = $1;
+ }
+ ;
+
+%%
+
+static mu_list_t
+ali_list_dup (mu_list_t src)
+{
+ mu_list_t dst;
+ mu_iterator_t itr;
+
+ if (mu_list_create (&dst))
+ return NULL;
+
+ if (mu_list_get_iterator (src, &itr))
+ {
+ mu_list_destroy (&dst);
+ return NULL;
+ }
+
+ for (mu_iterator_first (itr); !mu_iterator_is_done (itr); mu_iterator_next (itr))
+ {
+ void *data;
+ mu_iterator_current (itr, (void **)&data);
+ mu_list_append (dst, data);
+ }
+ mu_iterator_destroy (&itr);
+ return dst;
+}
+
+static int
+ali_member (mu_list_t list, const char *name)
+{
+ mu_iterator_t itr;
+ int found = 0;
+
+ if (mu_list_get_iterator (list, &itr))
+ return 0;
+ for (mu_iterator_first (itr); !found && !mu_iterator_is_done (itr);
+ mu_iterator_next (itr))
+ {
+ char *item;
+ mu_address_t tmp;
+
+ mu_iterator_current (itr, (void **)&item);
+ if (strcmp (item, name) == 0)
+ found = 1;
+ else if (mu_address_create (&tmp, item) == 0)
+ {
+ found = mu_address_contains_email (tmp, name);
+ mu_address_destroy (&tmp);
+ }
+ }
+ mu_iterator_destroy (&itr);
+ return found;
+}
+
+int
+aliascmp (const char *pattern, const char *name)
+{
+ int len = strlen (pattern);
+
+ if (len > 1 && pattern[len - 1] == '*')
+ return strncmp (pattern, name, len - 2);
+ return strcmp (pattern, name);
+}
+
+static int mh_alias_get_internal (const char *name, mu_iterator_t start,
+ mu_list_t *return_list, int *inclusive);
+
+int
+alias_expand_list (mu_list_t name_list, mu_iterator_t orig_itr, int *inclusive)
+{
+ mu_iterator_t itr;
+
+ if (mu_list_get_iterator (name_list, &itr))
+ return 1;
+ for (mu_iterator_first (itr); !mu_iterator_is_done (itr); mu_iterator_next (itr))
+ {
+ char *name;
+ mu_list_t exlist;
+
+ mu_iterator_current (itr, (void **)&name);
+ if (mh_alias_get_internal (name, orig_itr, &exlist, inclusive) == 0)
+ {
+ /* Insert exlist after name */
+ mu_iterator_ctl (itr, mu_itrctl_insert_list, exlist);
+ mu_list_destroy (&exlist);
+ /* Remove name */
+ mu_iterator_ctl (itr, mu_itrctl_delete, NULL);
+ }
+ }
+ mu_iterator_destroy (&itr);
+ return 0;
+}
+
+/* Look up the named alias. If found, return the list of recipient
+ names associated with it */
+static int
+mh_alias_get_internal (const char *name,
+ mu_iterator_t start, mu_list_t *return_list,
+ int *inclusive)
+{
+ mu_iterator_t itr;
+ int rc = 1;
+
+ if (!start)
+ {
+ if (mu_list_get_iterator (alias_list, &itr))
+ return 1;
+ mu_iterator_first (itr);
+ }
+ else
+ {
+ mu_iterator_dup (&itr, start);
+ mu_iterator_next (itr);
+ }
+
+ for (; !mu_iterator_is_done (itr); mu_iterator_next (itr))
+ {
+ struct mh_alias *alias;
+ mu_iterator_current (itr, (void **)&alias);
+ if (aliascmp (alias->name, name) == 0)
+ {
+ if (inclusive)
+ *inclusive |= alias->inclusive;
+ *return_list = ali_list_dup (alias->rcpt_list);
+ alias_expand_list (*return_list, itr, inclusive);
+ rc = 0;
+ break;
+ }
+ }
+
+ mu_iterator_destroy (&itr);
+ return rc;
+}
+
+int
+mh_alias_get (const char *name, mu_list_t *return_list)
+{
+ return mh_alias_get_internal (name, NULL, return_list, NULL);
+}
+
+int
+mh_alias_get_address (const char *name, mu_address_t *paddr, int *incl)
+{
+ mu_iterator_t itr;
+ mu_list_t list;
+
+ if (incl)
+ *incl = 0;
+ if (mh_alias_get_internal (name, NULL, &list, incl))
+ return 1;
+ if (mu_list_is_empty (list))
+ {
+ mu_list_destroy (&list);
+ return 1;
+ }
+
+ if (mu_list_get_iterator (list, &itr) == 0)
+ {
+ for (mu_iterator_first (itr); !mu_iterator_is_done (itr); mu_iterator_next (itr))
+ {
+ char *item;
+ mu_address_t a;
+ char *ptr = NULL;
+
+ mu_iterator_current (itr, (void **)&item);
+ if (mu_address_create (&a, item))
+ {
+ mu_error (_("Error expanding aliases -- invalid address `%s'"),
+ item);
+ }
+ else
+ {
+ if (incl && *incl)
+ mu_address_set_personal (a, 1, name);
+ mu_address_union (paddr, a);
+ mu_address_destroy (&a);
+ }
+ if (ptr)
+ free (ptr);
+ }
+ mu_iterator_destroy (&itr);
+ }
+ mu_list_destroy (&list);
+ return 0;
+}
+
+/* Look up the given user name in the aliases. Return the list of
+ alias names this user is member of */
+int
+mh_alias_get_alias (const char *uname, mu_list_t *return_list)
+{
+ mu_iterator_t itr;
+ int rc = 1;
+
+ if (mu_list_get_iterator (alias_list, &itr))
+ return 1;
+ for (mu_iterator_first (itr); !mu_iterator_is_done (itr); mu_iterator_next (itr))
+ {
+ struct mh_alias *alias;
+ mu_iterator_current (itr, (void **)&alias);
+ if (ali_member (alias->rcpt_list, uname))
+ {
+ if (*return_list == NULL && mu_list_create (return_list))
+ break;
+ mu_list_append (*return_list, alias->name);
+ rc = 0;
+ }
+ }
+
+ mu_iterator_destroy (&itr);
+ return rc;
+}
+
+void
+mh_alias_enumerate (mh_alias_enumerator_t fun, void *data)
+{
+ mu_iterator_t itr;
+ int rc = 0;
+
+ if (mu_list_get_iterator (alias_list, &itr))
+ return ;
+ for (mu_iterator_first (itr);
+ rc == 0 && !mu_iterator_is_done (itr);
+ mu_iterator_next (itr))
+ {
+ struct mh_alias *alias;
+ mu_list_t tmp;
+
+ mu_iterator_current (itr, (void **)&alias);
+
+ tmp = ali_list_dup (alias->rcpt_list);
+ alias_expand_list (tmp, itr, NULL);
+
+ rc = fun (alias->name, tmp, data);
+ mu_list_destroy (&tmp);
+ }
+ mu_iterator_destroy (&itr);
+}
+
+static mu_list_t
+unix_group_to_list (char *name)
+{
+ struct group *grp = getgrnam (name);
+ mu_list_t lst = list_create_or_die ();
+
+ if (grp)
+ {
+ char **p;
+
+ for (p = grp->gr_mem; *p; p++)
+ mu_list_append (lst, mu_strdup (*p));
+ }
+
+ return lst;
+}
+
+static mu_list_t
+unix_gid_to_list (char *name)
+{
+ struct group *grp = getgrnam (name);
+ mu_list_t lst = list_create_or_die ();
+
+ if (grp)
+ {
+ struct passwd *pw;
+ setpwent();
+ while ((pw = getpwent ()))
+ {
+ if (pw->pw_gid == grp->gr_gid)
+ mu_list_append (lst, mu_strdup (pw->pw_name));
+ }
+ endpwent();
+ }
+ return lst;
+}
+
+static mu_list_t
+unix_passwd_to_list ()
+{
+ mu_list_t lst = list_create_or_die ();
+ struct passwd *pw;
+
+ setpwent();
+ while ((pw = getpwent ()))
+ {
+ if (pw->pw_uid > 200)
+ mu_list_append (lst, mu_strdup (pw->pw_name));
+ }
+ endpwent();
+ return lst;
+}
+
+int
+mh_read_aliases ()
+{
+ const char *p;
+
+ p = mh_global_profile_get ("Aliasfile", NULL);
+ if (p)
+ {
+ struct mu_wordsplit ws;
+
+ if (mu_wordsplit (p, &ws, MU_WRDSF_DEFFLAGS))
+ {
+ mu_error (_("cannot split line `%s': %s"), p,
+ mu_wordsplit_strerror (&ws));
+ }
+ else
+ {
+ size_t i;
+ for (i = 0; i < ws.ws_wordc; i++)
+ mh_alias_read (ws.ws_wordv[i], 1);
+ mu_wordsplit_free (&ws);
+ }
+ }
+ mh_alias_read (DEFAULT_ALIAS_FILE, 0);
+ return 0;
+}

Return to:

Send suggestions and report system problems to the System administrator.