"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 }