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 821 by douglas, 2006-07-04T16:27:43-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 116 | Line 105 | static void learn(jmp_buf environment)
105                          check(close(file), environment);
106                  }
107  
108 <                int pipe_[2];
108 >                int between[2];
109  
110 <                check(pipe(pipe_), environment);
110 >                check(pipe(between), environment);
111  
112                  pid_t assassin;
113  
114                  if (!(assassin = check(fork(), environment)))
115                  {
116 <                        check(dup2(pipe_[1], 1), environment);
117 <                        check(close(pipe_[0]), environment);
116 >                        check(dup2(between[1], 1), environment);
117 >                        check(close(between[0]), environment);
118  
119                          const char *args[count ? count + 3 : 5];
120                          
# Line 146 | Line 135 | static void learn(jmp_buf environment)
135                          check(execv(ASSASSIN, (char *const *)args), environment);
136                  }
137  
138 <                check(close(pipe_[1]), environment);
138 >                check(close(between[1]), environment);
139 >
140 >                int in[2];
141 >
142 >                check(pipe(in), environment);
143  
144                  pid_t sed;
145  
146                  if (!(sed = check(fork(), environment)))
147                  {
148 <                        check(dup2(pipe_[0], 0), environment);
148 >                        check(dup2(between[0], 0), environment);
149 >                        check(dup2(in[1], 1), environment);
150 >                        check(close(in[0]), environment);
151                          check(execl(SED, "sed", "-e", INDENT, "-e", PERIOD, NULL), environment);
152                  }
153  
154 <                check(close(pipe_[0]), environment);
154 >                check(close(between[0]), environment);
155 >                check(close(in[1]), environment);
156 >
157 >                FILE *sed_ = fdopen(in[0], "r");
158 >                size_t size;
159 >
160 >                do
161 >                {
162 >                        char *line = fcheck(fgetln(sed_, &size), sed_, environment);
163 >
164 >                        printf("%s", line);
165 >                }
166 >                while (size != 0);
167  
168                  int status;
169  
# Line 168 | Line 175 | static void learn(jmp_buf environment)
175          }
176   }
177  
178 + static void deliver()
179 + {
180 +        printf("\nDelivering messages from the " POSITIVE " mailbox:\n");
181 +
182 +        const unsigned long *messages_ = messages[1];
183 +        const size_t count = counts[1];
184 +
185 +        streams[0] = mcheck(mail_open(streams[0], "INBOX", (debug ? OP_DEBUG : 0) | OP_SHORTCACHE), environment);
186 +
187 +        for (int index = 0; index != count; ++index)
188 +        {
189 +                int out[2], in[2];
190 +
191 +                check(pipe(out), environment);
192 +                check(pipe(in), environment);
193 +
194 +                pid_t assassin;
195 +
196 +                if (!(assassin = check(fork(), environment)))
197 +                {
198 +                        check(dup2(out[0], 0), environment);
199 +                        check(close(out[1]), environment);
200 +                        check(dup2(in[1], 1), environment);
201 +                        check(close(in[0]), environment);
202 +                        check(execl(ASSASSIN, "spamassassin", "-d", NULL), environment);
203 +                }
204 +
205 +                check(close(out[0]), environment);
206 +                check(close(in[1]), environment);
207 +
208 +                unsigned long size;
209 +                char *header = mcheck(mail_fetchheader_full(streams[1], messages_[index], NIL, &size, FT_UID), environment);
210 +
211 +                check(write(out[1], header, size), environment);
212 +
213 +                char *text = mcheck(mail_fetchtext_full(streams[1], messages_[index], &size, FT_UID), environment);
214 +
215 +                check(write(out[1], text, size), environment);
216 +                check(close(out[1]), environment);
217 +
218 +                FILE *assassin_ = fdopen(in[0], "r");
219 +                size_t size_;
220 +                bool header_ = true;
221 +                char *message = NULL;
222 +
223 +                size = 0;
224 +
225 +                do
226 +                {
227 +                        char *line = fcheck(fgetln(assassin_, &size_), assassin_, environment);
228 +
229 +                        message = message ? realloc(message, (size + size_) * sizeof (char)) : malloc((size + size_) * sizeof (char));
230 +
231 +                        memcpy(message + size, line, size_);
232 +
233 +                        size += size_;
234 +
235 +                        if (header_)
236 +                        {
237 +                                if (size_ == 1)
238 +                                {
239 +                                        assert(*line == '\n');
240 +
241 +                                        header_ = false;
242 +
243 +                                        goto crlf;
244 +                                }
245 +                                else if (size_ == 2 && !memcmp(line, "\r\n", 2))
246 +                                        header_ = false;
247 +                                else if (!(size_ > 2 && !memcmp(line + size_ - 2, "\r\n", 2)))
248 +                                {
249 + crlf:                           assert(message);
250 +
251 +                                        message = realloc(message, ++size * sizeof (char));
252 +
253 +                                        memcpy(message + size - 2, "\r\n", 2);
254 +                                }
255 +                        }
256 +                }
257 +                while (size_ != 0);
258 +
259 +                if (fclose(assassin_))
260 +                        longjmp(environment, 1);
261 +
262 +                int status;
263 +
264 +                check(waitpid(assassin, &status, 0), environment);
265 +
266 +                STRING message_;
267 +
268 +                INIT(&message_, mail_string, message, size);
269 +                mcheck((void *)mail_append_full(streams[0], "INBOX", "\\Seen", NIL, &message_), environment);
270 +                free(message);
271 +        }
272 +
273 +        streams[0] = mcheck(mail_open(streams[0], NEGATIVE, debug ? OP_DEBUG : 0), environment);
274 +
275 +        printf("    %u message(s) delivered.\n", count);
276 + }
277 +
278 + void delete()
279 + {
280 +        char *mailboxes[] = { NEGATIVE, POSITIVE };
281 +
282 +        for (char **mailbox = mailboxes; mailbox != mailboxes + sizeof (mailboxes) / sizeof (*mailboxes); ++mailbox)
283 +        {
284 +                printf("\nDeleting messages from the %s mailbox:\n", *mailbox);
285 +
286 +                const unsigned long *messages_ = messages[mailbox - mailboxes];
287 +                const size_t count = counts[mailbox - mailboxes];
288 +                char *sequence = calloc(1, sizeof (char));
289 +                size_t size = 1;
290 +
291 +                for (size_t index = 0; index != count; ++index)
292 +                {
293 +                        char *message;
294 +
295 +                        asprintf(&message, "%lu%s", messages_[index], index + 1 != count ? "," : "");
296 +
297 +                        sequence = realloc(sequence, (size += strlen(message)) * sizeof (char));
298 +
299 +                        strlcat(sequence, message, size);
300 +                        free(message);
301 +                }
302 +
303 +                mail_setflag_full(streams[mailbox - mailboxes], sequence, "\\Deleted", ST_UID | ST_SILENT);
304 +                free(sequence);
305 +                printf("    %u message(s) marked deleted.\n", count);
306 +        }
307 + }
308 +
309   int main(int argc, char *argv[])
310   {
311          int exception;
# Line 197 | Line 335 | int main(int argc, char *argv[])
335                  else
336                          return printf("Usage: %s [-debug]\n", argv[0]), 1;
337  
338 <        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");
338 >        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");
339 >
340 >        check(sigemptyset(&set), environment);
341 >        check(sigaddset(&set, SIGHUP), environment);
342 >        check(sigaddset(&set, SIGINT), environment);
343  
344   #       include <c-client/linkage.c>
345  
346          streams[0] = mcheck(mail_open(NIL, NEGATIVE, debug ? OP_DEBUG : 0), environment);
347          streams[1] = mcheck(mail_open(NIL, POSITIVE, debug ? OP_DEBUG : 0), environment);
348  
349 <        learn(environment);
349 >        learn();
350 >        deliver();
351 >        delete();
352          mail_close(streams[0]);
353          mail_close(streams[1]);
354 +        free(messages[0]);
355 +        free(messages[1]);
356  
357          return 0;
358   }
# Line 224 | Line 370 | void mm_searched(MAILSTREAM *stream, uns
370                          assert(messages[index]);
371  
372                          messages[index][counts[index] - 1] = number;
373 +
374 +                        break;
375                  }
376   }
377  
# Line 248 | Line 396 | void mm_login(NETMBX *mb, char *user, ch
396  
397   void mm_critical(MAILSTREAM *stream)
398   {
399 <        fprintf(stderr, "critical\n");
399 >        if (!critical++)
400 >                check(sigprocmask(SIG_BLOCK, &set, NULL), environment);
401   }
402  
403   void mm_nocritical(MAILSTREAM *stream)
404   {
405 <        fprintf(stderr, "nocritical\n");
405 >        if (!--critical)
406 >                check(sigprocmask(SIG_UNBLOCK, &set, NULL), environment);
407   }
408  
409   long mm_diskerror(MAILSTREAM *stream, long errcode, long serious)

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines