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 829 by douglas, 2006-07-06T23:50:18-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);
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 <                }
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 between[2];
75 >                        check(write(file_, message, size * sizeof (char)), environment);
76 >                        check(lseek(file_, 0, SEEK_SET), environment);
77  
78 <                check(pipe(between), environment);
78 >                        pid_t learn;
79  
80 <                pid_t assassin;
113 <
114 <                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
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(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);
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 <                        fwrite(line, size, sizeof (char), stdout);
165 <                }
166 <                while (size != 0);
167 <
168 <                if (fclose(sed_))
169 <                        longjmp(environment, 1);
86 >                        pid_t collab;
87  
88 <                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 < }
180 <
181 < static void deliver()
182 < {
183 <        printf("\nDelivering messages from the " POSITIVE " mailbox:\n");
184 <
185 <        const unsigned long *messages_ = messages[1];
186 <        const size_t count = counts[1];
187 <
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);
217 <
218 <                check(write(out[1], text, size), environment);
219 <                check(close(out[1]), environment);
220 <
221 <                FILE *assassin_ = fdopen(in[0], "r");
222 <                size_t size_;
223 <                bool header_ = true;
224 <                char *message = NULL;
225 <
226 <                size = 0;
227 <
228 <                do
229 <                {
230 <                        char *line = fcheck(fgetln(assassin_, &size_), assassin_, environment);
231 <
232 <                        message = message ? realloc(message, (size + size_) * sizeof (char)) : malloc((size + size_) * sizeof (char));
233 <
234 <                        memcpy(message + size, line, size_);
235 <
236 <                        size += size_;
237 <
238 <                        if (header_)
88 >                        if (!(collab = check(fork(), environment)))
89                          {
90 <                                if (size_ == 1)
91 <                                {
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);
253 <
254 <                                        message = realloc(message, ++size * sizeof (char));
255 <
256 <                                        memcpy(message + size - 2, "\r\n", 2);
257 <                                }
90 >                                check(dup2(file_, 0), environment);
91 >                                check(execl(SPAMC, "spamc", "-L", job->collab, "-U", SPAMD, NULL), environment);
92                          }
259                }
260                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 <
271 <                INIT(&message_, mail_string, message, size);
272 <                mcheck((void *)mail_append_full(streams[0], "INBOX", "\\Seen", NIL, &message_), environment);
273 <                free(message);
274 <        }
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 350 | Line 180 | int main(int argc, char *argv[])
180          streams[1] = mcheck(mail_open(NIL, POSITIVE, debug ? OP_DEBUG : 0), environment);
181  
182          learn();
353        deliver();
183          delete();
184          mail_close(streams[0]);
185          mail_close(streams[1]);
# Line 382 | Line 211 | void mm_exists(MAILSTREAM *stream, unsig
211   void mm_expunged(MAILSTREAM *stream, unsigned long number) {}
212   void mm_list(MAILSTREAM *stream, int delim, char *name, long attrib) {}
213   void mm_lsub(MAILSTREAM *stream, int delim, char *name, long attrib) {}
214 +
215   void mm_notify(MAILSTREAM *stream, char *string, long errflg) {}
216  
217   void mm_log(char *string, long errflg)
218   {
219 +        if (debug)
220 +                fprintf(stderr, "%li: %s\n", errflg, string);
221 +
222          if (errflg == ERROR)
223                  asprintf(&error, "%s", string);
224   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines