"Fossies" - the Fresh Open Source Software Archive

Member "msmtp-1.8.17/src/aliases.c" (16 Dec 2020, 7382 Bytes) of package /linux/privat/msmtp-1.8.17.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "aliases.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.8.13_vs_1.8.14.

    1 /*
    2  * aliases.c
    3  *
    4  * This file is part of msmtp, an SMTP client.
    5  *
    6  * Copyright (C) 2011, 2019
    7  * Scott Shumate <sshumate@austin.rr.com>
    8  *
    9  *   This program is free software; you can redistribute it and/or modify
   10  *   it under the terms of the GNU General Public License as published by
   11  *   the Free Software Foundation; either version 3 of the License, or
   12  *   (at your option) any later version.
   13  *
   14  *   This program is distributed in the hope that it will be useful,
   15  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
   16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17  *   GNU General Public License for more details.
   18  *
   19  *   You should have received a copy of the GNU General Public License
   20  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
   21  */
   22 
   23 #define MAXTOKS 32
   24 #define MAXLINE 512
   25 #define MAXDEPTH 16
   26 
   27 #include <stdio.h>
   28 #include <stdlib.h>
   29 #include <string.h>
   30 #include <ctype.h>
   31 #include <errno.h>
   32 
   33 #include "gettext.h"
   34 #define _(string) gettext(string)
   35 
   36 #include "aliases.h"
   37 #include "list.h"
   38 #include "xalloc.h"
   39 
   40 
   41 typedef struct alias
   42 {
   43     char *alias_str;
   44     list_t *addr_list;
   45 } alias_t;
   46 
   47 static char *trim(char *str)
   48 {
   49     char *end;
   50 
   51     while (isspace(*str))
   52         str++;
   53 
   54     end = str + strlen(str) - 1;
   55     while (end > str && isspace(*end))
   56         end--;
   57 
   58     *(++end) = '\0';
   59 
   60     return str;
   61 }
   62 
   63 static int split(char *str, char delim, char *tokv[])
   64 {
   65     int tokc = 0;
   66     char *loc;
   67 
   68     while (tokc < MAXTOKS && (loc = strchr(str, delim)) != NULL)
   69     {
   70         *loc = '\0';
   71         *tokv++ = trim(str);
   72         tokc++;
   73         str = loc + 1;
   74     }
   75 
   76     if (tokc < MAXTOKS)
   77     {
   78         *tokv++ = trim(str);
   79         tokc++;
   80     }
   81 
   82     return tokc;
   83 }
   84 
   85 static int is_alias(const char *str)
   86 {
   87     return (*str != '\0' && strchr(str, '@') == NULL);
   88 }
   89 
   90 static alias_t *alias_find(const char *alias_str, list_t *alias_list)
   91 {
   92     alias_t *entry;
   93 
   94     while (!list_is_empty(alias_list))
   95     {
   96         entry = alias_list->next->data;
   97         if (strcmp(alias_str, entry->alias_str) == 0)
   98             return entry;
   99         alias_list = alias_list->next;
  100     }
  101 
  102     return NULL;
  103 }
  104 
  105 static int aliases_read(FILE *f, list_t *alias_list, char **errstr)
  106 {
  107     char line[MAXLINE];
  108     char *tokv[MAXTOKS];
  109     int tokc;
  110     int i;
  111     int lnum = 1;
  112     alias_t *entry;
  113     list_t *addr_list;
  114     list_t *alias_itr = alias_list;
  115 
  116     while (fgets(line, MAXLINE, f) != NULL)
  117     {
  118         /* Check line length */
  119         if (strlen(line) == MAXLINE - 1)
  120         {
  121             *errstr = xasprintf(_("line %d: longer than %d characters"),
  122                     lnum, MAXLINE - 1);
  123             return ALIASES_EPARSE;
  124         }
  125 
  126         /* Split off comments */
  127         tokc = split(line, '#', tokv);
  128 
  129         /* Split on the colon delimiter */
  130         tokc = split(tokv[0], ':', tokv);
  131 
  132         /* If line is not empty */
  133         if (tokc != 1 || *tokv[0] != '\0')
  134         {
  135             /* Expect a single delimiter */
  136             if (tokc != 2)
  137             {
  138                 *errstr = xasprintf(_("line %d: single ':' delimiter expected"),
  139                         lnum);
  140                 return ALIASES_EPARSE;
  141             }
  142 
  143             /* Check for a valid alias */
  144             if (!is_alias(tokv[0]))
  145             {
  146                 *errstr = xasprintf(_("line %d: invalid alias '%s'"),
  147                         lnum, tokv[0]);
  148                 return ALIASES_EPARSE;
  149             }
  150 
  151             if (alias_find(tokv[0], alias_list))
  152             {
  153                 *errstr = xasprintf(_("line %d: duplicate alias '%s'"),
  154                         lnum, tokv[0]);
  155                 return ALIASES_EPARSE;
  156             }
  157 
  158             entry = xmalloc(sizeof(alias_t));
  159             entry->alias_str = xstrdup(tokv[0]);
  160             entry->addr_list = list_new();
  161             addr_list = entry->addr_list;
  162 
  163             list_insert(alias_itr, entry);
  164             alias_itr = alias_itr->next;
  165 
  166             /* Add addresses to the list*/
  167             tokc = split(tokv[1], ',', tokv);
  168             for (i = 0; i < tokc; i++)
  169             {
  170                 list_insert(addr_list, xstrdup(tokv[i]));
  171                 addr_list = addr_list->next;
  172             }
  173         }
  174         lnum++;
  175     }
  176     if (ferror(f))
  177     {
  178         *errstr = xasprintf(_("input error"));
  179         return ALIASES_EIO;
  180     }
  181 
  182     return ALIASES_EOK;
  183 }
  184 
  185 static void alias_free(void *ptr)
  186 {
  187     alias_t *entry = ptr;
  188 
  189     if (entry)
  190     {
  191         list_xfree(entry->addr_list, free);
  192         free(entry->alias_str);
  193         free(entry);
  194     }
  195 }
  196 
  197 static int expand_alias(char *alias, list_t *alias_list, int depth, list_t *addr_list)
  198 {
  199     alias_t *e;
  200     int rc;
  201     list_t *a;
  202 
  203     if (depth > MAXDEPTH)
  204         return ALIASES_ELOOP;
  205 
  206     e = alias_find(alias, alias_list);
  207     if (e == NULL)
  208         e = alias_find("default", alias_list);
  209 
  210     if (e == NULL)
  211     {
  212         /* Can't find it in aliases, use as-is */
  213         list_insert(addr_list, xstrdup(alias));
  214         return ALIASES_EOK;
  215     }
  216 
  217     for (a = e->addr_list; !list_is_empty(a); a = a->next)
  218     {
  219         if (! is_alias(a->next->data))
  220         {
  221             list_insert(addr_list, xstrdup(a->next->data));
  222             continue;
  223         }
  224         /* found an alias, recursively expand */
  225         rc = expand_alias(a->next->data, alias_list, depth+1, addr_list);
  226         if (rc != ALIASES_EOK)
  227             return rc;
  228     }
  229 
  230     return ALIASES_EOK;
  231 }
  232 
  233 int aliases_replace(const char *aliases, list_t *recipient_list, char **errstr)
  234 {
  235     FILE *f;
  236     int e;
  237     list_t *alias_list;
  238     list_t *addr_list, *addr_itr;
  239     list_t *rec_itr;
  240 
  241     /* Make sure there is at least one alias */
  242     for (rec_itr = recipient_list;
  243          !list_is_empty(rec_itr);
  244          rec_itr = rec_itr->next)
  245     {
  246         if (is_alias(rec_itr->next->data))
  247             break;
  248     }
  249     if (list_is_empty(rec_itr))
  250         return ALIASES_EOK;
  251 
  252     /* Open and read the alias file */
  253     if (!(f = fopen(aliases, "r")))
  254     {
  255         *errstr = xasprintf("%s", strerror(errno));
  256         return ALIASES_ECANTOPEN;
  257     }
  258 
  259     alias_list = list_new();
  260 
  261     if ((e = aliases_read(f, alias_list, errstr))
  262             != ALIASES_EOK)
  263     {
  264         fclose(f);
  265         list_xfree(alias_list, alias_free);
  266         return e;
  267     }
  268 
  269     fclose(f);
  270 
  271     /* Process all aliases in the recipient list */
  272     for (rec_itr = recipient_list;
  273          !list_is_empty(rec_itr);
  274          rec_itr = rec_itr->next)
  275     {
  276         if (is_alias(rec_itr->next->data))
  277         {
  278             addr_list = list_new();
  279             e = expand_alias(rec_itr->next->data, alias_list, 0, addr_list);
  280             if (e != ALIASES_EOK)
  281             {
  282                 *errstr = xasprintf(
  283                     _("Too many redirects when expanding alias %s."),
  284                     (char *) rec_itr->next->data);
  285                 list_xfree(addr_list, free);
  286                 list_xfree(alias_list, alias_free);
  287                 return e;
  288             }
  289             list_xremove(rec_itr, free);
  290             for (addr_itr = addr_list;
  291                  !list_is_empty(addr_itr);
  292                  addr_itr = addr_itr->next)
  293             {
  294                 list_insert(rec_itr, addr_itr->next->data);
  295                 rec_itr = rec_itr->next;
  296             }
  297             list_free(addr_list);
  298         }
  299     }
  300 
  301     list_xfree(alias_list, alias_free);
  302 
  303     return ALIASES_EOK;
  304 }