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 819 by douglas, 2006-07-03T22:15:40-07:00 vs.
Revision 833 by douglas, 2006-07-07T07:27:48-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  
45 static char *fcheck(char *value, FILE *stream, jmp_buf environment)
46 {
47        if (!value)
48        {
49                if (ferror(stream))
50                        longjmp(environment, 1);
51                else
52                {
53                        clearerr(stream);
54
55                        if (stream == stdin)
56                                printf("\n");
57
58                        return "";
59                }
60        }
61
62        return value;
63 }
64
42   static void *mcheck(void *value, jmp_buf environment)
43   {
44          if (value == NIL)
# Line 72 | Line 49 | static void *mcheck(void *value, jmp_buf
49  
50   static void learn()
51   {
52 <        typedef struct { const char *verb, *args, *mailbox; } Job;
52 >        typedef struct { const char *verb, *learn, *collab, *mailbox; } Job;
53          
54 <        Job jobs[] = { { .verb = "reporting", .args = "-rR", .mailbox = NEGATIVE }, { .verb = "revoking", .args = "-kW", .mailbox = POSITIVE } };
54 >        Job jobs[] = { { .verb = "report", .learn = "spam", .collab = "report", .mailbox = NEGATIVE }, { .verb = "revok", .learn = "ham", .collab = "revoke", .mailbox = POSITIVE } };
55  
56          for (Job *job = jobs; job != jobs + sizeof (jobs) / sizeof (*jobs); ++job)
57          {
58 <                printf("\nLearning and %s from the %s mailbox:\n", job->verb, job->mailbox);
58 >                printf("\nLearning and %sing from the %s mailbox:\n", job->verb, job->mailbox);
59  
60                  SEARCHPGM search = { .undeleted = 1 };
61                  
# Line 86 | Line 63 | static void learn()
63  
64                  const unsigned long *messages_ = messages[job - jobs];
65                  const size_t count = counts[job - jobs];
66 <                char files[count][sizeof (TEMP) / sizeof (char)];
66 >                size_t learned = 0;
67  
68                  for (size_t index = 0; index != count; ++index)
69                  {
70                          unsigned long size;
71 <                        char *header = mcheck(mail_fetchheader_full(streams[job - jobs], messages_[index], NIL, &size, FT_UID), environment);
72 <
73 <                        strcpy(files[index], TEMP);
71 >                        char *message = mcheck(mail_fetch_message(streams[job - jobs], messages_[index], &size, FT_UID), environment);
72 >                        char file[sizeof (TEMP) / sizeof (char)] = TEMP;
73 >                        int file_ = check(mkstemp(file), environment);
74  
75 <                        int file = check(mkstemp(files[index]), environment);
75 >                        check(write(file_, message, size * sizeof (char)), environment);
76 >                        check(lseek(file_, 0, SEEK_SET), environment);
77  
78 <                        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 <                }
107 <
108 <                int pipe_[2];
109 <
110 <                check(pipe(pipe_), 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);
78 >                        pid_t learn;
79  
80 <                        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
80 >                        if (!(learn = check(fork(), environment)))
81                          {
82 <                                args[2] = "--mbox";
83 <                                args[3] = "/dev/null";
82 >                                check(dup2(file_, 0), environment);
83 >                                check(execl(SPAMC, "spamc", "-L", job->learn, "-U", SPAMD, NULL), environment);
84                          }
85  
86 <                        args[count ? count + 2 : 4] = NULL;
134 <
135 <                        check(execv(ASSASSIN, (char *const *)args), environment);
136 <                }
137 <
138 <                check(close(pipe_[1]), environment);
139 <
140 <                pid_t sed;
141 <
142 <                if (!(sed = check(fork(), environment)))
143 <                {
144 <                        check(dup2(pipe_[0], 0), environment);
145 <                        check(execl(SED, "sed", "-e", INDENT, "-e", PERIOD, NULL), environment);
146 <                }
147 <
148 <                check(close(pipe_[0]), environment);
149 <
150 <                int status;
151 <
152 <                check(waitpid(assassin, &status, 0), environment);
153 <                check(waitpid(sed, &status, 0), environment);
154 <
155 <                for (size_t index = 0; index != count; ++index)
156 <                        check(unlink(files[index]), 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);
86 >                        pid_t collab;
87  
88 <                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_)
88 >                        if (!(collab = check(fork(), environment)))
89                          {
90 <                                if (size_ == 1)
91 <                                {
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 <                                }
90 >                                check(dup2(file_, 0), environment);
91 >                                check(execl(SPAMC, "spamc", "-L", job->collab, "-U", SPAMD, NULL), environment);
92                          }
238                }
239                while (size_ != 0);
93  
94 <                if (fclose(assassin_))
95 <                        longjmp(environment, 1);
94 >                        check(close(file_), environment);
95 >                        check(unlink(file), environment);
96  
97 <                int status;
97 >                        int status;
98  
99 <                check(waitpid(assassin, &status, 0), environment);
99 >                        check(waitpid(learn, &status, 0), environment);
100  
101 <                STRING message_;
102 <
250 <                INIT(&message_, mail_string, message, size);
251 <                mcheck((void *)mail_append_full(streams[0], "INBOX", "\\Seen", NIL, &message_), environment);
252 <                free(message);
253 <        }
101 >                        if (WEXITSTATUS(status) == 5)
102 >                                ++learned;
103  
104 <        streams[0] = mcheck(mail_open(streams[0], NEGATIVE, debug ? OP_DEBUG : 0), environment);
104 >                        check(waitpid(collab, &status, 0), environment);
105 >                }
106  
107 <        printf("    %u message(s) delivered.\n", count);
107 >                printf("    %u message(s) learned and %u message(s) %sed.\n", learned, count, job->verb);
108 >        }
109   }
110  
111   void delete()
# Line 329 | Line 180 | int main(int argc, char *argv[])
180          streams[1] = mcheck(mail_open(NIL, POSITIVE, debug ? OP_DEBUG : 0), environment);
181  
182          learn();
332        deliver();
183          delete();
184          mail_close(streams[0]);
185          mail_close(streams[1]);
# Line 339 | Line 189 | int main(int argc, char *argv[])
189          return 0;
190   }
191  
192 < void mm_flags(MAILSTREAM *stream, unsigned long number) {}
193 < void mm_status(MAILSTREAM *stream, char *mailbox, MAILSTATUS *status) {}
192 > void mm_flags(MAILSTREAM *stream, unsigned long number)
193 > {
194 >        if (debug)
195 >                fprintf(stderr, "flags: %lu\n", number);
196 > }
197 >
198 > void mm_status(MAILSTREAM *stream, char *mailbox, MAILSTATUS *status)
199 > {
200 >        if (debug)
201 >        {
202 >                fprintf(stderr, "status: %s\n", mailbox);
203 >
204 >                if (status->flags & SA_MESSAGES)
205 >                        fprintf(stderr, "   messages: %lu\n", status->messages);
206 >
207 >                if (status->flags & SA_RECENT)
208 >                        fprintf(stderr, "   recent: %lu\n", status->recent);
209 >
210 >                if (status->flags & SA_UNSEEN)
211 >                        fprintf(stderr, "   unseen: %lu\n", status->unseen);
212 >
213 >                if (status->flags & SA_UIDNEXT)
214 >                        fprintf(stderr, "   uid next: %lu\n", status->uidnext);
215 >
216 >                if (status->flags & SA_UIDVALIDITY)
217 >                        fprintf(stderr, "   uid validity: %lu\n", status->uidvalidity);
218 >        }
219 > }
220  
221   void mm_searched(MAILSTREAM *stream, unsigned long number)
222   {
# Line 357 | Line 233 | void mm_searched(MAILSTREAM *stream, uns
233                  }
234   }
235  
236 < void mm_exists(MAILSTREAM *stream, unsigned long number) {}
236 > void mm_exists(MAILSTREAM *stream, unsigned long number)
237 > {
238 >        if (debug)
239 >                fprintf(stderr, "exists: %lu\n", number);
240 > }
241 >
242   void mm_expunged(MAILSTREAM *stream, unsigned long number) {}
243   void mm_list(MAILSTREAM *stream, int delim, char *name, long attrib) {}
244   void mm_lsub(MAILSTREAM *stream, int delim, char *name, long attrib) {}
245 < void mm_notify(MAILSTREAM *stream, char *string, long errflg) {}
245 >
246 > void mm_notify(MAILSTREAM *stream, char *string, long errflg)
247 > {
248 >        if (debug)
249 >                fprintf(stderr, "%li: %s\n", errflg, string);
250 > }
251  
252   void mm_log(char *string, long errflg)
253   {
254 +        if (debug)
255 +                fprintf(stderr, "%li: %s\n", errflg, string);
256 +
257          if (errflg == ERROR)
258                  asprintf(&error, "%s", string);
259   }
# Line 390 | Line 279 | void mm_nocritical(MAILSTREAM *stream)
279  
280   long mm_diskerror(MAILSTREAM *stream, long errcode, long serious)
281   {
282 <        fprintf(stderr, "diskerror:\n   errcode = %li\n   serious = %li\n", errcode, serious);
282 >        fprintf(stderr, "diskerror: %li%s\n", errcode, serious ? " serious" : "");
283  
284          return 1;
285   }
286  
287   void mm_fatal(char *string)
288   {
289 <        fprintf(stderr, "fatal:\n   string = %s\n", string);
289 >        fprintf(stderr, "fatal: %s\n", string);
290   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines