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 817 by douglas, 2006-07-03T21:45:49-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 +                                        header_ = false;
222 +
223 +                                        goto crlf;
224 +                                }
225 +                                else if (size_ == 2 && !memcmp(line, "\r\n", 2))
226 +                                        header_ = false;
227 +                                else if (!(size_ > 2 && !memcmp(line + size_ - 2, "\r\n", 2)))
228 +                                {
229 + crlf:                           assert(message);
230 +
231 +                                        message = realloc(message, ++size * sizeof (char));
232 +
233 +                                        memcpy(message + size - 2, "\r\n", 2);
234 +                                }
235 +                        }
236 +                }
237 +                while (size_ != 0);
238 +
239 +                if (fclose(assassin_))
240 +                        longjmp(environment, 1);
241 +
242 +                int status;
243 +
244 +                check(waitpid(assassin, &status, 0), environment);
245 +
246 +                STRING message_;
247 +
248 +                INIT(&message_, mail_string, message, size);
249 +                mcheck((void *)mail_append_full(streams[0], "INBOX", "\\Seen", NIL, &message_), environment);
250 +                free(message);
251 +        }
252 +
253 +        streams[0] = mcheck(mail_open(streams[0], NEGATIVE, debug ? OP_DEBUG : 0), environment);
254 +
255 +        printf("    %u message(s) delivered.\n", count);
256 + }
257 +
258 + void delete()
259 + {
260 +        char *mailboxes[] = { NEGATIVE, POSITIVE };
261 +
262 +        for (char **mailbox = mailboxes; mailbox != mailboxes + sizeof (mailboxes) / sizeof (*mailboxes); ++mailbox)
263 +        {
264 +                printf("\nDeleting messages from the %s mailbox:\n", *mailbox);
265 +
266 +                const unsigned long *messages_ = messages[mailbox - mailboxes];
267 +                const size_t count = counts[mailbox - mailboxes];
268 +                char *sequence = calloc(1, sizeof (char));
269 +                size_t size = 1;
270 +
271 +                for (size_t index = 0; index != count; ++index)
272 +                {
273 +                        char *message;
274 +
275 +                        asprintf(&message, "%lu%s", messages_[index], index + 1 != count ? "," : "");
276 +
277 +                        sequence = realloc(sequence, (size += strlen(message)) * sizeof (char));
278 +
279 +                        strlcat(sequence, message, size);
280 +                        free(message);
281 +                }
282 +
283 +                mail_setflag_full(streams[mailbox - mailboxes], sequence, "\\Deleted", ST_UID | ST_SILENT);
284 +                free(sequence);
285 +                printf("    %u message(s) marked deleted.\n", count);
286 +        }
287 + }
288 +
289   int main(int argc, char *argv[])
290   {
291          int exception;
# Line 197 | Line 315 | int main(int argc, char *argv[])
315                  else
316                          return printf("Usage: %s [-debug]\n", argv[0]), 1;
317  
318 <        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");
318 >        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");
319 >
320 >        check(sigemptyset(&set), environment);
321 >        check(sigaddset(&set, SIGHUP), environment);
322 >        check(sigaddset(&set, SIGINT), environment);
323  
324   #       include <c-client/linkage.c>
325  
326          streams[0] = mcheck(mail_open(NIL, NEGATIVE, debug ? OP_DEBUG : 0), environment);
327          streams[1] = mcheck(mail_open(NIL, POSITIVE, debug ? OP_DEBUG : 0), environment);
328  
329 <        learn(environment);
329 >        learn();
330 >        deliver();
331 >        delete();
332          mail_close(streams[0]);
333          mail_close(streams[1]);
334 +        free(messages[0]);
335 +        free(messages[1]);
336  
337          return 0;
338   }
# Line 224 | Line 350 | void mm_searched(MAILSTREAM *stream, uns
350                          assert(messages[index]);
351  
352                          messages[index][counts[index] - 1] = number;
353 +
354 +                        break;
355                  }
356   }
357  
# Line 248 | Line 376 | void mm_login(NETMBX *mb, char *user, ch
376  
377   void mm_critical(MAILSTREAM *stream)
378   {
379 <        fprintf(stderr, "critical\n");
379 >        if (!critical++)
380 >                check(sigprocmask(SIG_BLOCK, &set, NULL), environment);
381   }
382  
383   void mm_nocritical(MAILSTREAM *stream)
384   {
385 <        fprintf(stderr, "nocritical\n");
385 >        if (!--critical)
386 >                check(sigprocmask(SIG_UNBLOCK, &set, NULL), environment);
387   }
388  
389   long mm_diskerror(MAILSTREAM *stream, long errcode, long serious)

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines