summaryrefslogtreecommitdiff
path: root/mh/mh_alias_gram.y
diff options
context:
space:
mode:
Diffstat (limited to 'mh/mh_alias_gram.y')
-rw-r--r--mh/mh_alias_gram.y529
1 files changed, 529 insertions, 0 deletions
diff --git a/mh/mh_alias_gram.y b/mh/mh_alias_gram.y
new file mode 100644
index 000000000..26b13ec83
--- /dev/null
+++ b/mh/mh_alias_gram.y
@@ -0,0 +1,529 @@
+%{
+/* 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>
+#include <mailutils/locus.h>
+#include <mailutils/yyloc.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 (void)
+{
+ int status;
+ mu_list_t list;
+
+ status = mu_list_create (&list);
+ if (status)
+ {
+ mu_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 void
+ali_append (struct mh_alias *ali)
+{
+ if (ali)
+ {
+ if (!alias_list)
+ alias_list = list_create_or_die ();
+ mu_list_append (alias_list, ali);
+ }
+}
+
+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 EOL
+%token <string> STRING
+%type <list> address_list address_group string_list
+%type <string> address
+%type <alias> alias
+
+%locations
+
+%%
+
+input : alias_list
+ ;
+
+alias_list : alias
+ {
+ ali_append ($1);
+ }
+ | alias_list EOL alias
+ {
+ ali_append ($3);
+ }
+ ;
+
+alias : /* empty */
+ {
+ $$ = NULL;
+ }
+ | 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 (void)
+{
+ const char *p;
+
+ if (alias_list)
+ return 0;
+
+ 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.