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 816 by douglas, 2006-07-03T19:12:17-07:00 vs.
Revision 827 by douglas, 2006-07-06T01:41:14-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 17 | Line 17
17   #define NEGATIVE "Spam/False Negative"
18   #define POSITIVE "Spam/False Positive"
19  
20 < #define SED "/usr/bin/sed"
21 < #define ASSASSIN "/usr/local/bin/spamassassin"
20 > /*#define SED "/usr/bin/sed"
21 > #define ASSASSIN "/usr/local/bin/spamassassin"*/
22 > #define SPAMC "/usr/local/bin/spamc"
23 > #define SPAMD "/var/run/spamd/spamd.sock"
24  
25 < #define INDENT "s/^/    /"
26 < #define PERIOD "s/[^.]$/&./"
25 > /*#define INDENT "s/^/    /"
26 > #define PERIOD "s/[^.]$/&./"*/
27  
28   #define TEMP "/tmp/SpamUpdate.XXXXXX"
29  
30   static jmp_buf environment;
31   static char *error = NULL;
32   static bool debug = false;
33 + static sigset_t set;
34   static MAILSTREAM *streams[2];
35 + static uint8_t critical = 0;
36   static unsigned long *messages[] = { NULL, NULL };
37   static size_t counts[] = { 0, 0 };
38  
# Line 40 | Line 44 | static int check(int value, jmp_buf envi
44          return value;
45   }
46  
47 < static char *fcheck(char *value, FILE *stream, jmp_buf environment)
47 > /*static char *fcheck(char *value, FILE *stream, jmp_buf environment)
48   {
49          if (!value)
50          {
# Line 58 | Line 62 | static char *fcheck(char *value, FILE *s
62          }
63  
64          return value;
65 < }
65 > }*/
66  
67   static void *mcheck(void *value, jmp_buf environment)
68   {
# Line 68 | Line 72 | static void *mcheck(void *value, jmp_buf
72          return value;
73   }
74  
71 /*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
75   static void learn()
76   {
77 <        typedef struct { const char *verb, *args, *mailbox; } Job;
77 >        typedef struct { const char *verb, *learn, *collab, *mailbox; } Job;
78          
79 <        Job jobs[] = { { .verb = "reporting", .args = "-rR", .mailbox = NEGATIVE }, { .verb = "revoking", .args = "-kW", .mailbox = POSITIVE } };
79 >        Job jobs[] = { { .verb = "report", .learn = "spam", .collab = "report", .mailbox = NEGATIVE }, { .verb = "revok", .learn = "ham", .collab = "revoke", .mailbox = POSITIVE } };
80  
81          for (Job *job = jobs; job != jobs + sizeof (jobs) / sizeof (*jobs); ++job)
82          {
83 <                printf("\nLearning and %s from the %s mailbox:\n", job->verb, job->mailbox);
83 >                printf("\nLearning and %sing from the %s mailbox:\n", job->verb, job->mailbox);
84  
85                  SEARCHPGM search = { .undeleted = 1 };
86                  
87                  mail_search_full(streams[job - jobs], NIL, &search, SE_UID);
88  
89 <                /*unsigned long *messages_ = messages[job - jobs];
90 <                size_t count = counts[job - jobs];
91 <                char files[count][sizeof (TEMP) / sizeof (char)];
89 >                const unsigned long *messages_ = messages[job - jobs];
90 >                const size_t count = counts[job - jobs];
91 >                size_t learned = 0;
92  
93                  for (size_t index = 0; index != count; ++index)
94                  {
95                          unsigned long size;
96                          char *header = mcheck(mail_fetchheader_full(streams[job - jobs], messages_[index], NIL, &size, FT_UID), environment);
97 +                        char file[sizeof (TEMP) / sizeof (char)] = TEMP;
98 +                        int file_ = check(mkstemp(file), environment);
99  
100 <                        strcpy(files[index], TEMP);
108 <
109 <                        int file = check(mkstemp(files[index]), environment);
110 <
111 <                        check(write(file, header, size), environment);
100 >                        check(write(file_, header, size), environment);
101  
102                          char *text = mcheck(mail_fetchtext_full(streams[job - jobs], messages_[index], &size, FT_UID), environment);
103  
104 <                        check(write(file, text, size), environment);
105 <                        check(close(file), environment);
117 <                }
104 >                        check(write(file_, text, size), environment);
105 >                        check(lseek(file_, 0, SEEK_SET), environment);
106  
107 <                int pipe_[2];
107 >                        pid_t learn;
108  
109 <                check(pipe(pipe_), environment);
109 >                        if (!(learn = check(fork(), environment)))
110 >                        {
111 >                                check(dup2(file_, 0), environment);
112 >                                check(execl(SPAMC, "spamc", "-L", job->learn, "-U", SPAMD, NULL), environment);
113 >                        }
114  
115 <                pid_t assassin;
115 >                        pid_t collab;
116  
117 <                if (!(assassin = check(fork(), environment)))
126 <                {
127 <                        check(dup2(pipe_[1], 1), environment);
128 <                        check(close(pipe_[0]), environment);
129 <
130 <                        const char *args[count ? count + 3 : 5];
131 <                        
132 <                        args[0] = "spamassassin";
133 <                        args[1] = job->args;
134 <
135 <                        if (count)
136 <                                for (size_t index = 0; index != count; ++index)
137 <                                        args[index + 2] = files[index];
138 <                        else
117 >                        if (!(collab = check(fork(), environment)))
118                          {
119 <                                args[2] = "--mbox";
120 <                                args[3] = "/dev/null";
119 >                                check(dup2(file_, 0), environment);
120 >                                check(execl(SPAMC, "spamc", "-L", job->collab, "-U", SPAMD, NULL), environment);
121                          }
122  
123 <                        args[count ? count + 2 : 4] = NULL;
123 >                        check(close(file_), environment);
124 >                        check(unlink(file), environment);
125  
126 <                        check(execv(ASSASSIN, (char *const *)args), environment);
147 <                }
126 >                        int status;
127  
128 <                check(close(pipe_[1]), environment);
128 >                        check(waitpid(learn, &status, 0), environment);
129  
130 <                pid_t sed;
130 >                        if (WEXITSTATUS(status) == 5)
131 >                                ++learned;
132  
133 <                if (!(sed = check(fork(), environment)))
154 <                {
155 <                        check(dup2(pipe_[0], 0), environment);
156 <                        check(execl(SED, "sed", "-e", INDENT, "-e", PERIOD, NULL), environment);
133 >                        check(waitpid(collab, &status, 0), environment);
134                  }
135  
136 <                check(close(pipe_[0]), environment);
160 <
161 <                int status;
162 <
163 <                check(waitpid(assassin, &status, 0), environment);
164 <                check(waitpid(sed, &status, 0), environment);
165 <
166 <                for (size_t index = 0; index != count; ++index)
167 <                        check(unlink(files[index]), environment);*/
136 >                printf("    %u message(s) learned and %u message(s) %sed.\n", learned, count, job->verb);
137          }
138   }
139  
140 < static void deliver()
140 > // XXX: this is going to be moved to a deliver daemon that will run more often
141 > /*static void deliver()
142   {
143          printf("\nDelivering messages from the " POSITIVE " mailbox:\n");
144  
145 <        unsigned long *messages_ = messages[1];
146 <        size_t count = counts[1];
145 >        const unsigned long *messages_ = messages[1];
146 >        const size_t count = counts[1];
147 >
148          streams[0] = mcheck(mail_open(streams[0], "INBOX", (debug ? OP_DEBUG : 0) | OP_SHORTCACHE), environment);
149  
150          for (int index = 0; index != count; ++index)
# Line 228 | Line 199 | static void deliver()
199                          {
200                                  if (size_ == 1)
201                                  {
202 +                                        assert(*line == '\n');
203 +
204                                          header_ = false;
205  
206                                          goto crlf;
# Line 263 | Line 236 | crlf:                          assert(message);
236          streams[0] = mcheck(mail_open(streams[0], NEGATIVE, debug ? OP_DEBUG : 0), environment);
237  
238          printf("    %u message(s) delivered.\n", count);
239 + }*/
240 +
241 + void delete()
242 + {
243 +        char *mailboxes[] = { NEGATIVE, POSITIVE };
244 +
245 +        for (char **mailbox = mailboxes; mailbox != mailboxes + sizeof (mailboxes) / sizeof (*mailboxes); ++mailbox)
246 +        {
247 +                printf("\nDeleting messages from the %s mailbox:\n", *mailbox);
248 +
249 +                const unsigned long *messages_ = messages[mailbox - mailboxes];
250 +                const size_t count = counts[mailbox - mailboxes];
251 +                char *sequence = calloc(1, sizeof (char));
252 +                size_t size = 1;
253 +
254 +                for (size_t index = 0; index != count; ++index)
255 +                {
256 +                        char *message;
257 +
258 +                        asprintf(&message, "%lu%s", messages_[index], index + 1 != count ? "," : "");
259 +
260 +                        sequence = realloc(sequence, (size += strlen(message)) * sizeof (char));
261 +
262 +                        strlcat(sequence, message, size);
263 +                        free(message);
264 +                }
265 +
266 +                mail_setflag_full(streams[mailbox - mailboxes], sequence, "\\Deleted", ST_UID | ST_SILENT);
267 +                free(sequence);
268 +                printf("    %u message(s) marked deleted.\n", count);
269 +        }
270   }
271  
272   int main(int argc, char *argv[])
# Line 294 | Line 298 | int main(int argc, char *argv[])
298                  else
299                          return printf("Usage: %s [-debug]\n", argv[0]), 1;
300  
301 <        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");
301 >        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");
302 >
303 >        check(sigemptyset(&set), environment);
304 >        check(sigaddset(&set, SIGHUP), environment);
305 >        check(sigaddset(&set, SIGINT), environment);
306  
307   #       include <c-client/linkage.c>
308  
# Line 302 | Line 310 | int main(int argc, char *argv[])
310          streams[1] = mcheck(mail_open(NIL, POSITIVE, debug ? OP_DEBUG : 0), environment);
311  
312          learn();
313 <        deliver();
313 >        //deliver();
314 >        delete();
315          mail_close(streams[0]);
316          mail_close(streams[1]);
317          free(messages[0]);
# Line 324 | Line 333 | void mm_searched(MAILSTREAM *stream, uns
333                          assert(messages[index]);
334  
335                          messages[index][counts[index] - 1] = number;
336 +
337 +                        break;
338                  }
339   }
340  
# Line 348 | Line 359 | void mm_login(NETMBX *mb, char *user, ch
359  
360   void mm_critical(MAILSTREAM *stream)
361   {
362 <        fprintf(stderr, "critical\n");
362 >        if (!critical++)
363 >                check(sigprocmask(SIG_BLOCK, &set, NULL), environment);
364   }
365  
366   void mm_nocritical(MAILSTREAM *stream)
367   {
368 <        fprintf(stderr, "nocritical\n");
368 >        if (!--critical)
369 >                check(sigprocmask(SIG_UNBLOCK, &set, NULL), environment);
370   }
371  
372   long mm_diskerror(MAILSTREAM *stream, long errcode, long serious)

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines