chiark / gitweb /
debian/control: Fix x86-model architecture string.
[misc] / qmail-checkspam.c
CommitLineData
8d769cc9 1/* -*-c-*-
2 *
9a4b2474 3 * $Id: qmail-checkspam.c,v 1.2 2004/04/08 01:36:26 mdw Exp $
8d769cc9 4 *
5 * Filter messages for spam
6 *
7 * (c) 2003 Mark Wooding
8 */
9
841e5aca 10/*----- Licensing notice --------------------------------------------------*
8d769cc9 11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
841e5aca 16 *
8d769cc9 17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
841e5aca 21 *
8d769cc9 22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software Foundation,
24 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 */
26
8d769cc9 27/*----- Header files ------------------------------------------------------*/
28
29#include <ctype.h>
30#include <errno.h>
913eb210 31#include <limits.h>
8d769cc9 32#include <stdio.h>
33#include <stdlib.h>
34#include <string.h>
35
36#include <sys/types.h>
37#include <sys/unistd.h>
38
39#include <libspamc.h>
40
41/*----- Main code ---------------------------------------------------------*/
42
43static const char *strenv(const char *e, const char *d)
44{
45 const char *p = getenv(e);
46 if (!p) return (d);
47 return (p);
48}
49
50static double dblenv(const char *e, double d)
51{
52 const char *p = getenv(e);
53 char *q;
54 int err = errno;
55 double f;
56 if (!p) return (d);
57 errno = 0;
58 f = strtod(p, &q);
59 if (errno) return (d);
60 errno = err;
61 return (f);
62}
63
64static int intenv(const char *e, int d)
65{
66 const char *p = getenv(e);
67 char *q;
68 int err = errno;
69 long l;
70 if (!p) return (d);
71 errno = 0;
72 l = strtol(p, &q, 0);
73 if (errno) return (d);
74 errno = err;
75 if (l < 0 || l > INT_MAX) return (d);
76 return ((int)l);
77}
78
79int shovel(int from, int to)
80{
81 char buf[4096];
82 ssize_t n;
83 char *p;
84 size_t r;
85
86 for (;;) {
87 n = read(from, buf, sizeof(buf));
88 if (n < 0 && errno != EINTR && errno != EAGAIN)
89 return (-1);
90 else if (!n)
91 return (0);
92 p = buf;
93 r = n;
94 while (r) {
95 n = write(to, p, n);
96 if (n <= 0 && errno != EINTR && errno != EAGAIN)
97 return (-1);
98 r -= n;
99 p += n;
100 }
101 }
102}
103
104int main(int argc, char *argv[])
105{
106 struct sockaddr sa;
107 struct message m;
108 int fd_m[2], fd_e[2];
109 pid_t kid;
02955332 110 const char *qmq;
8d769cc9 111 int rc;
112
6365546c 113 if (getenv("RELAYCLIENT")) goto exec;
8d769cc9 114 m.max_len = intenv("QMAIL_CHECKSPAM_MAXLEN", 2 * 1024 * 1024);
115 m.timeout = intenv("QMAIL_CHECKSPAM_TIMEOUT", 300);
116 rc = message_read(0, 0, &m);
117 if (rc != 0 && rc != EX_TOOBIG)
118 return (54);
119 if (!rc) {
120 if (lookup_host(strenv("QMAIL_CHECKSPAM_SPAMDHOST", "localhost"),
121 intenv("QMAIL_CHECKSPAM_SPAMDPORT", 783),
122 &sa))
123 return (56);
124 if (message_filter(&sa, "spamd", 0, &m))
125 return (74);
126 if (m.score >= dblenv("QMAIL_CHECKSPAM_THRESH", m.threshold))
127 return (31);
128 }
129 if (pipe(fd_m) || pipe(fd_e))
130 return (56);
131 if ((kid = fork()) < 0)
132 return (56);
133 if (!kid) {
134 close(fd_m[0]);
135 close(fd_e[0]);
136 if (message_write(fd_m[1], &m) < 0)
137 _exit(127);
138 if (rc == EX_TOOBIG && shovel(0, fd_m[1]))
139 _exit(127);
140 close(fd_m[1]);
141 if (shovel(1, fd_e[1]))
142 _exit(127);
143 close(fd_e[1]);
144 _exit(0);
145 }
146
147 dup2(fd_m[0], 0);
148 dup2(fd_e[0], 1);
149 close(fd_m[0]);
150 close(fd_e[0]);
151 close(fd_m[1]);
152 close(fd_e[1]);
6365546c 153exec:
02955332
MW
154 qmq = strenv("QMAIL_CHECKSPAM_QUEUE", "/var/qmail/bin/qmail-queue");
155 execlp(qmq, qmq, (char *)0);
8d769cc9 156 fprintf(stderr, "failed to exec: %s\n", strerror(errno));
157 return (56);
158}
159
160/*----- That's all, folks -------------------------------------------------*/