ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/repos/FreeBSDAdmin/Mail/SpamUpdate.c
(Generate patch)

Comparing FreeBSDAdmin/Mail/SpamUpdate.c (file contents):
Revision 815 by douglas, 2006-07-03T14:03:04-07:00 vs.
Revision 819 by douglas, 2006-07-03T22:15:40-07:00

# Line 6 | Line 6
6  
7   #include <assert.h>
8   #include <sys/types.h>
9 #include <regex.h>
9   #include <setjmp.h>
10 + #include <signal.h>
11   #include <stdbool.h>
12   #include <stdio.h>
13   #include <sys/wait.h>
# Line 28 | Line 28
28   static jmp_buf environment;
29   static char *error = NULL;
30   static bool debug = false;
31 + static sigset_t set;
32   static MAILSTREAM *streams[2];
33 + static uint8_t critical = 0;
34   static unsigned long *messages[] = { NULL, NULL };
35   static size_t counts[] = { 0, 0 };
36  
37 < /*static*/ int check(int value, jmp_buf environment)
37 > static int check(int value, jmp_buf environment)
38   {
39          if (value == -1)
40                  longjmp(environment, 1);
# Line 40 | Line 42 | static size_t counts[] = { 0, 0 };
42          return value;
43   }
44  
45 < /*static*/ char *fcheck(char *value, FILE *stream, jmp_buf environment)
45 > static char *fcheck(char *value, FILE *stream, jmp_buf environment)
46   {
47          if (!value)
48          {
# Line 68 | Line 70 | static void *mcheck(void *value, jmp_buf
70          return value;
71   }
72  
73 < /*static*/ int regcheck(int value, const regex_t *regex, jmp_buf environment)
72 < {
73 <        if (value && value != REG_NOMATCH)
74 <        {
75 <                char exception[regerror(value, regex, NULL, 0)];
76 <
77 <                regerror(value, regex, exception, sizeof (exception));
78 <                longjmp(environment, (int)exception);
79 <        }
80 <
81 <        return value;
82 < }
83 <
84 < static void learn(jmp_buf environment)
73 > static void learn()
74   {
75          typedef struct { const char *verb, *args, *mailbox; } Job;
76          
# Line 95 | Line 84 | static void learn(jmp_buf environment)
84                  
85                  mail_search_full(streams[job - jobs], NIL, &search, SE_UID);
86  
87 <                unsigned long *messages_ = messages[job - jobs];
88 <                size_t count = counts[job - jobs];
87 >                const unsigned long *messages_ = messages[job - jobs];
88 >                const size_t count = counts[job - jobs];
89                  char files[count][sizeof (TEMP) / sizeof (char)];
90  
91                  for (size_t index = 0; index != count; ++index)
# Line 168 | Line 157 | static void learn(jmp_buf environment)
157          }
158   }
159  
160 + static void deliver()
161 + {
162 +        printf("\nDelivering messages from the " POSITIVE " mailbox:\n");
163 +
164 +        const unsigned long *messages_ = messages[1];
165 +        const size_t count = counts[1];
166 +
167 +        streams[0] = mcheck(mail_open(streams[0], "INBOX", (debug ? OP_DEBUG : 0) | OP_SHORTCACHE), environment);
168 +
169 +        for (int index = 0; index != count; ++index)
170 +        {
171 +                int out[2], in[2];
172 +
173 +                check(pipe(out), environment);
174 +                check(pipe(in), environment);
175 +
176 +                pid_t assassin;
177 +
178 +                if (!(assassin = check(fork(), environment)))
179 +                {
180 +                        check(dup2(out[0], 0), environment);
181 +                        check(close(out[1]), environment);
182 +                        check(dup2(in[1], 1), environment);
183 +                        check(close(in[0]), environment);
184 +                        check(execl(ASSASSIN, "spamassassin", "-d", NULL), environment);
185 +                }
186 +
187 +                check(close(out[0]), environment);
188 +                check(close(in[1]), environment);
189 +
190 +                unsigned long size;
191 +                char *header = mcheck(mail_fetchheader_full(streams[1], messages_[index], NIL, &size, FT_UID), environment);
192 +
193 +                check(write(out[1], header, size), environment);
194 +
195 +                char *text = mcheck(mail_fetchtext_full(streams[1], messages_[index], &size, FT_UID), environment);
196 +
197 +                check(write(out[1], text, size), environment);
198 +                check(close(out[1]), environment);
199 +
200 +                FILE *assassin_ = fdopen(in[0], "r");
201 +                size_t size_;
202 +                bool header_ = true;
203 +                char *message = NULL;
204 +
205 +                size = 0;
206 +
207 +                do
208 +                {
209 +                        char *line = fcheck(fgetln(assassin_, &size_), assassin_, environment);
210 +
211 +                        message = message ? realloc(message, (size + size_) * sizeof (char)) : malloc((size + size_) * sizeof (char));
212 +
213 +                        memcpy(message + size, line, size_);
214 +
215 +                        size += size_;
216 +
217 +                        if (header_)
218 +                        {
219 +                                if (size_ == 1)
220 +                                {
221 +                                        assert(*line == '\n');
222 +
223 +                                        header_ = false;
224 +
225 +                                        goto crlf;
226 +                                }
227 +                                else if (size_ == 2 && !memcmp(line, "\r\n", 2))
228 +                                        header_ = false;
229 +                                else if (!(size_ > 2 && !memcmp(line + size_ - 2, "\r\n", 2)))
230 +                                {
231 + crlf:                           assert(message);
232 +
233 +                                        message = realloc(message, ++size * sizeof (char));
234 +
235 +                                        memcpy(message + size - 2, "\r\n", 2);
236 +                                }
237 +                        }
238 +                }
239 +                while (size_ != 0);
240 +
241 +                if (fclose(assassin_))
242 +                        longjmp(environment, 1);
243 +
244 +                int status;
245 +
246 +                check(waitpid(assassin, &status, 0), environment);
247 +
248 +                STRING message_;
249 +
250 +                INIT(&message_, mail_string, message, size);
251 +                mcheck((void *)mail_append_full(streams[0], "INBOX", "\\Seen", NIL, &message_), environment);
252 +                free(message);
253 +        }
254 +
255 +        streams[0] = mcheck(mail_open(streams[0], NEGATIVE, debug ? OP_DEBUG : 0), environment);
256 +
257 +        printf("    %u message(s) delivered.\n", count);
258 + }
259 +
260 + void delete()
261 + {
262 +        char *mailboxes[] = { NEGATIVE, POSITIVE };
263 +
264 +        for (char **mailbox = mailboxes; mailbox != mailboxes + sizeof (mailboxes) / sizeof (*mailboxes); ++mailbox)
265 +        {
266 +                printf("\nDeleting messages from the %s mailbox:\n", *mailbox);
267 +
268 +                const unsigned long *messages_ = messages[mailbox - mailboxes];
269 +                const size_t count = counts[mailbox - mailboxes];
270 +                char *sequence = calloc(1, sizeof (char));
271 +                size_t size = 1;
272 +
273 +                for (size_t index = 0; index != count; ++index)
274 +                {
275 +                        char *message;
276 +
277 +                        asprintf(&message, "%lu%s", messages_[index], index + 1 != count ? "," : "");
278 +
279 +                        sequence = realloc(sequence, (size += strlen(message)) * sizeof (char));
280 +
281 +                        strlcat(sequence, message, size);
282 +                        free(message);
283 +                }
284 +
285 +                mail_setflag_full(streams[mailbox - mailboxes], sequence, "\\Deleted", ST_UID | ST_SILENT);
286 +                free(sequence);
287 +                printf("    %u message(s) marked deleted.\n", count);
288 +        }
289 + }
290 +
291   int main(int argc, char *argv[])
292   {
293          int exception;
# Line 197 | Line 317 | int main(int argc, char *argv[])
317                  else
318                          return printf("Usage: %s [-debug]\n", argv[0]), 1;
319  
320 <        printf("Information:\n    If you receive Spam in your Inbox mailbox, copy it to the " NEGATIVE " mailbox.\n\n    If you receive mail that is not Spam in your Assassin mailbox, copy it to the " POSITIVE " mailbox.\n");
320 >        printf("Information:\n    If you receive spam in your Inbox mailbox, copy it to the " NEGATIVE " mailbox.\n\n    If you receive mail that is not spam in your Spam/Assassin mailbox, copy it to the " POSITIVE " mailbox.\n");
321 >
322 >        check(sigemptyset(&set), environment);
323 >        check(sigaddset(&set, SIGHUP), environment);
324 >        check(sigaddset(&set, SIGINT), environment);
325  
326   #       include <c-client/linkage.c>
327  
328          streams[0] = mcheck(mail_open(NIL, NEGATIVE, debug ? OP_DEBUG : 0), environment);
329          streams[1] = mcheck(mail_open(NIL, POSITIVE, debug ? OP_DEBUG : 0), environment);
330  
331 <        learn(environment);
331 >        learn();
332 >        deliver();
333 >        delete();
334          mail_close(streams[0]);
335          mail_close(streams[1]);
336 +        free(messages[0]);
337 +        free(messages[1]);
338  
339          return 0;
340   }
# Line 224 | Line 352 | void mm_searched(MAILSTREAM *stream, uns
352                          assert(messages[index]);
353  
354                          messages[index][counts[index] - 1] = number;
355 +
356 +                        break;
357                  }
358   }
359  
# Line 248 | Line 378 | void mm_login(NETMBX *mb, char *user, ch
378  
379   void mm_critical(MAILSTREAM *stream)
380   {
381 <        fprintf(stderr, "critical\n");
381 >        if (!critical++)
382 >                check(sigprocmask(SIG_BLOCK, &set, NULL), environment);
383   }
384  
385   void mm_nocritical(MAILSTREAM *stream)
386   {
387 <        fprintf(stderr, "nocritical\n");
387 >        if (!--critical)
388 >                check(sigprocmask(SIG_UNBLOCK, &set, NULL), environment);
389   }
390  
391   long mm_diskerror(MAILSTREAM *stream, long errcode, long serious)

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines