"Fossies" - the Fresh Open Source Software Archive

Member "msmtp-1.8.4/src/aliases.c" (11 Jun 2018, 6885 Bytes) of package /linux/privat/msmtp-1.8.4.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.

    1 /*
    2  * aliases.c
    3  *
    4  * This file is part of msmtp, an SMTP client.
    5  *
    6  * Copyright (C) 2011
    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 
   26 #include <stdio.h>
   27 #include <stdlib.h>
   28 #include <string.h>
   29 #include <ctype.h>
   30 #include <errno.h>
   31 
   32 #include "gettext.h"
   33 #define _(string) gettext(string)
   34 
   35 #include "aliases.h"
   36 #include "list.h"
   37 #include "tools.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 int is_address(const char *str)
   91 {
   92     return (*str != '\0' && strchr(str, '@') != NULL);
   93 }
   94 
   95 static alias_t *alias_find(const char *alias_str, list_t *alias_list)
   96 {
   97     alias_t *entry;
   98 
   99     while (!list_is_empty(alias_list))
  100     {
  101         entry = alias_list->next->data;
  102         if (strcmp(alias_str, entry->alias_str) == 0)
  103             return entry;
  104         alias_list = alias_list->next;
  105     }
  106 
  107     return NULL;
  108 }
  109 
  110 static int aliases_read(FILE *f, list_t *alias_list, char **errstr)
  111 {
  112     char line[MAXLINE];
  113     char *tokv[MAXTOKS];
  114     int tokc;
  115     int i;
  116     int lnum = 1;
  117     alias_t *entry;
  118     list_t *addr_list;
  119     list_t *alias_itr = alias_list;
  120 
  121     while (fgets(line, MAXLINE, f) != NULL)
  122     {
  123         /* Check line length */
  124         if (strlen(line) == MAXLINE - 1)
  125         {
  126             *errstr = xasprintf(_("line %d: longer than %d characters"),
  127                     lnum, MAXLINE - 1);
  128             return ALIASES_EPARSE;
  129         }
  130 
  131         /* Split off comments */
  132         tokc = split(line, '#', tokv);
  133 
  134         /* Split on the colon delimiter */
  135         tokc = split(tokv[0], ':', tokv);
  136 
  137         /* If line is not empty */
  138         if (tokc != 1 || *tokv[0] != '\0')
  139         {
  140             /* Expect a single delimiter */
  141             if (tokc != 2)
  142             {
  143                 *errstr = xasprintf(_("line %d: single ':' delimiter expected"),
  144                         lnum);
  145                 return ALIASES_EPARSE;
  146             }
  147 
  148             /* Check for a valid alias */
  149             if (!is_alias(tokv[0]))
  150             {
  151                 *errstr = xasprintf(_("line %d: invalid alias '%s'"),
  152                         lnum, tokv[0]);
  153                 return ALIASES_EPARSE;
  154             }
  155 
  156             if (alias_find(tokv[0], alias_list))
  157             {
  158                 *errstr = xasprintf(_("line %d: duplicate alias '%s'"),
  159                         lnum, tokv[0]);
  160                 return ALIASES_EPARSE;
  161             }
  162 
  163             entry = xmalloc(sizeof(alias_t));
  164             entry->alias_str = xstrdup(tokv[0]);
  165             entry->addr_list = list_new();
  166             addr_list = entry->addr_list;
  167 
  168             list_insert(alias_itr, entry);
  169             alias_itr = alias_itr->next;
  170 
  171             /* Add addresses to the list*/
  172             tokc = split(tokv[1], ',', tokv);
  173             for (i = 0; i < tokc; i++)
  174             {
  175                 if (!is_address(tokv[i]))
  176                 {
  177                     *errstr = xasprintf(_("line %d: invalid address '%s'"),
  178                             lnum, tokv[i]);
  179                     return ALIASES_EPARSE;
  180                 }
  181 
  182                 list_insert(addr_list, xstrdup(tokv[i]));
  183                 addr_list = addr_list->next;
  184             }
  185         }
  186         lnum++;
  187     }
  188     if (ferror(f))
  189     {
  190         *errstr = xasprintf(_("input error"));
  191         return ALIASES_EIO;
  192     }
  193 
  194     return ALIASES_EOK;
  195 }
  196 
  197 static void alias_free(void *ptr)
  198 {
  199     alias_t *entry = ptr;
  200 
  201     if (entry)
  202     {
  203         list_xfree(entry->addr_list, free);
  204         free(entry->alias_str);
  205         free(entry);
  206     }
  207 }
  208 
  209 int aliases_replace(const char *aliases, list_t *recipient_list, char **errstr)
  210 {
  211     FILE *f;
  212     int e;
  213     list_t *alias_list;
  214     list_t *addr_list;
  215     alias_t *entry;
  216     list_t *rec_itr;
  217 
  218     /* Make sure there is at least one alias */
  219     for (rec_itr = recipient_list;
  220          !list_is_empty(rec_itr);
  221          rec_itr = rec_itr->next)
  222     {
  223         if (is_alias(rec_itr->next->data))
  224             break;
  225     }
  226     if (list_is_empty(rec_itr))
  227         return ALIASES_EOK;
  228 
  229     /* Open and read the alias file */
  230     if (!(f = fopen(aliases, "r")))
  231     {
  232         *errstr = xasprintf("%s", strerror(errno));
  233         return ALIASES_ECANTOPEN;
  234     }
  235 
  236     alias_list = list_new();
  237 
  238     if ((e = aliases_read(f, alias_list, errstr))
  239             != ALIASES_EOK)
  240     {
  241         fclose(f);
  242         list_xfree(alias_list, alias_free);
  243         return e;
  244     }
  245 
  246     fclose(f);
  247 
  248     /* Process all aliases in the recipient list */
  249     for (rec_itr = recipient_list;
  250          !list_is_empty(rec_itr);
  251          rec_itr = rec_itr->next)
  252     {
  253         if (is_alias(rec_itr->next->data))
  254         {
  255             entry = alias_find(rec_itr->next->data, alias_list);
  256             if (entry == NULL)
  257             {
  258                 entry = alias_find("default", alias_list);
  259             }
  260             if (entry != NULL)
  261             {
  262                 list_xremove(rec_itr, free);
  263                 addr_list = entry->addr_list;
  264                 if (!list_is_empty(addr_list))
  265                 {
  266                     list_insert(rec_itr, xstrdup(addr_list->next->data));
  267                     addr_list = addr_list->next;
  268                     while (!list_is_empty(addr_list))
  269                     {
  270                         list_insert(rec_itr, xstrdup(addr_list->next->data));
  271                         rec_itr = rec_itr->next;
  272                         addr_list = addr_list->next;
  273                     }
  274                 }
  275             }
  276         }
  277     }
  278 
  279     list_xfree(alias_list, alias_free);
  280 
  281     return ALIASES_EOK;
  282 }