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 822 by douglas, 2006-07-04T16:57:34-07:00 vs.
Revision 836 by douglas, 2006-07-10T00:55:02-07:00

# 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"
22 <
23 < #define INDENT "s/^/    /"
24 < #define PERIOD "s/[^.]$/&./"
20 > #define SPAMC "/usr/local/bin/spamc"
21 > #define SPAMD "/var/run/spamd/spamd.sock"
22  
23   #define TEMP "/tmp/SpamUpdate.XXXXXX"
24  
# Line 42 | Line 39 | static int check(int value, jmp_buf envi
39          return value;
40   }
41  
42 + static void *mcheck(void *value, jmp_buf environment)
43 + {
44 +        if (value == NIL)
45 +                longjmp(environment, 2);
46 +
47 +        return value;
48 + }
49 +
50   static char *fcheck(char *value, FILE *stream, jmp_buf environment)
51   {
52          if (!value)
# Line 62 | Line 67 | static char *fcheck(char *value, FILE *s
67          return value;
68   }
69  
65 static void *mcheck(void *value, jmp_buf environment)
66 {
67        if (value == NIL)
68                longjmp(environment, 2);
69
70        return value;
71 }
72
70   static void learn()
71   {
72 <        typedef struct { const char *verb, *args, *mailbox; } Job;
72 >        typedef struct { const char *verb, *learn, *collab, *mailbox; } Job;
73          
74 <        Job jobs[] = { { .verb = "reporting", .args = "-rR", .mailbox = NEGATIVE }, { .verb = "revoking", .args = "-kW", .mailbox = POSITIVE } };
74 >        Job jobs[] = { { .verb = "report", .learn = "spam", .collab = "report", .mailbox = NEGATIVE }, { .verb = "revok", .learn = "ham", .collab = "revoke", .mailbox = POSITIVE } };
75  
76          for (Job *job = jobs; job != jobs + sizeof (jobs) / sizeof (*jobs); ++job)
77          {
78 <                printf("\nLearning and %s from the %s mailbox:\n", job->verb, job->mailbox);
78 >                printf("\nLearning and %sing from the %s mailbox:\n", job->verb, job->mailbox);
79  
80                  SEARCHPGM search = { .undeleted = 1 };
81                  
# Line 86 | Line 83 | static void learn()
83  
84                  const unsigned long *messages_ = messages[job - jobs];
85                  const size_t count = counts[job - jobs];
86 <                char files[count][sizeof (TEMP) / sizeof (char)];
86 >                size_t learned = 0, collabed = 0;
87  
88                  for (size_t index = 0; index != count; ++index)
89                  {
90                          unsigned long size;
91 <                        char *header = mcheck(mail_fetchheader_full(streams[job - jobs], messages_[index], NIL, &size, FT_UID), environment);
92 <
93 <                        strcpy(files[index], TEMP);
97 <
98 <                        int file = check(mkstemp(files[index]), environment);
99 <
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);
106 <                }
91 >                        char *message = mcheck(mail_fetch_message(streams[job - jobs], messages_[index], &size, FT_UID), environment);
92 >                        char file[sizeof (TEMP) / sizeof (char)] = TEMP;
93 >                        int file_ = check(mkstemp(file), environment);
94  
95 <                int between[2];
95 >                        check(write(file_, message, size * sizeof (char)), environment);
96 >                        check(lseek(file_, 0, SEEK_SET), environment);
97  
98 <                check(pipe(between), environment);
98 >                        pid_t learn;
99 >                        int pipe_[2][2];
100  
101 <                pid_t assassin;
101 >                        check(pipe(pipe_[0]), environment);
102  
103 <                if (!(assassin = check(fork(), environment)))
115 <                {
116 <                        check(dup2(between[1], 1), environment);
117 <                        check(close(between[0]), environment);
118 <
119 <                        const char *args[count ? count + 3 : 5];
120 <                        
121 <                        args[0] = "spamassassin";
122 <                        args[1] = job->args;
123 <
124 <                        if (count)
125 <                                for (size_t index = 0; index != count; ++index)
126 <                                        args[index + 2] = files[index];
127 <                        else
103 >                        if (!(learn = check(fork(), environment)))
104                          {
105 <                                args[2] = "--mbox";
106 <                                args[3] = "/dev/null";
105 >                                check(dup2(file_, 0), environment);
106 >                                check(dup2(pipe_[0][1], 1), environment);
107 >                                check(close(pipe_[0][0]), environment);
108 >                                check(execl(SPAMC, "spamc", "-L", job->learn, "-U", SPAMD, NULL), environment);
109                          }
110  
111 <                        args[count ? count + 2 : 4] = NULL;
134 <
135 <                        check(execv(ASSASSIN, (char *const *)args), environment);
136 <                }
137 <
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(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(between[0]), environment);
155 <                check(close(in[1]), environment);
111 >                        check(close(pipe_[0][1]), environment);
112  
113 <                FILE *sed_ = fdopen(in[0], "r");
158 <                size_t size;
113 >                        pid_t collab;
114  
115 <                do
161 <                {
162 <                        char *line = fcheck(fgetln(sed_, &size), sed_, environment);
163 <
164 <                        fwrite(line, size, sizeof (char), stdout);
165 <                }
166 <                while (size != 0);
167 <
168 <                if (fclose(sed_))
169 <                        longjmp(environment, 1);
170 <
171 <                int status;
172 <
173 <                check(waitpid(assassin, &status, 0), environment);
174 <                check(waitpid(sed, &status, 0), environment);
175 <
176 <                for (size_t index = 0; index != count; ++index)
177 <                        check(unlink(files[index]), environment);
178 <        }
179 < }
115 >                        check(pipe(pipe_[1]), environment);
116  
117 < static void deliver()
118 < {
119 <        printf("\nDelivering messages from the " POSITIVE " mailbox:\n");
120 <
121 <        const unsigned long *messages_ = messages[1];
122 <        const size_t count = counts[1];
123 <
188 <        streams[0] = mcheck(mail_open(streams[0], "INBOX", (debug ? OP_DEBUG : 0) | OP_SHORTCACHE), environment);
189 <
190 <        for (int index = 0; index != count; ++index)
191 <        {
192 <                int out[2], in[2];
193 <
194 <                check(pipe(out), environment);
195 <                check(pipe(in), environment);
196 <
197 <                pid_t assassin;
198 <
199 <                if (!(assassin = check(fork(), environment)))
200 <                {
201 <                        check(dup2(out[0], 0), environment);
202 <                        check(close(out[1]), environment);
203 <                        check(dup2(in[1], 1), environment);
204 <                        check(close(in[0]), environment);
205 <                        check(execl(ASSASSIN, "spamassassin", "-d", NULL), environment);
206 <                }
207 <
208 <                check(close(out[0]), environment);
209 <                check(close(in[1]), environment);
210 <
211 <                unsigned long size;
212 <                char *header = mcheck(mail_fetchheader_full(streams[1], messages_[index], NIL, &size, FT_UID), environment);
213 <
214 <                check(write(out[1], header, size), environment);
215 <
216 <                char *text = mcheck(mail_fetchtext_full(streams[1], messages_[index], &size, FT_UID), environment);
117 >                        if (!(collab = check(fork(), environment)))
118 >                        {
119 >                                check(dup2(file_, 0), environment);
120 >                                check(dup2(pipe_[1][1], 1), environment);
121 >                                check(close(pipe_[1][0]), environment);
122 >                                check(execl(SPAMC, "spamc", "-L", job->collab, "-U", SPAMD, NULL), environment);
123 >                        }
124  
125 <                check(write(out[1], text, size), environment);
126 <                check(close(out[1]), environment);
125 >                        check(close(file_), environment);
126 >                        check(unlink(file), environment);
127 >                        check(close(pipe_[1][1]), environment);
128  
129 <                FILE *assassin_ = fdopen(in[0], "r");
130 <                size_t size_;
131 <                bool header_ = true;
224 <                char *message = NULL;
129 >                        FILE *learn_ = fdopen(pipe_[0][0], "r");
130 >                        size_t size_;
131 >                        char *line = fcheck(fgetln(learn_, &size_), learn_, environment);
132  
133 <                size = 0;
133 >                        if (strncmp(line, "Message successfully un/learned\n", size_) == 0)
134 >                                ++learned;
135  
136 <                do
229 <                {
230 <                        char *line = fcheck(fgetln(assassin_, &size_), assassin_, environment);
136 >                        fclose(learn_);
137  
138 <                        message = message ? realloc(message, (size + size_) * sizeof (char)) : malloc((size + size_) * sizeof (char));
138 >                        FILE *collab_ = fdopen(pipe_[1][0], "r");
139  
140 <                        memcpy(message + size, line, size_);
140 >                        line = fcheck(fgetln(collab_, &size_), collab_, environment);
141  
142 <                        size += size_;
142 >                        if (strncmp(line, "Message successfully reported/revoked\n", size_) == 0)
143 >                                ++collabed;
144  
145 <                        if (header_)
239 <                        {
240 <                                if (size_ == 1)
241 <                                {
242 <                                        assert(*line == '\n');
243 <
244 <                                        header_ = false;
245 <
246 <                                        goto crlf;
247 <                                }
248 <                                else if (size_ == 2 && !memcmp(line, "\r\n", 2))
249 <                                        header_ = false;
250 <                                else if (!(size_ > 2 && !memcmp(line + size_ - 2, "\r\n", 2)))
251 <                                {
252 < crlf:                           assert(message);
145 >                        fclose(collab_);
146  
147 <                                        message = realloc(message, ++size * sizeof (char));
147 >                        int status;
148  
149 <                                        memcpy(message + size - 2, "\r\n", 2);
150 <                                }
258 <                        }
149 >                        check(waitpid(learn, &status, 0), environment);
150 >                        check(waitpid(collab, &status, 0), environment);
151                  }
260                while (size_ != 0);
261
262                if (fclose(assassin_))
263                        longjmp(environment, 1);
264
265                int status;
266
267                check(waitpid(assassin, &status, 0), environment);
152  
153 <                STRING message_;
270 <
271 <                INIT(&message_, mail_string, message, size);
272 <                mcheck((void *)mail_append_full(streams[0], "INBOX", "\\Seen", NIL, &message_), environment);
273 <                free(message);
153 >                printf("    %u message(s) learned and %u message(s) %sed.\n", learned, collabed, job->verb);
154          }
275
276        streams[0] = mcheck(mail_open(streams[0], NEGATIVE, debug ? OP_DEBUG : 0), environment);
277
278        printf("    %u message(s) delivered.\n", count);
155   }
156  
157   void delete()
# Line 350 | Line 226 | int main(int argc, char *argv[])
226          streams[1] = mcheck(mail_open(NIL, POSITIVE, debug ? OP_DEBUG : 0), environment);
227  
228          learn();
353        deliver();
229          delete();
230          mail_close(streams[0]);
231          mail_close(streams[1]);
# Line 360 | Line 235 | int main(int argc, char *argv[])
235          return 0;
236   }
237  
238 < void mm_flags(MAILSTREAM *stream, unsigned long number) {}
239 < void mm_status(MAILSTREAM *stream, char *mailbox, MAILSTATUS *status) {}
238 > void mm_flags(MAILSTREAM *stream, unsigned long number)
239 > {
240 >        if (debug)
241 >                fprintf(stderr, "flags: %lu\n", number);
242 > }
243 >
244 > void mm_status(MAILSTREAM *stream, char *mailbox, MAILSTATUS *status)
245 > {
246 >        if (debug)
247 >        {
248 >                fprintf(stderr, "status: %s\n", mailbox);
249 >
250 >                if (status->flags & SA_MESSAGES)
251 >                        fprintf(stderr, "   messages: %lu\n", status->messages);
252 >
253 >                if (status->flags & SA_RECENT)
254 >                        fprintf(stderr, "   recent: %lu\n", status->recent);
255 >
256 >                if (status->flags & SA_UNSEEN)
257 >                        fprintf(stderr, "   unseen: %lu\n", status->unseen);
258 >
259 >                if (status->flags & SA_UIDNEXT)
260 >                        fprintf(stderr, "   uid next: %lu\n", status->uidnext);
261 >
262 >                if (status->flags & SA_UIDVALIDITY)
263 >                        fprintf(stderr, "   uid validity: %lu\n", status->uidvalidity);
264 >        }
265 > }
266  
267   void mm_searched(MAILSTREAM *stream, unsigned long number)
268   {
# Line 378 | Line 279 | void mm_searched(MAILSTREAM *stream, uns
279                  }
280   }
281  
282 < void mm_exists(MAILSTREAM *stream, unsigned long number) {}
282 > void mm_exists(MAILSTREAM *stream, unsigned long number)
283 > {
284 >        if (debug)
285 >                fprintf(stderr, "exists: %lu\n", number);
286 > }
287 >
288   void mm_expunged(MAILSTREAM *stream, unsigned long number) {}
289   void mm_list(MAILSTREAM *stream, int delim, char *name, long attrib) {}
290   void mm_lsub(MAILSTREAM *stream, int delim, char *name, long attrib) {}
291 < void mm_notify(MAILSTREAM *stream, char *string, long errflg) {}
291 >
292 > void mm_notify(MAILSTREAM *stream, char *string, long errflg)
293 > {
294 >        if (debug)
295 >                fprintf(stderr, "%li: %s\n", errflg, string);
296 > }
297  
298   void mm_log(char *string, long errflg)
299   {
300 +        if (debug)
301 +                fprintf(stderr, "%li: %s\n", errflg, string);
302 +
303          if (errflg == ERROR)
304                  asprintf(&error, "%s", string);
305   }
# Line 411 | Line 325 | void mm_nocritical(MAILSTREAM *stream)
325  
326   long mm_diskerror(MAILSTREAM *stream, long errcode, long serious)
327   {
328 <        fprintf(stderr, "diskerror:\n   errcode = %li\n   serious = %li\n", errcode, serious);
328 >        fprintf(stderr, "diskerror: %li%s\n", errcode, serious ? " serious" : "");
329  
330          return 1;
331   }
332  
333   void mm_fatal(char *string)
334   {
335 <        fprintf(stderr, "fatal:\n   string = %s\n", string);
335 >        fprintf(stderr, "fatal: %s\n", string);
336   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines