"Fossies" - the Fresh Open Source Software Archive

Member "amavisd-milter-1.7.2/amavisd-milter/amavisd.c" (27 Jan 2019, 8613 Bytes) of package /linux/privat/amavisd-milter-1.7.2.tar.gz:


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 "amavisd.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Copyright (c) 2005, Petr Rehor <rx@rx.cz>. All rights reserved.
    3  *
    4  * Redistribution and use in source and binary forms, with or without
    5  * modification, are permitted provided that the following conditions
    6  * are met:
    7  * 1. Redistributions of source code must retain the above copyright
    8  *    notice, this list of conditions and the following disclaimer.
    9  * 2. Redistributions in binary form must reproduce the above copyright
   10  *    notice, this list of conditions and the following disclaimer in the
   11  *    documentation and/or other materials provided with the distribution.
   12  * 3. Neither the name of the copyright holders nor the names of its
   13  *    contributors may be used to endorse or promote products derived from
   14  *    this software without specific prior written permission.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   19  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   20  * OWNERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
   22  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   23  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   24  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   25  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   26  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   27  */
   28 
   29 #include "amavisd-milter.h"
   30 
   31 #include <ctype.h>
   32 
   33 
   34 /*
   35 ** AMAVISD_GROW_AMABUF - Reallocate amavisd communication buffer
   36 */
   37 static void *
   38 amavisd_grow_amabuf(struct mlfiCtx *mlfi, char *b)
   39 {
   40     char       *amabuf;
   41     size_t      buflen, bufpos;
   42 
   43     /* Calculate buffer pointer position */
   44     if (b == NULL) {
   45         bufpos = 0;
   46     } else {
   47         bufpos = b - mlfi->mlfi_amabuf;
   48     }
   49 
   50     /* Calculate new buffer size */
   51     buflen = mlfi->mlfi_amabuf_length + AMABUFCHUNK;
   52     if (mlfi->mlfi_amabuf_length < MAXAMABUF && buflen >= MAXAMABUF) {
   53         logqidmsg(mlfi, LOG_WARNING,
   54             "maximum size of amavisd communication buffer was reached");
   55         buflen = MAXAMABUF;
   56     } else if (buflen > MAXAMABUF) {
   57         logqidmsg(mlfi, LOG_ERR,
   58             "amavisd communication buffer is too big (%lu)",
   59             (unsigned long)buflen);
   60         errno = EOVERFLOW;
   61         return NULL;
   62     }
   63 
   64     /* Reallocate buffer */
   65     if ((amabuf = realloc(mlfi->mlfi_amabuf, buflen)) == NULL) {
   66         logqidmsg(mlfi, LOG_ERR,
   67             "could not reallocate amavisd communication buffer (%lu)",
   68             (unsigned long)buflen);
   69         return NULL;
   70     }
   71     mlfi->mlfi_amabuf = amabuf;
   72     mlfi->mlfi_amabuf_length = buflen;
   73 
   74     logqidmsg(mlfi, LOG_DEBUG,
   75         "amavisd communication buffer was increased to %lu",
   76         (unsigned long)buflen);
   77 
   78     return amabuf + bufpos;
   79 }
   80 
   81 
   82 /*
   83 ** AMAVISD_CONNECT - Connect to amavisd socket
   84 */
   85 int
   86 amavisd_connect(struct mlfiCtx *mlfi, struct sockaddr_un *sock, time_t timeout)
   87 {
   88     int         i;
   89 #ifdef HAVE_SEM_TIMEDWAIT
   90     struct      timespec max_timeout;
   91 #endif
   92 
   93     /* Lock amavisd connection */
   94     if (max_sem != NULL && mlfi->mlfi_max_sem_locked == 0) {
   95 #ifdef HAVE_SEM_TIMEDWAIT
   96         max_timeout.tv_sec = timeout;
   97         max_timeout.tv_nsec = 0;
   98         while ((i = sem_timedwait(max_sem, &max_timeout)) != 0 &&
   99             errno == EINTR)
  100         {
  101             continue;
  102         }
  103 #else
  104         while ((i = sem_trywait(max_sem)) != 0 &&
  105             errno == EAGAIN && time(NULL) < timeout)
  106         {
  107             sleep(1);
  108         }
  109 #endif
  110         if (i == -1) {
  111             if (errno != AMAVISD_CONNECT_TIMEDOUT_ERRNO) {
  112                 logqidmsg(mlfi, LOG_ERR,
  113                     "could not lock amavisd connections semaphore: %s",
  114                     strerror(errno));
  115             }
  116             return -1;
  117         }
  118         mlfi->mlfi_max_sem_locked = 1;
  119         sem_getvalue(max_sem, &i);
  120         logqidmsg(mlfi, LOG_DEBUG, "grab amavisd connection %d", i);
  121     }
  122 
  123     /* Initialize domain socket */
  124     memset(sock, '\0', sizeof(*sock));
  125     sock->sun_family = AF_UNIX;
  126     (void) strlcpy(sock->sun_path, amavisd_socket, sizeof(sock->sun_path));
  127     if ((mlfi->mlfi_amasd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) {
  128         logqidmsg(mlfi, LOG_ERR, "could not create amavisd socket %s: %s",
  129             amavisd_socket, strerror(errno));
  130         return -1;
  131     }
  132 
  133     /* Connect to amavisd */
  134     if (connect(mlfi->mlfi_amasd, (struct sockaddr *)sock, sizeof(*sock)) == -1)
  135     {
  136         logqidmsg(mlfi, LOG_ERR, "could not connect to amavisd socket %s: %s",
  137             amavisd_socket, strerror(errno));
  138         return -1;
  139     }
  140 
  141     /* Return socket */
  142     logqidmsg(mlfi, LOG_DEBUG, "open amavisd communication socket %s",
  143         amavisd_socket);
  144     return mlfi->mlfi_amasd;
  145 }
  146 
  147 
  148 /*
  149 ** AMAVISD_REQUEST - Write request line to amavisd
  150 */
  151 int
  152 amavisd_request(struct mlfiCtx *mlfi, const char *name, const char *value)
  153 {
  154     const char *p;
  155     char       *b = mlfi->mlfi_amabuf;
  156 
  157     /* Encode request */
  158     if (name != NULL) {
  159         p = name;
  160         while (*p != '\0') {
  161             if (b >= mlfi->mlfi_amabuf + mlfi->mlfi_amabuf_length - 5 &&
  162                 (b = amavisd_grow_amabuf(mlfi, b)) == NULL)
  163             {
  164                 return -1;
  165             }
  166             if (isalnum(*p) || *p == '-' || *p == '_') {
  167                 *b++ = *p++;
  168             } else {
  169                 (void) snprintf(b, 4, "%%%02x", *p++);
  170                 b += 3;
  171             }
  172         }
  173         if (value != NULL) {
  174             *b++ = '=';
  175         }
  176     }
  177     if (value != NULL) {
  178         p = value;
  179         while (*p != '\0') {
  180             if (b >= mlfi->mlfi_amabuf + mlfi->mlfi_amabuf_length - 4 &&
  181                 (b = amavisd_grow_amabuf(mlfi, b)) == NULL)
  182             {
  183                 return -1;
  184             }
  185             if (isalnum(*p) || *p == '-' || *p == '_') {
  186                 *b++ = *p++;
  187             } else {
  188                 (void) snprintf(b, 4, "%%%02x", *p++);
  189                 b += 3;
  190             }
  191         }
  192     }
  193     *b++ = '\n';
  194 
  195     /* Write request to amavisd socket */
  196     return write_sock(mlfi->mlfi_amasd, mlfi->mlfi_amabuf,
  197         b - mlfi->mlfi_amabuf, amavisd_timeout);
  198 }
  199 
  200 
  201 /*
  202 ** AMAVISD_RESPONSE - Read response line from amavisd
  203 */
  204 int
  205 amavisd_response(struct mlfiCtx *mlfi)
  206 {
  207     int         decode = 0;
  208     char       *b = mlfi->mlfi_amabuf;
  209     char       *b2;
  210 
  211     /* Read response line */
  212     while (read_sock(mlfi->mlfi_amasd, b, 1, amavisd_timeout) > 0) {
  213         if (b >= mlfi->mlfi_amabuf + mlfi->mlfi_amabuf_length - 2) {
  214             if ((b2 = amavisd_grow_amabuf(mlfi, b)) == NULL) {
  215                 *(b + 1) = '\0';
  216                 return -1;
  217             } else {
  218                 b = b2;
  219             }
  220         }
  221         if (*b == '\n') {
  222             *b = '\0';
  223             return 0;
  224         } else if (*b == '%') {
  225             decode = 1;
  226         } else if (decode == 1) {
  227             if (isxdigit(*b)) {
  228                 decode = 2;
  229                 b++;
  230             } else {
  231                 *(b + 1) = '\0';
  232                 errno = EILSEQ;
  233                 return -1;
  234             }
  235         } else if (decode == 2) {
  236             if (isxdigit(*b)) {
  237                 *(b + 1) = '\0';
  238                 *(b - 1) = (u_char) strtol(b - 1, NULL, 16);
  239                 decode = 0;
  240             } else {
  241                 *(b + 1) = '\0';
  242                 errno = EILSEQ;
  243                 return -1;
  244             }
  245         } else if (*b == '\r') {
  246             /* Do nothing */
  247         } else {
  248             b++;
  249         }
  250     }
  251 
  252     /* read_sock failed */
  253     *b = '\0';
  254     return -1;
  255 }
  256 
  257 
  258 /*
  259 ** AMAVISD_CLOSE - Close amavisd socket
  260 */
  261 void
  262 amavisd_close(struct mlfiCtx *mlfi)
  263 {
  264     /* Close amavisd connection */
  265     if (mlfi->mlfi_amasd != -1) {
  266         if (close(mlfi->mlfi_amasd) == -1) {
  267             logqidmsg(mlfi, LOG_ERR, "could not close amavisd socket %s: %s",
  268                 mlfi->mlfi_fname, strerror(errno));
  269         }
  270         mlfi->mlfi_amasd = -1;
  271         logqidmsg(mlfi, LOG_DEBUG, "close amavisd communication socket");
  272     }
  273 
  274     /* Unlock amavisd connection */
  275     if (mlfi->mlfi_max_sem_locked != 0) {
  276         if (sem_post(max_sem) == -1) {
  277             logqidmsg(mlfi, LOG_ERR,
  278                 "%s: could not unlock amavisd connections semaphore: %s",
  279                 strerror(errno));
  280         }
  281         mlfi->mlfi_max_sem_locked = 0;
  282         logqidmsg(mlfi, LOG_DEBUG, "got back amavisd connection");
  283     }
  284 }