Cleanup again and all of this done with one hand !!!
We're moving closer to cleaning the repository and using autoconf and all. But my keyboard quota is almost expired.
Showing
10 changed files
with
1384 additions
and
1201 deletions
... | @@ -23,7 +23,7 @@ | ... | @@ -23,7 +23,7 @@ |
23 | #include <errno.h> | 23 | #include <errno.h> |
24 | 24 | ||
25 | int | 25 | int |
26 | attribute_create (attribute_t *pattr) | 26 | attribute_create (attribute_t *pattr, void *owner) |
27 | { | 27 | { |
28 | attribute_t attr; | 28 | attribute_t attr; |
29 | if (pattr == NULL) | 29 | if (pattr == NULL) |
... | @@ -31,15 +31,18 @@ attribute_create (attribute_t *pattr) | ... | @@ -31,15 +31,18 @@ attribute_create (attribute_t *pattr) |
31 | attr = calloc (1, sizeof(*attr)); | 31 | attr = calloc (1, sizeof(*attr)); |
32 | if (attr == NULL) | 32 | if (attr == NULL) |
33 | return ENOMEM; | 33 | return ENOMEM; |
34 | attr->owner = owner; | ||
34 | *pattr = attr; | 35 | *pattr = attr; |
35 | return 0; | 36 | return 0; |
36 | } | 37 | } |
37 | 38 | ||
38 | void | 39 | void |
39 | attribute_destroy (attribute_t *pattr) | 40 | attribute_destroy (attribute_t *pattr, void *owner) |
40 | { | 41 | { |
41 | if (pattr && *pattr) | 42 | if (pattr && *pattr) |
42 | { | 43 | { |
44 | attribute_t attr = *pattr; | ||
45 | if (attr->owner != owner) | ||
43 | free (*pattr); | 46 | free (*pattr); |
44 | /* loose the link */ | 47 | /* loose the link */ |
45 | *pattr = NULL; | 48 | *pattr = NULL; |
... | @@ -48,68 +51,144 @@ attribute_destroy (attribute_t *pattr) | ... | @@ -48,68 +51,144 @@ attribute_destroy (attribute_t *pattr) |
48 | } | 51 | } |
49 | 52 | ||
50 | int | 53 | int |
54 | attribute_get_flags (attribute_t attr, int *pflags) | ||
55 | { | ||
56 | if (attr->_get_flags) | ||
57 | return attr->_get_flags (attr, pflags); | ||
58 | if (pflags) | ||
59 | *pflags = attr->flags; | ||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | int | ||
64 | attribute_set_flags (attribute_t attr, int flags) | ||
65 | { | ||
66 | if (attr->_set_flags) | ||
67 | return attr->_set_flags (attr, flags); | ||
68 | attr->flags |= flags; | ||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | int | ||
73 | attribute_set_get_flags (attribute_t attr, int (*_get_flags) | ||
74 | (attribute_t, int *), void *owner) | ||
75 | { | ||
76 | if (attr == NULL) | ||
77 | return EINVAL; | ||
78 | if (attr->owner != owner) | ||
79 | return EACCES; | ||
80 | attr->_get_flags = _get_flags; | ||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | int | ||
85 | attribute_set_set_flags (attribute_t attr, int (*_set_flags) | ||
86 | (attribute_t, int), void *owner) | ||
87 | { | ||
88 | if (attr == NULL) | ||
89 | return EINVAL; | ||
90 | if (attr->owner != owner) | ||
91 | return EACCES; | ||
92 | attr->_set_flags = _set_flags; | ||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | int | ||
97 | attribute_set_unset_flags (attribute_t attr, int (*_unset_flags) | ||
98 | (attribute_t, int), void *owner) | ||
99 | { | ||
100 | if (attr == NULL) | ||
101 | return EINVAL; | ||
102 | if (attr->owner != owner) | ||
103 | return EACCES; | ||
104 | attr->_unset_flags = _unset_flags; | ||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | int | ||
51 | attribute_set_seen (attribute_t attr) | 109 | attribute_set_seen (attribute_t attr) |
52 | { | 110 | { |
111 | int status = 0; | ||
53 | if (attr == NULL) | 112 | if (attr == NULL) |
54 | return EINVAL; | 113 | return EINVAL; |
55 | attr->flag |= MU_ATTRIBUTE_SEEN; | 114 | if (attr->_get_flags) |
115 | status = attr->_get_flags (attr, &(attr->flags)); | ||
116 | attr->flags |= MU_ATTRIBUTE_SEEN; | ||
56 | return 0; | 117 | return 0; |
57 | } | 118 | } |
58 | 119 | ||
59 | int | 120 | int |
60 | attribute_set_answered (attribute_t attr) | 121 | attribute_set_answered (attribute_t attr) |
61 | { | 122 | { |
123 | int status = 0; | ||
62 | if (attr == NULL) | 124 | if (attr == NULL) |
63 | return EINVAL; | 125 | return EINVAL; |
64 | attr->flag |= MU_ATTRIBUTE_ANSWERED; | 126 | if (attr->_get_flags) |
127 | status = attr->_get_flags (attr, &(attr->flags)); | ||
128 | attr->flags |= MU_ATTRIBUTE_ANSWERED; | ||
65 | return 0; | 129 | return 0; |
66 | } | 130 | } |
67 | 131 | ||
68 | int | 132 | int |
69 | attribute_set_flagged (attribute_t attr) | 133 | attribute_set_flagged (attribute_t attr) |
70 | { | 134 | { |
135 | int status = 0; | ||
71 | if (attr == NULL) | 136 | if (attr == NULL) |
72 | return EINVAL; | 137 | return EINVAL; |
73 | attr->flag |= MU_ATTRIBUTE_FLAGGED; | 138 | if (attr->_get_flags) |
139 | status = attr->_get_flags (attr, &(attr->flags)); | ||
140 | attr->flags |= MU_ATTRIBUTE_FLAGGED; | ||
74 | return 0; | 141 | return 0; |
75 | } | 142 | } |
76 | 143 | ||
77 | int | 144 | int |
78 | attribute_set_read (attribute_t attr) | 145 | attribute_set_read (attribute_t attr) |
79 | { | 146 | { |
147 | int status = 0; | ||
80 | if (attr == NULL) | 148 | if (attr == NULL) |
81 | return EINVAL; | 149 | return EINVAL; |
82 | attr->flag |= MU_ATTRIBUTE_READ; | 150 | if (attr->_get_flags) |
151 | status = attr->_get_flags (attr, &(attr->flags)); | ||
152 | attr->flags |= MU_ATTRIBUTE_READ; | ||
83 | return 0; | 153 | return 0; |
84 | } | 154 | } |
85 | 155 | ||
86 | int | 156 | int |
87 | attribute_set_deleted (attribute_t attr) | 157 | attribute_set_deleted (attribute_t attr) |
88 | { | 158 | { |
159 | int status = 0; | ||
89 | if (attr == NULL) | 160 | if (attr == NULL) |
90 | return EINVAL; | 161 | return EINVAL; |
91 | attr->flag |= MU_ATTRIBUTE_DELETED; | 162 | if (attr->_get_flags) |
163 | status = attr->_get_flags (attr, &(attr->flags)); | ||
164 | attr->flags |= MU_ATTRIBUTE_DELETED; | ||
92 | return 0; | 165 | return 0; |
93 | } | 166 | } |
94 | 167 | ||
95 | int | 168 | int |
96 | attribute_set_draft (attribute_t attr) | 169 | attribute_set_draft (attribute_t attr) |
97 | { | 170 | { |
171 | int status = 0; | ||
98 | if (attr == NULL) | 172 | if (attr == NULL) |
99 | return EINVAL; | 173 | return EINVAL; |
100 | attr->flag |= MU_ATTRIBUTE_DRAFT; | 174 | if (attr->_get_flags) |
175 | status = attr->_get_flags (attr, &(attr->flags)); | ||
176 | attr->flags |= MU_ATTRIBUTE_DRAFT; | ||
101 | return 0; | 177 | return 0; |
102 | } | 178 | } |
103 | 179 | ||
104 | int | 180 | int |
105 | attribute_set_recent (attribute_t attr) | 181 | attribute_set_recent (attribute_t attr) |
106 | { | 182 | { |
183 | int status = 0; | ||
107 | if (attr == NULL) | 184 | if (attr == NULL) |
108 | return EINVAL; | 185 | return EINVAL; |
186 | if (attr->_get_flags) | ||
187 | status = attr->_get_flags (attr, &(attr->flags)); | ||
109 | if (attr == NULL) | 188 | if (attr == NULL) |
110 | { | 189 | { |
111 | attr->flag &= ~MU_ATTRIBUTE_READ; | 190 | attr->flags &= ~MU_ATTRIBUTE_READ; |
112 | attr->flag &= ~MU_ATTRIBUTE_SEEN; | 191 | attr->flags &= ~MU_ATTRIBUTE_SEEN; |
113 | return 0; | 192 | return 0; |
114 | } | 193 | } |
115 | return EACCES; | 194 | return EACCES; |
... | @@ -118,131 +197,176 @@ attribute_set_recent (attribute_t attr) | ... | @@ -118,131 +197,176 @@ attribute_set_recent (attribute_t attr) |
118 | int | 197 | int |
119 | attribute_is_seen (attribute_t attr) | 198 | attribute_is_seen (attribute_t attr) |
120 | { | 199 | { |
200 | int status = 0; | ||
121 | if (attr == NULL) | 201 | if (attr == NULL) |
122 | return 0; | 202 | return 0; |
123 | return attr->flag & MU_ATTRIBUTE_SEEN; | 203 | if (attr->_get_flags) |
204 | status = attr->_get_flags (attr, &(attr->flags)); | ||
205 | return attr->flags & MU_ATTRIBUTE_SEEN; | ||
124 | } | 206 | } |
125 | 207 | ||
126 | int | 208 | int |
127 | attribute_is_answered (attribute_t attr) | 209 | attribute_is_answered (attribute_t attr) |
128 | { | 210 | { |
211 | int status = 0; | ||
129 | if (attr == NULL) | 212 | if (attr == NULL) |
130 | return 0; | 213 | return 0; |
131 | return attr->flag & MU_ATTRIBUTE_ANSWERED; | 214 | if (attr->_get_flags) |
215 | status = attr->_get_flags (attr, &(attr->flags)); | ||
216 | return attr->flags & MU_ATTRIBUTE_ANSWERED; | ||
132 | } | 217 | } |
133 | 218 | ||
134 | int | 219 | int |
135 | attribute_is_flagged (attribute_t attr) | 220 | attribute_is_flagged (attribute_t attr) |
136 | { | 221 | { |
222 | int status = 0; | ||
137 | if (attr == NULL) | 223 | if (attr == NULL) |
138 | return 0; | 224 | return 0; |
139 | return attr->flag & MU_ATTRIBUTE_FLAGGED; | 225 | if (attr->_get_flags) |
226 | status = attr->_get_flags (attr, &(attr->flags)); | ||
227 | return attr->flags & MU_ATTRIBUTE_FLAGGED; | ||
140 | } | 228 | } |
141 | 229 | ||
142 | int | 230 | int |
143 | attribute_is_read (attribute_t attr) | 231 | attribute_is_read (attribute_t attr) |
144 | { | 232 | { |
233 | int status = 0; | ||
145 | if (attr == NULL) | 234 | if (attr == NULL) |
146 | return 0; | 235 | return 0; |
147 | return attr->flag & MU_ATTRIBUTE_READ; | 236 | if (attr->_get_flags) |
237 | status = attr->_get_flags (attr, &(attr->flags)); | ||
238 | return attr->flags & MU_ATTRIBUTE_READ; | ||
148 | } | 239 | } |
149 | 240 | ||
150 | int | 241 | int |
151 | attribute_is_deleted (attribute_t attr) | 242 | attribute_is_deleted (attribute_t attr) |
152 | { | 243 | { |
244 | int status = 0; | ||
153 | if (attr == NULL) | 245 | if (attr == NULL) |
154 | return 0; | 246 | return 0; |
155 | return attr->flag & MU_ATTRIBUTE_DELETED; | 247 | if (attr->_get_flags) |
248 | status = attr->_get_flags (attr, &(attr->flags)); | ||
249 | return attr->flags & MU_ATTRIBUTE_DELETED; | ||
156 | } | 250 | } |
157 | 251 | ||
158 | int | 252 | int |
159 | attribute_is_draft (attribute_t attr) | 253 | attribute_is_draft (attribute_t attr) |
160 | { | 254 | { |
255 | int status = 0; | ||
161 | if (attr == NULL) | 256 | if (attr == NULL) |
162 | return 0; | 257 | return 0; |
163 | return attr->flag & MU_ATTRIBUTE_DRAFT; | 258 | if (attr->_get_flags) |
259 | status = attr->_get_flags (attr, &(attr->flags)); | ||
260 | return attr->flags & MU_ATTRIBUTE_DRAFT; | ||
164 | } | 261 | } |
165 | 262 | ||
166 | int | 263 | int |
167 | attribute_is_recent (attribute_t attr) | 264 | attribute_is_recent (attribute_t attr) |
168 | { | 265 | { |
266 | int status = 0; | ||
169 | if (attr == NULL) | 267 | if (attr == NULL) |
170 | return 0; | 268 | return 0; |
269 | if (attr->_get_flags) | ||
270 | status = attr->_get_flags (attr, &(attr->flags)); | ||
171 | /* something is recent when it is not read and not seen. */ | 271 | /* something is recent when it is not read and not seen. */ |
172 | return (attr->flag == 0 | 272 | return (attr->flags == 0 |
173 | || ! ((attr->flag & MU_ATTRIBUTE_SEEN) | 273 | || ! ((attr->flags & MU_ATTRIBUTE_SEEN) |
174 | && (attr->flag & MU_ATTRIBUTE_READ))); | 274 | && (attr->flags & MU_ATTRIBUTE_READ))); |
175 | } | 275 | } |
176 | 276 | ||
177 | int | 277 | int |
178 | attribute_unset_seen (attribute_t attr) | 278 | attribute_unset_seen (attribute_t attr) |
179 | { | 279 | { |
280 | int status = 0; | ||
180 | if (attr == NULL) | 281 | if (attr == NULL) |
181 | return 0; | 282 | return 0; |
182 | attr->flag &= ~MU_ATTRIBUTE_SEEN; | 283 | if (attr->_unset_flags) |
183 | return 0; | 284 | status = attr->_unset_flags (attr, MU_ATTRIBUTE_SEEN); |
285 | attr->flags &= ~MU_ATTRIBUTE_SEEN; | ||
286 | return status; | ||
184 | } | 287 | } |
185 | 288 | ||
186 | int | 289 | int |
187 | attribute_unset_answered (attribute_t attr) | 290 | attribute_unset_answered (attribute_t attr) |
188 | { | 291 | { |
292 | int status = 0; | ||
189 | if (attr == NULL) | 293 | if (attr == NULL) |
190 | return 0; | 294 | return 0; |
191 | attr->flag &= ~MU_ATTRIBUTE_ANSWERED; | 295 | if (attr->_unset_flags) |
192 | return 0; | 296 | status = attr->_unset_flags (attr, MU_ATTRIBUTE_ANSWERED); |
297 | attr->flags &= ~MU_ATTRIBUTE_ANSWERED; | ||
298 | return status; | ||
193 | } | 299 | } |
194 | 300 | ||
195 | int | 301 | int |
196 | attribute_unset_flagged (attribute_t attr) | 302 | attribute_unset_flagged (attribute_t attr) |
197 | { | 303 | { |
304 | int status = 0; | ||
198 | if (attr == NULL) | 305 | if (attr == NULL) |
199 | return 0; | 306 | return 0; |
200 | attr->flag &= ~MU_ATTRIBUTE_FLAGGED; | 307 | if (attr->_unset_flags) |
201 | return 0; | 308 | status = attr->_unset_flags (attr, MU_ATTRIBUTE_FLAGGED); |
309 | attr->flags &= ~MU_ATTRIBUTE_FLAGGED; | ||
310 | return status; | ||
202 | } | 311 | } |
203 | 312 | ||
204 | int | 313 | int |
205 | attribute_unset_read (attribute_t attr) | 314 | attribute_unset_read (attribute_t attr) |
206 | { | 315 | { |
316 | int status = 0; | ||
207 | if (attr == NULL) | 317 | if (attr == NULL) |
208 | return 0; | 318 | return 0; |
209 | attr->flag &= ~MU_ATTRIBUTE_READ; | 319 | if (attr->_unset_flags) |
210 | return 0; | 320 | status = attr->_unset_flags (attr, MU_ATTRIBUTE_READ); |
321 | attr->flags &= ~MU_ATTRIBUTE_READ; | ||
322 | return status; | ||
211 | } | 323 | } |
212 | 324 | ||
213 | int | 325 | int |
214 | attribute_unset_deleted (attribute_t attr) | 326 | attribute_unset_deleted (attribute_t attr) |
215 | { | 327 | { |
328 | int status = 0; | ||
216 | if (attr == NULL) | 329 | if (attr == NULL) |
217 | return 0; | 330 | return 0; |
218 | attr->flag &= ~MU_ATTRIBUTE_DELETED; | 331 | if (attr->_unset_flags) |
219 | return 0; | 332 | status = attr->_unset_flags (attr, MU_ATTRIBUTE_DELETED); |
333 | attr->flags &= ~MU_ATTRIBUTE_DELETED; | ||
334 | return status; | ||
220 | } | 335 | } |
221 | 336 | ||
222 | int | 337 | int |
223 | attribute_unset_draft (attribute_t attr) | 338 | attribute_unset_draft (attribute_t attr) |
224 | { | 339 | { |
340 | int status = 0; | ||
225 | if (attr == NULL) | 341 | if (attr == NULL) |
226 | return 0; | 342 | return 0; |
227 | attr->flag &= ~MU_ATTRIBUTE_DRAFT; | 343 | if (attr->_unset_flags) |
228 | return 0; | 344 | status = attr->_unset_flags (attr, MU_ATTRIBUTE_DRAFT); |
345 | attr->flags &= ~MU_ATTRIBUTE_DRAFT; | ||
346 | return status; | ||
229 | } | 347 | } |
230 | 348 | ||
231 | int | 349 | int |
232 | attribute_unset_recent (attribute_t attr) | 350 | attribute_unset_recent (attribute_t attr) |
233 | { | 351 | { |
352 | int status = 0; | ||
234 | if (attr == NULL) | 353 | if (attr == NULL) |
235 | return 0; | 354 | return 0; |
236 | attr->flag |= MU_ATTRIBUTE_SEEN; | 355 | if (attr->_unset_flags) |
237 | return 0; | 356 | status = attr->_unset_flags (attr, MU_ATTRIBUTE_SEEN); |
357 | attr->flags |= MU_ATTRIBUTE_SEEN; | ||
358 | return status; | ||
238 | } | 359 | } |
239 | 360 | ||
240 | int | 361 | int |
241 | attribute_is_equal (attribute_t attr, attribute_t attr2) | 362 | attribute_is_equal (attribute_t attr, attribute_t attr2) |
242 | { | 363 | { |
364 | int status = 0; | ||
243 | if (attr == NULL || attr2 == NULL) | 365 | if (attr == NULL || attr2 == NULL) |
244 | return 0; | 366 | return 0; |
245 | return attr->flag == attr2->flag; | 367 | if (attr->_get_flags) |
368 | status = attr->_get_flags (attr, &(attr->flags)); | ||
369 | return attr->flags == attr2->flags; | ||
246 | } | 370 | } |
247 | 371 | ||
248 | int | 372 | int |
... | @@ -255,14 +379,12 @@ attribute_copy (attribute_t dest, attribute_t src) | ... | @@ -255,14 +379,12 @@ attribute_copy (attribute_t dest, attribute_t src) |
255 | } | 379 | } |
256 | 380 | ||
257 | int | 381 | int |
258 | string_to_attribute (const char *buffer, attribute_t *pattr) | 382 | string_to_flags (const char *buffer, int *pflags) |
259 | { | 383 | { |
260 | const char *sep; | 384 | const char *sep; |
261 | int status; | ||
262 | 385 | ||
263 | status = attribute_create (pattr); | 386 | if (pflags == NULL) |
264 | if (status != 0) | 387 | return EINVAL; |
265 | return status; | ||
266 | 388 | ||
267 | /* Set the attribute */ | 389 | /* Set the attribute */ |
268 | if (strncasecmp (buffer, "Status:", 7) == 0) | 390 | if (strncasecmp (buffer, "Status:", 7) == 0) |
... | @@ -271,22 +393,22 @@ string_to_attribute (const char *buffer, attribute_t *pattr) | ... | @@ -271,22 +393,22 @@ string_to_attribute (const char *buffer, attribute_t *pattr) |
271 | sep++; | 393 | sep++; |
272 | } | 394 | } |
273 | else | 395 | else |
274 | sep = buffer; | 396 | return EINVAL; |
275 | 397 | ||
276 | while (*sep == ' ') sep++; /* glob spaces */ | 398 | while (*sep == ' ') sep++; /* glob spaces */ |
277 | if (strchr (sep, 'R') != NULL || strchr (sep, 'r') != NULL) | 399 | if (strchr (sep, 'R') != NULL || strchr (sep, 'r') != NULL) |
278 | attribute_set_read (*pattr); | 400 | *pflags |= MU_ATTRIBUTE_READ; |
279 | if (strchr (sep, 'O') != NULL || strchr (sep, 'o') != NULL) | 401 | if (strchr (sep, 'O') != NULL || strchr (sep, 'o') != NULL) |
280 | attribute_set_seen (*pattr); | 402 | *pflags |= MU_ATTRIBUTE_SEEN; |
281 | if (strchr (sep, 'A') != NULL || strchr (sep, 'a') != NULL) | 403 | if (strchr (sep, 'A') != NULL || strchr (sep, 'a') != NULL) |
282 | attribute_set_answered (*pattr); | 404 | *pflags |= MU_ATTRIBUTE_ANSWERED; |
283 | if (strchr (sep, 'F') != NULL || strchr (sep, 'f') != NULL) | 405 | if (strchr (sep, 'F') != NULL || strchr (sep, 'f') != NULL) |
284 | attribute_set_flagged (*pattr); | 406 | *pflags |= MU_ATTRIBUTE_FLAGGED; |
285 | return 0; | 407 | return 0; |
286 | } | 408 | } |
287 | 409 | ||
288 | int | 410 | int |
289 | attribute_to_string (attribute_t attr, char *buffer, size_t len, size_t *pn) | 411 | flags_to_string (int flags, char *buffer, size_t len, size_t *pn) |
290 | { | 412 | { |
291 | char status[32]; | 413 | char status[32]; |
292 | char a[8]; | 414 | char a[8]; |
... | @@ -294,14 +416,16 @@ attribute_to_string (attribute_t attr, char *buffer, size_t len, size_t *pn) | ... | @@ -294,14 +416,16 @@ attribute_to_string (attribute_t attr, char *buffer, size_t len, size_t *pn) |
294 | 416 | ||
295 | *status = *a = '\0'; | 417 | *status = *a = '\0'; |
296 | 418 | ||
297 | if (attribute_is_seen (attr)) | 419 | if (flags & MU_ATTRIBUTE_SEEN) |
298 | strcat (a, "R"); | 420 | strcat (a, "R"); |
299 | if (attribute_is_answered (attr)) | 421 | if (flags & MU_ATTRIBUTE_ANSWERED) |
300 | strcat (a, "A"); | 422 | strcat (a, "A"); |
301 | if (attribute_is_flagged (attr)) | 423 | if (flags & MU_ATTRIBUTE_FLAGGED) |
302 | strcat (a, "F"); | 424 | strcat (a, "F"); |
303 | if (attribute_is_read (attr)) | 425 | if (flags & MU_ATTRIBUTE_READ) |
304 | strcat (a, "O"); | 426 | strcat (a, "O"); |
427 | if (flags & MU_ATTRIBUTE_DELETED) | ||
428 | strcat (a, "d"); | ||
305 | 429 | ||
306 | if (*a != '\0') | 430 | if (*a != '\0') |
307 | { | 431 | { | ... | ... |
... | @@ -20,7 +20,7 @@ | ... | @@ -20,7 +20,7 @@ |
20 | # include "config.h" | 20 | # include "config.h" |
21 | #endif | 21 | #endif |
22 | 22 | ||
23 | #include <header.h> | 23 | #include <header0.h> |
24 | #include <io0.h> | 24 | #include <io0.h> |
25 | #include <string.h> | 25 | #include <string.h> |
26 | #include <stdlib.h> | 26 | #include <stdlib.h> |
... | @@ -33,30 +33,6 @@ static int header_read (stream_t is, char *buf, size_t buflen, | ... | @@ -33,30 +33,6 @@ static int header_read (stream_t is, char *buf, size_t buflen, |
33 | static int header_write (stream_t os, const char *buf, size_t buflen, | 33 | static int header_write (stream_t os, const char *buf, size_t buflen, |
34 | off_t off, size_t *pnwrite); | 34 | off_t off, size_t *pnwrite); |
35 | 35 | ||
36 | struct _hdr | ||
37 | { | ||
38 | char *fn; | ||
39 | char *fn_end; | ||
40 | char *fv; | ||
41 | char *fv_end; | ||
42 | }; | ||
43 | |||
44 | struct _header | ||
45 | { | ||
46 | /* Owner. */ | ||
47 | void *owner; | ||
48 | /* Data. */ | ||
49 | char *blurb; | ||
50 | size_t blurb_len; | ||
51 | size_t hdr_count; | ||
52 | struct _hdr *hdr; | ||
53 | |||
54 | /* Streams. */ | ||
55 | stream_t stream; | ||
56 | int (*_get_value) __P ((header_t, const char *, char *, size_t , size_t *)); | ||
57 | |||
58 | }; | ||
59 | |||
60 | int | 36 | int |
61 | header_create (header_t *ph, const char *blurb, size_t len, void *owner) | 37 | header_create (header_t *ph, const char *blurb, size_t len, void *owner) |
62 | { | 38 | { |
... | @@ -66,6 +42,7 @@ header_create (header_t *ph, const char *blurb, size_t len, void *owner) | ... | @@ -66,6 +42,7 @@ header_create (header_t *ph, const char *blurb, size_t len, void *owner) |
66 | return ENOMEM; | 42 | return ENOMEM; |
67 | h->owner = owner; | 43 | h->owner = owner; |
68 | 44 | ||
45 | /* Ignore the return value. */ | ||
69 | header_parse (h, blurb, len); | 46 | header_parse (h, blurb, len); |
70 | 47 | ||
71 | *ph = h; | 48 | *ph = h; |
... | @@ -83,7 +60,9 @@ header_destroy (header_t *ph, void *owner) | ... | @@ -83,7 +60,9 @@ header_destroy (header_t *ph, void *owner) |
83 | if (h->owner == owner) | 60 | if (h->owner == owner) |
84 | { | 61 | { |
85 | stream_destroy (&(h->stream), h); | 62 | stream_destroy (&(h->stream), h); |
63 | if (h->hdr) | ||
86 | free (h->hdr); | 64 | free (h->hdr); |
65 | if (h->blurb) | ||
87 | free (h->blurb); | 66 | free (h->blurb); |
88 | free (h); | 67 | free (h); |
89 | } | 68 | } |
... | @@ -207,8 +186,7 @@ header_parse (header_t header, const char *blurb, int len) | ... | @@ -207,8 +186,7 @@ header_parse (header_t header, const char *blurb, int len) |
207 | } | 186 | } |
208 | 187 | ||
209 | /* FIXME: grossly inneficient, to many copies and reallocating. | 188 | /* FIXME: grossly inneficient, to many copies and reallocating. |
210 | * This all header business need a good rewrite. | 189 | This all header business need a good rewrite. */ |
211 | */ | ||
212 | int | 190 | int |
213 | header_set_value (header_t header, const char *fn, const char *fv, int replace) | 191 | header_set_value (header_t header, const char *fn, const char *fv, int replace) |
214 | { | 192 | { |
... | @@ -218,11 +196,14 @@ header_set_value (header_t header, const char *fn, const char *fv, int replace) | ... | @@ -218,11 +196,14 @@ header_set_value (header_t header, const char *fn, const char *fv, int replace) |
218 | if (header == NULL || fn == NULL || fv == NULL) | 196 | if (header == NULL || fn == NULL || fv == NULL) |
219 | return EINVAL; | 197 | return EINVAL; |
220 | 198 | ||
221 | /* Easy approach: if replace, overwrite the field-{namve,value} | 199 | /* Try to fill out the buffer, if we know how. */ |
222 | and readjust the pointers by calling header_parse () | 200 | if (header->_set_value != NULL) |
223 | this is wastefull, we're just fragmenting the memory | 201 | return header->_set_value (header, fn, fv, replace); |
224 | it can be done better. But that may imply a rewite of the headers | 202 | |
225 | So for another day. */ | 203 | /* Easy approach: if replace, overwrite the field-{name,value} and readjust |
204 | the pointers by calling header_parse () this is wastefull, we're just | ||
205 | fragmenting the memory it can be done better. But that may imply a | ||
206 | rewite of the headers So for another day. */ | ||
226 | if (replace) | 207 | if (replace) |
227 | { | 208 | { |
228 | size_t name_len; | 209 | size_t name_len; |
... | @@ -251,8 +232,8 @@ header_set_value (header_t header, const char *fn, const char *fv, int replace) | ... | @@ -251,8 +232,8 @@ header_set_value (header_t header, const char *fn, const char *fv, int replace) |
251 | } | 232 | } |
252 | } | 233 | } |
253 | 234 | ||
254 | /* Replacing was taking care of above now just add to | 235 | /* Replacing was taking care of above now just add to the end the new |
255 | the end the new header. Really not cute. */ | 236 | header. Really not cute. */ |
256 | len = strlen (fn) + strlen (fv) + 1 + 1 + 1 + 1; | 237 | len = strlen (fn) + strlen (fv) + 1 + 1 + 1 + 1; |
257 | blurb = calloc (header->blurb_len + len, 1); | 238 | blurb = calloc (header->blurb_len + len, 1); |
258 | if (blurb == NULL) | 239 | if (blurb == NULL) |
... | @@ -266,20 +247,6 @@ header_set_value (header_t header, const char *fn, const char *fv, int replace) | ... | @@ -266,20 +247,6 @@ header_set_value (header_t header, const char *fn, const char *fv, int replace) |
266 | } | 247 | } |
267 | 248 | ||
268 | int | 249 | int |
269 | header_set_get_value (header_t header, int (*_get_value) | ||
270 | (header_t, const char *, char *, size_t, size_t *), | ||
271 | void *owner) | ||
272 | { | ||
273 | if (header == NULL) | ||
274 | return EINVAL; | ||
275 | if (header->owner != owner) | ||
276 | return EACCES; | ||
277 | |||
278 | header->_get_value = _get_value; | ||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | int | ||
283 | header_get_value (header_t header, const char *name, char *buffer, | 250 | header_get_value (header_t header, const char *name, char *buffer, |
284 | size_t buflen, size_t *pn) | 251 | size_t buflen, size_t *pn) |
285 | { | 252 | { |
... | @@ -287,20 +254,61 @@ header_get_value (header_t header, const char *name, char *buffer, | ... | @@ -287,20 +254,61 @@ header_get_value (header_t header, const char *name, char *buffer, |
287 | size_t name_len; | 254 | size_t name_len; |
288 | size_t total = 0, fn_len = 0, fv_len = 0; | 255 | size_t total = 0, fn_len = 0, fv_len = 0; |
289 | int threshold; | 256 | int threshold; |
257 | int err = 0; | ||
290 | 258 | ||
291 | if (header == NULL || name == NULL) | 259 | if (header == NULL || name == NULL) |
292 | return EINVAL; | 260 | return EINVAL; |
293 | 261 | ||
262 | if (header->_get_value != NULL) | ||
263 | return header->_get_value (header, name, buffer, buflen, pn); | ||
264 | |||
265 | /* Try to fill out the buffer, if we know how. */ | ||
266 | if (header->blurb == NULL) | ||
267 | { | ||
268 | stream_t is; | ||
269 | err = header_get_stream (header, &is); | ||
270 | if (err != 0) | ||
271 | return err; | ||
272 | else | ||
273 | { | ||
274 | char buf[1024]; | ||
275 | char *tbuf; | ||
276 | size_t nread = 0; | ||
277 | do | ||
278 | { | ||
279 | err = stream_read (is, buf, sizeof (buf), header->temp_blurb_len, | ||
280 | &nread); | ||
281 | if (err != 0 | ||
282 | || (tbuf = realloc (header->temp_blurb, | ||
283 | header->temp_blurb_len + nread)) == NULL) | ||
284 | { | ||
285 | free (header->temp_blurb); | ||
286 | header->temp_blurb = NULL; | ||
287 | header->temp_blurb_len = 0; | ||
288 | return err; | ||
289 | } | ||
290 | else | ||
291 | header->temp_blurb = tbuf; | ||
292 | memcpy (header->temp_blurb + header->temp_blurb_len, buf, nread); | ||
293 | header->temp_blurb_len += nread; | ||
294 | } while (nread != 0); | ||
295 | /* parse it. */ | ||
296 | header_parse (header, header->temp_blurb, header->temp_blurb_len); | ||
297 | free (header->temp_blurb); | ||
298 | header->temp_blurb = NULL; | ||
299 | header->temp_blurb_len = 0; | ||
300 | } | ||
301 | } | ||
302 | |||
294 | /* We set the threshold to be 1 less for the null. */ | 303 | /* We set the threshold to be 1 less for the null. */ |
295 | threshold = --buflen; | 304 | threshold = --buflen; |
296 | 305 | ||
297 | /* Caution: We may have more then one value for a field | 306 | /* Caution: We may have more then one value for a field name, for example |
298 | name, for example a "Received" field-name is added by | 307 | a "Received" field-name is added by each passing MTA. The way that the |
299 | each passing MTA. The way that the parsing (_parse()) | 308 | parsing (_parse()) is done it's not take to account. So we just stuff |
300 | is done it's not take to account. So we just stuff in | 309 | in the buffer all the field-values to a corresponding field-name. |
301 | the buffer all the field-values to a corresponding field-name. | 310 | FIXME: Should we kosher the output ? meaning replace occurences of |
302 | FIXME: Should we kosher the output ? meaning replace | 311 | " \t\r\n" for spaces ? for now we don't. */ |
303 | occurences of " \t\r\n" for spaces ? for now we don't. */ | ||
304 | for (name_len = strlen (name), i = 0; i < header->hdr_count; i++) | 312 | for (name_len = strlen (name), i = 0; i < header->hdr_count; i++) |
305 | { | 313 | { |
306 | fn_len = header->hdr[i].fn_end - header->hdr[i].fn; | 314 | fn_len = header->hdr[i].fn_end - header->hdr[i].fn; |
... | @@ -332,48 +340,35 @@ header_get_value (header_t header, const char *name, char *buffer, | ... | @@ -332,48 +340,35 @@ header_get_value (header_t header, const char *name, char *buffer, |
332 | *buffer = '\0'; /* Null terminated. */ | 340 | *buffer = '\0'; /* Null terminated. */ |
333 | if (pn) | 341 | if (pn) |
334 | *pn = total; | 342 | *pn = total; |
343 | |||
344 | /* Check if they provided a hook. */ | ||
335 | if (total == 0) | 345 | if (total == 0) |
336 | { | 346 | { |
337 | int err = ENOENT; | 347 | err = ENOENT; |
338 | /* Check if they provided a hook. */ | ||
339 | if (header->_get_value != NULL) | 348 | if (header->_get_value != NULL) |
340 | err = header->_get_value (header, name, buffer, buflen, pn); | 349 | err = header->_get_value (header, name, buffer, buflen, pn); |
341 | /* Cache it locally. */ | 350 | /* Success. Cache it locally. */ |
342 | if (err == 0) | 351 | if (err == 0) |
343 | header_set_value (header, name, buffer, 0); | 352 | header_set_value (header, name, buffer, 0); |
344 | return err; | ||
345 | } | ||
346 | return 0; | ||
347 | } | ||
348 | |||
349 | int | ||
350 | header_entry_count (header_t header, size_t *pnum) | ||
351 | { | ||
352 | if (header == NULL) | ||
353 | { | ||
354 | if (pnum) | ||
355 | *pnum = 0; | ||
356 | return EINVAL; | ||
357 | } | 353 | } |
358 | if (pnum) | 354 | return err; |
359 | *pnum = header->hdr_count; | ||
360 | return 0; | ||
361 | } | 355 | } |
362 | 356 | ||
363 | int | 357 | int |
364 | header_lines (header_t header, size_t *plines) | 358 | header_lines (header_t header, size_t *plines) |
365 | { | 359 | { |
366 | int n; | 360 | int n; |
367 | size_t t = 0; | 361 | size_t lines = 0; |
368 | if (header == NULL) | 362 | if (header == NULL) |
369 | return EINVAL; | 363 | return EINVAL; |
364 | |||
370 | for (n = header->blurb_len - 1; n >= 0; n--) | 365 | for (n = header->blurb_len - 1; n >= 0; n--) |
371 | { | 366 | { |
372 | if (header->blurb[n] == '\n') | 367 | if (header->blurb[n] == '\n') |
373 | t++; | 368 | lines++; |
374 | } | 369 | } |
375 | if (plines) | 370 | if (plines) |
376 | *plines = t; | 371 | *plines = lines; |
377 | return 0; | 372 | return 0; |
378 | } | 373 | } |
379 | 374 | ||
... | @@ -382,57 +377,50 @@ header_size (header_t header, size_t *pnum) | ... | @@ -382,57 +377,50 @@ header_size (header_t header, size_t *pnum) |
382 | { | 377 | { |
383 | if (header == NULL) | 378 | if (header == NULL) |
384 | return EINVAL; | 379 | return EINVAL; |
380 | |||
385 | if (pnum) | 381 | if (pnum) |
386 | *pnum = header->blurb_len; | 382 | *pnum = header->blurb_len; |
387 | return 0; | 383 | return 0; |
388 | } | 384 | } |
389 | 385 | ||
390 | int | 386 | int |
391 | header_entry_name (header_t header, size_t num, char *buf, | 387 | header_set_get_value (header_t header, int (*_get_value) |
392 | size_t buflen, size_t *nwritten) | 388 | (header_t, const char *, char *, size_t, size_t *), |
389 | void *owner) | ||
393 | { | 390 | { |
394 | size_t len; | ||
395 | if (header == NULL) | 391 | if (header == NULL) |
396 | return EINVAL; | 392 | return EINVAL; |
397 | if (header->hdr_count == 0 || num > header->hdr_count) | 393 | if (header->owner != owner) |
398 | return ENOENT; | 394 | return EACCES; |
399 | len = header->hdr[num].fn_end - header->hdr[num].fn; | 395 | header->_get_value = _get_value; |
400 | /* save one for the null */ | ||
401 | --buflen; | ||
402 | if (buf && buflen > 0) | ||
403 | { | ||
404 | buflen = (len > buflen) ? buflen : len; | ||
405 | memcpy (buf, header->hdr[num].fn, buflen); | ||
406 | buf[buflen] = '\0'; | ||
407 | } | ||
408 | if (nwritten) | ||
409 | *nwritten = len; | ||
410 | return 0; | 396 | return 0; |
411 | } | 397 | } |
412 | 398 | ||
413 | int | 399 | int |
414 | header_entry_value (header_t header, size_t num, char *buf, | 400 | header_set_set_value (header_t header, int (*_set_value) |
415 | size_t buflen, size_t *nwritten) | 401 | (header_t , const char *, const char *, int), |
402 | void *owner) | ||
416 | { | 403 | { |
417 | size_t len; | ||
418 | if (header == NULL) | 404 | if (header == NULL) |
419 | return EINVAL; | 405 | return EINVAL; |
420 | if (header->hdr_count == 0 || num > header->hdr_count) | 406 | if (header->owner != owner) |
421 | return ENOENT; | 407 | return EACCES; |
422 | len = header->hdr[num].fv_end - header->hdr[num].fv; | 408 | header->_set_value = _set_value; |
423 | /* Save one for the null. */ | ||
424 | --buflen; | ||
425 | if (buf && buflen > 0) | ||
426 | { | ||
427 | buflen = (len > buflen) ? buflen : len; | ||
428 | memcpy (buf, header->hdr[num].fv, buflen); | ||
429 | buf[buflen] = '\0'; | ||
430 | } | ||
431 | if (nwritten) | ||
432 | *nwritten = len; | ||
433 | return 0; | 409 | return 0; |
434 | } | 410 | } |
435 | 411 | ||
412 | int | ||
413 | header_set_stream (header_t header, stream_t stream, void *owner) | ||
414 | { | ||
415 | if (header == NULL) | ||
416 | return EINVAL; | ||
417 | if (header->owner != owner) | ||
418 | return EACCES; | ||
419 | header->stream = stream; | ||
420 | return 0; | ||
421 | } | ||
422 | |||
423 | |||
436 | static int | 424 | static int |
437 | header_write (stream_t os, const char *buf, size_t buflen, | 425 | header_write (stream_t os, const char *buf, size_t buflen, |
438 | off_t off, size_t *pnwrite) | 426 | off_t off, size_t *pnwrite) | ... | ... |
... | @@ -34,17 +34,13 @@ extern "C" { | ... | @@ -34,17 +34,13 @@ extern "C" { |
34 | 34 | ||
35 | struct _attribute | 35 | struct _attribute |
36 | { | 36 | { |
37 | size_t flag; | 37 | void *owner; |
38 | size_t flags; | ||
39 | int (*_get_flags) __P ((attribute_t, int *)); | ||
40 | int (*_set_flags) __P ((attribute_t, int)); | ||
41 | int (*_unset_flags) __P ((attribute_t, int)); | ||
38 | }; | 42 | }; |
39 | 43 | ||
40 | #define MU_ATTRIBUTE_ANSWERED 0x01 | ||
41 | #define MU_ATTRIBUTE_FLAGGED 0x02 | ||
42 | #define MU_ATTRIBUTE_DELETED 0x04 | ||
43 | #define MU_ATTRIBUTE_DRAFT 0x08 | ||
44 | #define MU_ATTRIBUTE_SEEN 0x10 | ||
45 | #define MU_ATTRIBUTE_READ 0x20 | ||
46 | #define MU_ATTRIBUTE_RECENT 0x00 | ||
47 | |||
48 | #ifdef __cplusplus | 44 | #ifdef __cplusplus |
49 | } | 45 | } |
50 | #endif | 46 | #endif | ... | ... |
... | @@ -35,8 +35,16 @@ extern "C" { | ... | @@ -35,8 +35,16 @@ extern "C" { |
35 | struct _attribute; | 35 | struct _attribute; |
36 | typedef struct _attribute * attribute_t; | 36 | typedef struct _attribute * attribute_t; |
37 | 37 | ||
38 | extern int attribute_create __P ((attribute_t *)); | 38 | #define MU_ATTRIBUTE_ANSWERED 0x01 |
39 | extern void attribute_destroy __P ((attribute_t *)); | 39 | #define MU_ATTRIBUTE_FLAGGED 0x02 |
40 | #define MU_ATTRIBUTE_DELETED 0x04 | ||
41 | #define MU_ATTRIBUTE_DRAFT 0x08 | ||
42 | #define MU_ATTRIBUTE_SEEN 0x10 | ||
43 | #define MU_ATTRIBUTE_READ 0x20 | ||
44 | #define MU_ATTRIBUTE_RECENT 0x00 | ||
45 | |||
46 | extern int attribute_create __P ((attribute_t *, void *)); | ||
47 | extern void attribute_destroy __P ((attribute_t *, void *)); | ||
40 | 48 | ||
41 | extern int attribute_is_seen __P ((attribute_t)); | 49 | extern int attribute_is_seen __P ((attribute_t)); |
42 | extern int attribute_is_answered __P ((attribute_t)); | 50 | extern int attribute_is_answered __P ((attribute_t)); |
... | @@ -62,14 +70,22 @@ extern int attribute_unset_draft __P ((attribute_t)); | ... | @@ -62,14 +70,22 @@ extern int attribute_unset_draft __P ((attribute_t)); |
62 | extern int attribute_unset_recent __P ((attribute_t)); | 70 | extern int attribute_unset_recent __P ((attribute_t)); |
63 | extern int attribute_unset_read __P ((attribute_t)); | 71 | extern int attribute_unset_read __P ((attribute_t)); |
64 | 72 | ||
73 | extern int attribute_get_flags __P ((attribute_t, int *)); | ||
74 | extern int attribute_set_flags __P ((attribute_t, int)); | ||
75 | |||
76 | extern int attribute_set_set_flags __P ((attribute_t, int (*_set_flags) | ||
77 | __P ((attribute_t, int)), void *)); | ||
78 | extern int attribute_set_unset_flags __P ((attribute_t, int (*_unset_flags) | ||
79 | __P ((attribute_t, int)), void *)); | ||
80 | extern int attribute_set_get_flags __P ((attribute_t, int (*_get_flags) | ||
81 | __P ((attribute_t, int *)), void *)); | ||
65 | extern int attribute_is_equal __P ((attribute_t att1, attribute_t att2)); | 82 | extern int attribute_is_equal __P ((attribute_t att1, attribute_t att2)); |
66 | 83 | ||
67 | extern int attribute_copy __P ((attribute_t dst, | 84 | extern int attribute_copy __P ((attribute_t dst, |
68 | attribute_t src)); | 85 | attribute_t src)); |
69 | 86 | ||
70 | extern int string_to_attribute __P ((const char *buf, | 87 | extern int string_to_flags __P ((const char *buf, int *pattr)); |
71 | attribute_t *pattr)); | 88 | extern int flags_to_string __P ((int flags, char *buf, |
72 | extern int attribute_to_string __P ((attribute_t attr, char *buf, | ||
73 | size_t len, size_t *)); | 89 | size_t len, size_t *)); |
74 | 90 | ||
75 | #ifdef __cplusplus | 91 | #ifdef __cplusplus | ... | ... |
... | @@ -67,27 +67,27 @@ extern "C" { | ... | @@ -67,27 +67,27 @@ extern "C" { |
67 | struct _header; | 67 | struct _header; |
68 | typedef struct _header * header_t; | 68 | typedef struct _header * header_t; |
69 | 69 | ||
70 | extern int header_create __P ((header_t *, const char *blurb, | 70 | extern int header_create __P ((header_t *, const char *, |
71 | size_t ln, void *owner)); | 71 | size_t, void *)); |
72 | extern void header_destroy __P ((header_t *, void *owner)); | 72 | extern void header_destroy __P ((header_t *, void *)); |
73 | extern int header_set_value __P ((header_t, const char *, | ||
74 | const char *, int)); | ||
75 | extern int header_get_value __P ((header_t, const char *, char *, | ||
76 | size_t, size_t *)); | ||
77 | extern int header_get_stream __P ((header_t, stream_t *)); | ||
78 | extern int header_size __P ((header_t, size_t *)); | ||
79 | extern int header_lines __P ((header_t, size_t *)); | ||
73 | 80 | ||
74 | extern int header_set_value __P ((header_t, const char *fn, | 81 | extern int header_set_stream __P ((header_t, stream_t, void *)); |
75 | const char *fv, int replace)); | ||
76 | 82 | ||
83 | extern int header_set_set_value __P ((header_t, int (*_set_value) | ||
84 | __P ((header_t, const char *, | ||
85 | const char *, int)), | ||
86 | void *)); | ||
77 | extern int header_set_get_value __P ((header_t, int (*_get_value) | 87 | extern int header_set_get_value __P ((header_t, int (*_get_value) |
78 | __P ((header_t, const char *fn, char *buf, | 88 | __P ((header_t, const char *, |
79 | size_t buflen, size_t *nwritten)), | 89 | char *, size_t, size_t *)), |
80 | void *owner)); | 90 | void *)); |
81 | extern int header_get_value __P ((header_t, const char *fn, char *buf, | ||
82 | size_t buflen, size_t *nwritten)); | ||
83 | extern int header_entry_count __P ((header_t, size_t *num)); | ||
84 | extern int header_entry_name __P ((header_t, size_t num, char *buf, | ||
85 | size_t buflen, size_t *total)); | ||
86 | extern int header_entry_value __P ((header_t, size_t num, char *buf, | ||
87 | size_t buflen, size_t *total)); | ||
88 | extern int header_get_stream __P ((header_t, stream_t *stream)); | ||
89 | extern int header_size __P ((header_t, size_t *size)); | ||
90 | extern int header_lines __P ((header_t, size_t *lines)); | ||
91 | 91 | ||
92 | #ifdef _cplusplus | 92 | #ifdef _cplusplus |
93 | } | 93 | } | ... | ... |
... | @@ -21,8 +21,8 @@ | ... | @@ -21,8 +21,8 @@ |
21 | #include <message0.h> | 21 | #include <message0.h> |
22 | #include <registrar0.h> | 22 | #include <registrar0.h> |
23 | #include <auth0.h> | 23 | #include <auth0.h> |
24 | #include <attribute.h> | 24 | #include <header0.h> |
25 | #include <mailutils_errno.h> | 25 | #include <attribute0.h> |
26 | 26 | ||
27 | #include <termios.h> | 27 | #include <termios.h> |
28 | #include <errno.h> | 28 | #include <errno.h> |
... | @@ -33,34 +33,62 @@ | ... | @@ -33,34 +33,62 @@ |
33 | #include <fcntl.h> | 33 | #include <fcntl.h> |
34 | 34 | ||
35 | 35 | ||
36 | static int mailbox_pop_create (mailbox_t *mbox, const char *name); | 36 | /* The different possible states of a Pop client, it maps to the POP3 commands. |
37 | static void mailbox_pop_destroy (mailbox_t *mbox); | 37 | Note that POP3 is not reentrant. It is only one channel. */ |
38 | 38 | enum pop_state | |
39 | struct mailbox_registrar _mailbox_pop_registrar = | ||
40 | { | 39 | { |
41 | "POP3", | 40 | /* The initialisation of POP_NO_STATE is redundant but it is here for |
42 | mailbox_pop_create, mailbox_pop_destroy | 41 | info purposes meaning 0 is the starting state. */ |
42 | POP_NO_STATE = 0, | ||
43 | POP_OPEN_CONNECTION, | ||
44 | POP_GREETINGS, | ||
45 | POP_APOP_TX, POP_APOP_ACK, | ||
46 | POP_DELE_TX, POP_DELE_ACK, | ||
47 | POP_LIST_TX, POP_LIST_ACK, POP_LIST_RX, | ||
48 | POP_PASS_TX, POP_PASS_ACK, | ||
49 | POP_QUIT_TX, POP_QUIT_ACK, | ||
50 | POP_NOOP_TX, POP_NOOP_ACK, | ||
51 | POP_RETR_TX, POP_RETR_ACK, POP_RETR_RX_HDR, POP_RETR_RX_BODY, | ||
52 | POP_RSET_TX, POP_RSET_ACK, | ||
53 | POP_STAT_TX, POP_STAT_ACK, | ||
54 | POP_TOP_TX, POP_TOP_ACK, POP_TOP_RX, | ||
55 | POP_UIDL_TX, POP_UIDL_ACK, | ||
56 | POP_USER_TX, POP_USER_ACK, | ||
57 | POP_CLOSE_CONNECTION, /* I do not think a shutdown of a connection will | ||
58 | block. More for the symmetry. */ | ||
43 | }; | 59 | }; |
44 | 60 | ||
45 | static int mailbox_pop_open (mailbox_t, int flags); | 61 | /* Those two are exportable funtions i.e. they are visible/call when you |
46 | static int mailbox_pop_close (mailbox_t); | 62 | call a URL "pop://..." to mailbox_create. */ |
47 | static int mailbox_pop_get_message (mailbox_t, size_t msgno, message_t *msg); | ||
48 | static int mailbox_pop_messages_count (mailbox_t, size_t *num); | ||
49 | static int mailbox_pop_expunge (mailbox_t); | ||
50 | static int mailbox_pop_num_deleted (mailbox_t, size_t *); | ||
51 | |||
52 | /* update and scanning*/ | ||
53 | static int mailbox_pop_is_updated (mailbox_t); | ||
54 | static int mailbox_pop_scan (mailbox_t mbox, size_t msgno, size_t *pcount); | ||
55 | 63 | ||
56 | /* mailbox size ? */ | 64 | static int pop_create (mailbox_t *, const char *); |
57 | static int mailbox_pop_size (mailbox_t, off_t *size); | 65 | static void pop_destroy (mailbox_t *); |
58 | 66 | ||
59 | static int mailbox_pop_readstream (stream_t is, char *buffer, size_t buflen, | 67 | struct mailbox_registrar _mailbox_pop_registrar = |
60 | off_t offset, size_t *pnread); | 68 | { |
61 | static int mailbox_pop_getfd (stream_t, int *pfd); | 69 | "POP3", |
62 | static int mailbox_pop_body_size (body_t, size_t *psize); | 70 | pop_create, pop_destroy |
71 | }; | ||
63 | 72 | ||
73 | /* Functions/Methods that implements the mailbox_t API. */ | ||
74 | static int pop_open (mailbox_t, int); | ||
75 | static int pop_close (mailbox_t); | ||
76 | static int pop_get_message (mailbox_t, size_t, message_t *); | ||
77 | static int pop_messages_count (mailbox_t, size_t *); | ||
78 | static int pop_expunge (mailbox_t); | ||
79 | static int pop_num_deleted (mailbox_t, size_t *); | ||
80 | static int pop_scan (mailbox_t, size_t, size_t *); | ||
81 | static int pop_is_updated (mailbox_t); | ||
82 | |||
83 | /* The implementation of message_t */ | ||
84 | static int pop_size (mailbox_t, off_t *); | ||
85 | static int pop_readstream (stream_t, char *, size_t, off_t, size_t *); | ||
86 | static int pop_get_fd (stream_t, int *); | ||
87 | static int pop_get_flags (attribute_t, int *); | ||
88 | static int pop_body_size (body_t, size_t *); | ||
89 | static int pop_body_lines (body_t body, size_t *plines); | ||
90 | static int pop_header_read (stream_t, char *, size_t, off_t, size_t *); | ||
91 | static int pop_uidl (message_t, char *, size_t, size_t *); | ||
64 | 92 | ||
65 | /* According to the rfc: | 93 | /* According to the rfc: |
66 | RFC 2449 POP3 Extension Mechanism November 1998 | 94 | RFC 2449 POP3 Extension Mechanism November 1998 |
... | @@ -82,7 +110,15 @@ static int mailbox_pop_body_size (body_t, size_t *psize); | ... | @@ -82,7 +110,15 @@ static int mailbox_pop_body_size (body_t, size_t *psize); |
82 | the initial greeting) is unchanged at 512 octets (including the | 110 | the initial greeting) is unchanged at 512 octets (including the |
83 | terminating CRLF). */ | 111 | terminating CRLF). */ |
84 | 112 | ||
85 | /* buffered IO */ | 113 | /* Buffered I/O, since the connection maybe non-blocking, we use a little |
114 | working buffer to hold the I/O between us and the POP3 Server. For | ||
115 | example if write () return EAGAIN, we keep on calling bio_write () until | ||
116 | the buffer is empty. bio_read () does a little more, it takes care of | ||
117 | filtering out the starting "." and return O(zero) when seeing the terminal | ||
118 | octets ".\r\n". bio_readline () insists on having a _complete_ line .i.e | ||
119 | a string terminated by \n, it will allocate/grow the working buffer as | ||
120 | needed. The '\r\n" termination is converted to '\n'. bio_destroy () | ||
121 | does not close the stream but only free () the working buffer. */ | ||
86 | struct _bio | 122 | struct _bio |
87 | { | 123 | { |
88 | #define POP_BUFSIZ 512 | 124 | #define POP_BUFSIZ 512 |
... | @@ -94,7 +130,6 @@ struct _bio | ... | @@ -94,7 +130,6 @@ struct _bio |
94 | char *ptr; | 130 | char *ptr; |
95 | char *nl; | 131 | char *nl; |
96 | }; | 132 | }; |
97 | |||
98 | typedef struct _bio *bio_t; | 133 | typedef struct _bio *bio_t; |
99 | 134 | ||
100 | static int bio_create (bio_t *, stream_t); | 135 | static int bio_create (bio_t *, stream_t); |
... | @@ -103,55 +138,85 @@ static int bio_readline (bio_t); | ... | @@ -103,55 +138,85 @@ static int bio_readline (bio_t); |
103 | static int bio_read (bio_t); | 138 | static int bio_read (bio_t); |
104 | static int bio_write (bio_t); | 139 | static int bio_write (bio_t); |
105 | 140 | ||
106 | struct _mailbox_pop_data; | 141 | /* Advance declarations. */ |
107 | struct _mailbox_pop_message; | 142 | struct _pop_data; |
108 | 143 | struct _pop_message; | |
109 | typedef struct _mailbox_pop_data * mailbox_pop_data_t; | 144 | |
110 | typedef struct _mailbox_pop_message * mailbox_pop_message_t; | 145 | typedef struct _pop_data * pop_data_t; |
111 | 146 | typedef struct _pop_message * pop_message_t; | |
112 | struct _mailbox_pop_message | 147 | |
148 | /* This structure holds the info when for a pop_get_message() the | ||
149 | pop_message_t type will serve as the owner of the message_t and contains | ||
150 | the command to send to RETReive the specify message. The problem comes | ||
151 | from the header. If the POP server supports TOP, we can cleanly fetch | ||
152 | the header. But otherwise we use the clumsy approach. .i.e for the header | ||
153 | we read 'til ^\n then discard the rest for the body we read after ^\n and | ||
154 | discard the beginning. This a waste, Pop was not conceive for this | ||
155 | obviously. */ | ||
156 | struct _pop_message | ||
113 | { | 157 | { |
114 | bio_t bio; | ||
115 | int inbody; | 158 | int inbody; |
159 | size_t body_size; | ||
160 | size_t body_lines; | ||
116 | size_t num; | 161 | size_t num; |
117 | off_t body_size; | ||
118 | message_t message; | 162 | message_t message; |
119 | mailbox_pop_data_t mpd; | 163 | pop_data_t mpd; /* Back pointer. */ |
120 | }; | 164 | }; |
121 | 165 | ||
122 | struct _mailbox_pop_data | 166 | /* Structure to hold things general to the POP client, like its state, how |
167 | many messages we have so far etc ... */ | ||
168 | struct _pop_data | ||
123 | { | 169 | { |
124 | void *func; | 170 | void *func; /* Indicate a command is in operation, busy. */ |
125 | void *id; | 171 | size_t id; /* Use in pop_expunge to indiate the message, if bailing out. */ |
126 | int state; | 172 | enum pop_state state; |
127 | mailbox_pop_message_t *pmessages; | 173 | pop_message_t *pmessages; |
128 | size_t pmessages_count; | 174 | size_t pmessages_count; |
129 | size_t messages_count; | 175 | size_t messages_count; |
130 | size_t size; | 176 | size_t size; |
131 | #ifdef HAVE_PTHREAD_H | 177 | #ifdef HAVE_PTHREAD_H |
132 | pthread_mutex_t mutex; | 178 | pthread_mutex_t mutex; |
133 | #endif | 179 | #endif |
134 | int flags; | 180 | int flags; /* Flags of for the stream_t object. */ |
135 | bio_t bio; | 181 | bio_t bio; /* Working I/O buffer. */ |
136 | int is_updated; | 182 | int is_updated; |
137 | char *user; | 183 | char *user; /* Temporary holders for user and passwd. */ |
138 | char *passwd; | 184 | char *passwd; |
139 | mailbox_pop_message_t mpm; | 185 | mailbox_t mbox; /* Back pointer. */ |
140 | } ; | 186 | } ; |
141 | 187 | ||
188 | /* Little Macro, since this is very repetitive. */ | ||
189 | #define CLEAR_STATE(mpd) \ | ||
190 | mpd->func = NULL, \ | ||
191 | mpd->state = POP_NO_STATE | ||
192 | |||
193 | /* Clear the state for non recoverable error. */ | ||
194 | #define CHECK_NON_RECOVERABLE(mpd, status) \ | ||
195 | do \ | ||
196 | { \ | ||
197 | if (status != 0) \ | ||
198 | { \ | ||
199 | if (status != EAGAIN && status != EINPROGRESS && status != EINTR) \ | ||
200 | { \ | ||
201 | CLEAR_STATE (mpd); \ | ||
202 | } \ | ||
203 | return status; \ | ||
204 | } \ | ||
205 | } \ | ||
206 | while (0) | ||
207 | |||
142 | 208 | ||
143 | /* Parse the url, allocate mailbox_t etc .. */ | 209 | /* Parse the url, allocate mailbox_t etc .. */ |
144 | static int | 210 | static int |
145 | mailbox_pop_create (mailbox_t *pmbox, const char *name) | 211 | pop_create (mailbox_t *pmbox, const char *name) |
146 | { | 212 | { |
147 | mailbox_t mbox; | 213 | mailbox_t mbox; |
148 | mailbox_pop_data_t mpd; | 214 | pop_data_t mpd; |
149 | size_t name_len; | 215 | size_t name_len; |
150 | int status; | ||
151 | 216 | ||
152 | /* Sanity check. */ | 217 | /* Sanity check. */ |
153 | if (pmbox == NULL || name == NULL || *name == '\0') | 218 | if (pmbox == NULL || name == NULL || *name == '\0') |
154 | return MU_ERROR_INVALID_ARG; | 219 | return EINVAL; |
155 | 220 | ||
156 | name_len = strlen (name); | 221 | name_len = strlen (name); |
157 | 222 | ||
... | @@ -173,95 +238,104 @@ mailbox_pop_create (mailbox_t *pmbox, const char *name) | ... | @@ -173,95 +238,104 @@ mailbox_pop_create (mailbox_t *pmbox, const char *name) |
173 | /* Allocate memory for mbox. */ | 238 | /* Allocate memory for mbox. */ |
174 | mbox = calloc (1, sizeof (*mbox)); | 239 | mbox = calloc (1, sizeof (*mbox)); |
175 | if (mbox == NULL) | 240 | if (mbox == NULL) |
176 | return MU_ERROR_OUT_OF_MEMORY; | 241 | return ENOMEM; |
177 | 242 | ||
178 | /* Allocate specific pop box data. */ | 243 | /* Allocate specifics for pop data. */ |
179 | mpd = mbox->data = calloc (1, sizeof (*mpd)); | 244 | mpd = mbox->data = calloc (1, sizeof (*mpd)); |
180 | if (mbox->data == NULL) | 245 | if (mbox->data == NULL) |
181 | { | 246 | { |
182 | mailbox_pop_destroy (&mbox); | 247 | pop_destroy (&mbox); |
183 | return MU_ERROR_OUT_OF_MEMORY; | 248 | return ENOMEM; |
184 | } | ||
185 | |||
186 | /* Allocate the struct for buffered I/O. */ | ||
187 | status = bio_create (&(mpd->bio), NULL); | ||
188 | if (status != 0) | ||
189 | { | ||
190 | mailbox_pop_destroy (&mbox); | ||
191 | return status; | ||
192 | } | 249 | } |
250 | mpd->state = POP_NO_STATE; | ||
251 | mpd->mbox = mbox; | ||
193 | 252 | ||
194 | /* Copy the name. */ | 253 | /* Copy the name. */ |
195 | mbox->name = calloc (name_len + 1, sizeof (char)); | 254 | mbox->name = calloc (name_len + 1, sizeof (char)); |
196 | if (mbox->name == NULL) | 255 | if (mbox->name == NULL) |
197 | { | 256 | { |
198 | mailbox_pop_destroy (&mbox); | 257 | pop_destroy (&mbox); |
199 | return MU_ERROR_OUT_OF_MEMORY; | 258 | return ENOMEM; |
200 | } | 259 | } |
201 | memcpy (mbox->name, name, name_len); | 260 | memcpy (mbox->name, name, name_len); |
202 | 261 | ||
203 | #ifdef HAVE_PHTREAD_H | 262 | #ifdef HAVE_PHTREAD_H |
204 | /* Mutex when accessing the structure fields. */ | 263 | /* Mutex when accessing the structure fields. */ |
205 | /* FIXME: should we use rdwr locks instead ?? */ | 264 | /* FIXME: should we use rdwr locks instead ?? */ |
206 | pthread_mutex_init (&(mud->mutex), NULL); | 265 | /* XXXX: This is not use yet and the library is still not thread safe. This |
266 | is more a gentle remider that I got more work to do. */ | ||
267 | pthread_mutex_init (&(mpd->mutex), NULL); | ||
207 | #endif | 268 | #endif |
208 | 269 | ||
209 | /* Initialize the structure. */ | 270 | /* Initialize the structure. */ |
210 | mbox->_create = mailbox_pop_create; | 271 | mbox->_create = pop_create; |
211 | mbox->_destroy = mailbox_pop_destroy; | 272 | mbox->_destroy = pop_destroy; |
212 | 273 | ||
213 | mbox->_open = mailbox_pop_open; | 274 | mbox->_open = pop_open; |
214 | mbox->_close = mailbox_pop_close; | 275 | mbox->_close = pop_close; |
215 | 276 | ||
216 | /* Messages. */ | 277 | /* Messages. */ |
217 | mbox->_get_message = mailbox_pop_get_message; | 278 | mbox->_get_message = pop_get_message; |
218 | mbox->_messages_count = mailbox_pop_messages_count; | 279 | mbox->_messages_count = pop_messages_count; |
219 | mbox->_expunge = mailbox_pop_expunge; | 280 | mbox->_expunge = pop_expunge; |
220 | mbox->_num_deleted = mailbox_pop_num_deleted; | 281 | mbox->_num_deleted = pop_num_deleted; |
221 | 282 | ||
222 | mbox->_scan = mailbox_pop_scan; | 283 | mbox->_scan = pop_scan; |
223 | mbox->_is_updated = mailbox_pop_is_updated; | 284 | mbox->_is_updated = pop_is_updated; |
224 | 285 | ||
225 | mbox->_size = mailbox_pop_size; | 286 | mbox->_size = pop_size; |
226 | 287 | ||
227 | (*pmbox) = mbox; | 288 | (*pmbox) = mbox; |
228 | 289 | ||
229 | return 0; /* Okdoke. */ | 290 | return 0; /* Okdoke. */ |
230 | } | 291 | } |
231 | 292 | ||
293 | /* Cleaning up all the ressources. */ | ||
232 | static void | 294 | static void |
233 | mailbox_pop_destroy (mailbox_t *pmbox) | 295 | pop_destroy (mailbox_t *pmbox) |
234 | { | 296 | { |
235 | if (pmbox && *pmbox) | 297 | if (pmbox && *pmbox) |
236 | { | 298 | { |
237 | mailbox_t mbox = *pmbox; | 299 | mailbox_t mbox = *pmbox; |
238 | if (mbox->data) | 300 | if (mbox->data) |
239 | { | 301 | { |
240 | mailbox_pop_data_t mpd = mbox->data; | 302 | pop_data_t mpd = mbox->data; |
241 | size_t i; | 303 | size_t i; |
304 | /* Destroy the pop messages and ressources associated to them. */ | ||
242 | for (i = 0; i < mpd->pmessages_count; i++) | 305 | for (i = 0; i < mpd->pmessages_count; i++) |
243 | { | 306 | { |
244 | if (mpd->pmessages[i]) | 307 | if (mpd->pmessages[i]) |
245 | { | 308 | { |
246 | bio_destroy (&(mpd->pmessages[i]->bio)); | ||
247 | message_destroy (&(mpd->pmessages[i]->message), | 309 | message_destroy (&(mpd->pmessages[i]->message), |
248 | mpd->pmessages[i]); | 310 | mpd->pmessages[i]); |
249 | } | ||
250 | free (mpd->pmessages[i]); | 311 | free (mpd->pmessages[i]); |
251 | } | 312 | } |
313 | } | ||
314 | bio_destroy (&(mpd->bio)); | ||
252 | free (mpd->pmessages); | 315 | free (mpd->pmessages); |
253 | free (mpd); | 316 | free (mpd); |
317 | #ifdef HAVE_PHTREAD_H | ||
318 | pthread_mutex_destroy (&(mpd->mutex)); | ||
319 | #endif | ||
254 | } | 320 | } |
255 | free (mbox->name); | 321 | /* Since the mailbox is destroy, close the stream but not via |
256 | free (mbox->event); | 322 | pop_close () which can return EAGAIN, or other unpleasant side |
323 | effects, but rather the hard way. */ | ||
324 | stream_close (mbox->stream); | ||
257 | stream_destroy (&(mbox->stream), mbox); | 325 | stream_destroy (&(mbox->stream), mbox); |
258 | auth_destroy (&(mbox->auth), mbox); | 326 | auth_destroy (&(mbox->auth), mbox); |
327 | if (mbox->name) | ||
328 | free (mbox->name); | ||
329 | if (mbox->event) | ||
330 | free (mbox->event); | ||
259 | if (mbox->url) | 331 | if (mbox->url) |
260 | url_destroy (&(mbox->url)); | 332 | url_destroy (&(mbox->url)); |
333 | free (mbox); | ||
261 | *pmbox = NULL; | 334 | *pmbox = NULL; |
262 | } | 335 | } |
263 | } | 336 | } |
264 | 337 | ||
338 | /* We should probably use getpass () or something similar. */ | ||
265 | static struct termios stored_settings; | 339 | static struct termios stored_settings; |
266 | 340 | ||
267 | static void | 341 | static void |
... | @@ -283,9 +357,8 @@ echo_on(void) | ... | @@ -283,9 +357,8 @@ echo_on(void) |
283 | static int | 357 | static int |
284 | pop_authenticate (auth_t auth, char **user, char **passwd) | 358 | pop_authenticate (auth_t auth, char **user, char **passwd) |
285 | { | 359 | { |
286 | /* FIXME: this incorrect and goes against GNU style: having a limitation | 360 | /* FIXME: This incorrect and goes against GNU style: having a limitation on |
287 | * on the user/passwd length, it should be fix | 361 | the user/passwd length, it should be fix. */ |
288 | */ | ||
289 | char u[128]; | 362 | char u[128]; |
290 | char p[128]; | 363 | char p[128]; |
291 | mailbox_t mbox = auth->owner; | 364 | mailbox_t mbox = auth->owner; |
... | @@ -294,7 +367,7 @@ pop_authenticate (auth_t auth, char **user, char **passwd) | ... | @@ -294,7 +367,7 @@ pop_authenticate (auth_t auth, char **user, char **passwd) |
294 | *u = '\0'; | 367 | *u = '\0'; |
295 | *p = '\0'; | 368 | *p = '\0'; |
296 | 369 | ||
297 | /* prompt for the user/login name */ | 370 | /* Prompt for the user/login name. */ |
298 | status = url_get_user (mbox->url, u, sizeof (u), NULL); | 371 | status = url_get_user (mbox->url, u, sizeof (u), NULL); |
299 | if (status != 0 || *u == '\0') | 372 | if (status != 0 || *u == '\0') |
300 | { | 373 | { |
... | @@ -302,8 +375,7 @@ pop_authenticate (auth_t auth, char **user, char **passwd) | ... | @@ -302,8 +375,7 @@ pop_authenticate (auth_t auth, char **user, char **passwd) |
302 | fgets (u, sizeof (u), stdin); | 375 | fgets (u, sizeof (u), stdin); |
303 | u [strlen (u) - 1] = '\0'; /* nuke the trailing NL */ | 376 | u [strlen (u) - 1] = '\0'; /* nuke the trailing NL */ |
304 | } | 377 | } |
305 | /* prompt for the passwd */ | 378 | /* Prompt for the passwd. */ |
306 | /* FIXME: should turn off echo .... */ | ||
307 | status = url_get_passwd (mbox->url, p, sizeof (p), NULL); | 379 | status = url_get_passwd (mbox->url, p, sizeof (p), NULL); |
308 | if (status != 0 || *p == '\0' || *p == '*') | 380 | if (status != 0 || *p == '\0' || *p == '*') |
309 | { | 381 | { |
... | @@ -320,12 +392,12 @@ pop_authenticate (auth_t auth, char **user, char **passwd) | ... | @@ -320,12 +392,12 @@ pop_authenticate (auth_t auth, char **user, char **passwd) |
320 | } | 392 | } |
321 | 393 | ||
322 | static int | 394 | static int |
323 | mailbox_pop_open (mailbox_t mbox, int flags) | 395 | pop_open (mailbox_t mbox, int flags) |
324 | { | 396 | { |
325 | mailbox_pop_data_t mpd; | 397 | pop_data_t mpd; |
326 | int status; | 398 | int status; |
327 | bio_t bio; | 399 | bio_t bio; |
328 | void *func = (void *)mailbox_pop_open; | 400 | void *func = (void *)pop_open; |
329 | char host[256] ; | 401 | char host[256] ; |
330 | long port; | 402 | long port; |
331 | 403 | ||
... | @@ -333,20 +405,12 @@ mailbox_pop_open (mailbox_t mbox, int flags) | ... | @@ -333,20 +405,12 @@ mailbox_pop_open (mailbox_t mbox, int flags) |
333 | if (mbox == NULL || mbox->url == NULL || (mpd = mbox->data) == NULL) | 405 | if (mbox == NULL || mbox->url == NULL || (mpd = mbox->data) == NULL) |
334 | return EINVAL; | 406 | return EINVAL; |
335 | 407 | ||
336 | /* Create the networking stack. */ | 408 | /* Fetch the pop server name and the port in the url_t. */ |
337 | if (mbox->stream == NULL) | 409 | if ((status = url_get_host (mbox->url, host, sizeof(host), NULL)) != 0 |
338 | { | 410 | || (status = url_get_port (mbox->url, &port)) != 0) |
339 | status = tcp_stream_create (&(mbox->stream)); | ||
340 | if (status != 0) | ||
341 | return status; | ||
342 | } | ||
343 | |||
344 | if ((status = url_get_host (mbox->url, host, sizeof(host), NULL)) != 0 || | ||
345 | (status = url_get_port (mbox->url, &port)) != 0) | ||
346 | return status; | 411 | return status; |
347 | 412 | ||
348 | /* Dealing whith Authentication. */ | 413 | /* Dealing whith Authentication. So far only normal user/pass supported. */ |
349 | /* So far only normal user/pass supported. */ | ||
350 | if (mbox->auth == NULL) | 414 | if (mbox->auth == NULL) |
351 | { | 415 | { |
352 | status = auth_create (&(mbox->auth), mbox); | 416 | status = auth_create (&(mbox->auth), mbox); |
... | @@ -361,141 +425,134 @@ mailbox_pop_open (mailbox_t mbox, int flags) | ... | @@ -361,141 +425,134 @@ mailbox_pop_open (mailbox_t mbox, int flags) |
361 | mpd->func = func; | 425 | mpd->func = func; |
362 | bio = mpd->bio; | 426 | bio = mpd->bio; |
363 | 427 | ||
364 | /* Enter the state machine. */ | 428 | /* Enter the pop state machine, and boogy: AUTHORISATION State. */ |
365 | switch (mpd->state) | 429 | switch (mpd->state) |
366 | { | 430 | { |
367 | /* Establish the connection. */ | 431 | case POP_NO_STATE: |
368 | case 0: | ||
369 | /* Spawn auth prologue. */ | 432 | /* Spawn auth prologue. */ |
370 | auth_prologue (mbox->auth); | 433 | auth_prologue (mbox->auth); |
434 | /* Create the networking stack. */ | ||
435 | if (mbox->stream == NULL) | ||
436 | { | ||
437 | status = tcp_stream_create (&(mbox->stream)); | ||
438 | if (status != 0) | ||
439 | return status; | ||
440 | } | ||
441 | mpd->state = POP_OPEN_CONNECTION; | ||
371 | 442 | ||
443 | case POP_OPEN_CONNECTION: | ||
444 | /* Establish the connection. */ | ||
372 | status = stream_open (mbox->stream, host, port, flags); | 445 | status = stream_open (mbox->stream, host, port, flags); |
373 | if (status != 0) | 446 | if (status != 0) |
374 | { | 447 | { |
448 | /* Clear the state for non recoverable error. */ | ||
375 | if (status != EAGAIN && status != EINPROGRESS && status != EINTR) | 449 | if (status != EAGAIN && status != EINPROGRESS && status != EINTR) |
376 | { | 450 | { |
377 | mpd->func = NULL; | 451 | mpd->func = NULL; |
378 | mpd->state = 0; | 452 | mpd->state = POP_NO_STATE; |
379 | } | 453 | } |
380 | return status; | 454 | return status; |
381 | } | 455 | } |
382 | /* Set the Buffer I/O. */ | 456 | /* Allocate the struct for buffered I/O. */ |
383 | bio->stream = mbox->stream; | 457 | bio_destroy (&(mpd->bio)); |
384 | bio->ptr = bio->buffer; | 458 | status = bio_create (&(mpd->bio), mbox->stream); |
385 | bio->nl = NULL; | 459 | /* Can't recover bailout. */ |
386 | mpd->state = 1; | ||
387 | /* Glob the greetings. */ | ||
388 | case 1: | ||
389 | status = bio_readline (bio); | ||
390 | if (status != 0) | 460 | if (status != 0) |
391 | { | 461 | { |
392 | if (status != EAGAIN && status != EINTR) | 462 | stream_close (bio->stream); |
393 | { | 463 | CLEAR_STATE (mpd); |
394 | mpd->func = NULL; | ||
395 | mpd->state = 0; | ||
396 | } | ||
397 | return status; | 464 | return status; |
398 | } | 465 | } |
466 | bio = mpd->bio; | ||
467 | mpd->state = POP_GREETINGS; | ||
468 | |||
469 | case POP_GREETINGS: | ||
470 | /* Swallow the greetings. */ | ||
471 | status = bio_readline (bio); | ||
472 | CHECK_NON_RECOVERABLE (mpd, status); | ||
473 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_PROT, bio->buffer); | ||
399 | if (strncasecmp (bio->buffer, "+OK", 3) != 0) | 474 | if (strncasecmp (bio->buffer, "+OK", 3) != 0) |
400 | { | 475 | { |
401 | mpd->func = NULL; | ||
402 | mpd->state = 0; | ||
403 | stream_close (bio->stream); | 476 | stream_close (bio->stream); |
404 | bio->stream = NULL; | 477 | CLEAR_STATE (mpd); |
405 | return EACCES; | 478 | return EACCES; |
406 | } | 479 | } |
407 | 480 | ||
481 | /* Fetch the the user/passwd from them. */ | ||
408 | auth_authenticate (mbox->auth, &mpd->user, &mpd->passwd); | 482 | auth_authenticate (mbox->auth, &mpd->user, &mpd->passwd); |
409 | /* FIXME: Use snprintf. */ | 483 | |
410 | //mpd->len = sprintf (pop->buffer, POP_BUFSIZ, "USER %s\r\n", user); | 484 | bio->len = snprintf (bio->buffer, bio->maxlen, "USER %s\r\n", mpd->user); |
411 | bio->len = sprintf (bio->buffer, "USER %s\r\n", mpd->user); | ||
412 | bio->ptr = bio->buffer; | 485 | bio->ptr = bio->buffer; |
413 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_PROT, bio->buffer); | 486 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_PROT, bio->buffer); |
414 | free (mpd->user); mpd->user = NULL; | 487 | free (mpd->user); mpd->user = NULL; |
415 | mpd->state = 2; | 488 | mpd->state = POP_USER_TX; |
489 | |||
490 | case POP_USER_TX: | ||
416 | /* Send username. */ | 491 | /* Send username. */ |
417 | case 2: | ||
418 | status = bio_write (bio); | 492 | status = bio_write (bio); |
419 | if (status != 0) | 493 | CHECK_NON_RECOVERABLE (mpd, status); |
420 | { | 494 | mpd->state = POP_USER_ACK; |
421 | if (status != EAGAIN && status != EINTR) | 495 | |
422 | { | 496 | case POP_USER_ACK: |
423 | mpd->func = NULL; | 497 | /* Get the user ack. */ |
424 | mpd->state = 0; | ||
425 | } | ||
426 | return status; | ||
427 | } | ||
428 | mpd->state = 3; | ||
429 | /* Get the ack. */ | ||
430 | case 3: | ||
431 | status = bio_readline (bio); | 498 | status = bio_readline (bio); |
432 | if (status != 0) | 499 | CHECK_NON_RECOVERABLE (mpd, status); |
433 | { | ||
434 | if (status != EAGAIN && status != EINTR) | ||
435 | { | ||
436 | mpd->func = NULL; | ||
437 | mpd->state = 0; | ||
438 | } | ||
439 | return status; | ||
440 | } | ||
441 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_PROT, bio->buffer); | 500 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_PROT, bio->buffer); |
442 | if (strncasecmp (bio->buffer, "+OK", 3) != 0) | 501 | if (strncasecmp (bio->buffer, "+OK", 3) != 0) |
502 | { | ||
503 | stream_close (bio->stream); | ||
504 | CLEAR_STATE (mpd); | ||
443 | return EACCES; | 505 | return EACCES; |
444 | 506 | } | |
445 | /* FIXME Use snprintf. */ | 507 | bio->len = snprintf (bio->buffer, POP_BUFSIZ, "PASS %s\r\n", |
446 | //mpd->len = snprintf (mpd->buffer, POP_BUFSIZ, "PASS %s\r\n", passwd); | 508 | mpd->passwd); |
447 | bio->len = sprintf (bio->buffer, "PASS %s\r\n", mpd->passwd); | ||
448 | bio->ptr = bio->buffer; | 509 | bio->ptr = bio->buffer; |
449 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_PROT, bio->buffer); | 510 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_PROT, bio->buffer); |
511 | /* We have to nuke the passwd. */ | ||
512 | memset (mpd->passwd, 0, strlen (mpd->passwd)); | ||
450 | free (mpd->passwd); mpd->passwd = NULL; | 513 | free (mpd->passwd); mpd->passwd = NULL; |
451 | mpd->state = 4; | 514 | mpd->state = POP_PASS_TX; |
515 | |||
516 | case POP_PASS_TX: | ||
452 | /* Send passwd. */ | 517 | /* Send passwd. */ |
453 | case 4: | ||
454 | status = bio_write (bio); | 518 | status = bio_write (bio); |
455 | if (status != 0) | 519 | CHECK_NON_RECOVERABLE (mpd, status); |
456 | { | 520 | mpd->state = POP_PASS_ACK; |
457 | if (status != EAGAIN && status != EINTR) | 521 | |
458 | { | 522 | case POP_PASS_ACK: |
459 | mpd->func = NULL; | ||
460 | mpd->state = 0; | ||
461 | } | ||
462 | return status; | ||
463 | } | ||
464 | mpd->state = 5; | ||
465 | /* Get the ack from passwd. */ | 523 | /* Get the ack from passwd. */ |
466 | case 5: | ||
467 | status = bio_readline (bio); | 524 | status = bio_readline (bio); |
468 | if (status != 0) | 525 | CHECK_NON_RECOVERABLE (mpd, status); |
469 | { | ||
470 | if (status != EAGAIN && status != EINTR) | ||
471 | { | ||
472 | mpd->func = NULL; | ||
473 | mpd->state = 0; | ||
474 | } | ||
475 | return status; | ||
476 | } | ||
477 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_PROT, bio->buffer); | 526 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_PROT, bio->buffer); |
478 | if (strncasecmp (bio->buffer, "+OK", 3) != 0) | 527 | if (strncasecmp (bio->buffer, "+OK", 3) != 0) |
528 | { | ||
529 | stream_close (bio->stream); | ||
530 | CLEAR_STATE (mpd); | ||
479 | return EACCES; | 531 | return EACCES; |
480 | }/* Swith state. */ | 532 | } |
533 | break; /* We're outta here. */ | ||
534 | default: | ||
535 | /* | ||
536 | fprintf (stderr, "pop_open unknown state\n"); | ||
537 | */ | ||
538 | }/* End AUTHORISATION state. */ | ||
481 | 539 | ||
482 | /* Spawn cleanup functions. */ | 540 | /* Spawn cleanup functions. */ |
483 | auth_epilogue (mbox->auth); | 541 | auth_epilogue (mbox->auth); |
484 | 542 | ||
485 | /* Clear any state. */ | 543 | /* Clear any state. */ |
486 | mpd->id = mpd->func = NULL; | 544 | CLEAR_STATE (mpd); |
487 | mpd->state = 0; | ||
488 | |||
489 | return 0; | 545 | return 0; |
490 | } | 546 | } |
491 | 547 | ||
492 | static int | 548 | static int |
493 | mailbox_pop_close (mailbox_t mbox) | 549 | pop_close (mailbox_t mbox) |
494 | { | 550 | { |
495 | mailbox_pop_data_t mpd; | 551 | pop_data_t mpd; |
496 | void *func = (void *)mailbox_pop_close; | 552 | void *func = (void *)pop_close; |
497 | int status; | 553 | int status; |
498 | bio_t bio; | 554 | bio_t bio; |
555 | size_t i; | ||
499 | 556 | ||
500 | if (mbox == NULL || (mpd = mbox->data) == NULL) | 557 | if (mbox == NULL || (mpd = mbox->data) == NULL) |
501 | return EINVAL; | 558 | return EINVAL; |
... | @@ -506,65 +563,74 @@ mailbox_pop_close (mailbox_t mbox) | ... | @@ -506,65 +563,74 @@ mailbox_pop_close (mailbox_t mbox) |
506 | mpd->func = func; | 563 | mpd->func = func; |
507 | bio = mpd->bio; | 564 | bio = mpd->bio; |
508 | 565 | ||
509 | if (bio->stream != NULL) | 566 | /* Ok boys, it's a wrap: UPDATE State. */ |
510 | { | ||
511 | switch (mpd->state) | 567 | switch (mpd->state) |
512 | { | 568 | { |
513 | case 0: | 569 | case POP_NO_STATE: |
514 | bio->len = sprintf (bio->buffer, "QUIT\r\n"); | 570 | bio->len = snprintf (bio->buffer, bio->maxlen, "QUIT\r\n"); |
515 | bio->ptr = bio->buffer; | 571 | bio->ptr = bio->buffer; |
516 | mpd->state = 1; | ||
517 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_PROT, bio->buffer); | 572 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_PROT, bio->buffer); |
518 | case 1: | 573 | mpd->state = POP_QUIT_TX; |
574 | |||
575 | case POP_QUIT_TX: | ||
576 | /* Send the quit. */ | ||
519 | status = bio_write (mpd->bio); | 577 | status = bio_write (mpd->bio); |
520 | if (status != 0) | 578 | CHECK_NON_RECOVERABLE (mpd, status); |
521 | { | 579 | mpd->state = POP_QUIT_ACK; |
522 | if (status != EAGAIN && status != EINTR) | 580 | |
523 | { | 581 | case POP_QUIT_ACK: |
524 | mpd->func = mpd->id = NULL; | 582 | /* Glob the acknowledge. */ |
525 | mpd->state = 0; | ||
526 | } | ||
527 | return status; | ||
528 | } | ||
529 | case 2: | ||
530 | status = bio_readline (bio); | 583 | status = bio_readline (bio); |
531 | if (status != 0) | 584 | CHECK_NON_RECOVERABLE (mpd, status); |
532 | { | ||
533 | if (status != EAGAIN && status != EINTR) | ||
534 | { | ||
535 | mpd->func = mpd->id = NULL; | ||
536 | mpd->state = 0; | ||
537 | } | ||
538 | return status; | ||
539 | } | ||
540 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_PROT, bio->buffer); | 585 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_PROT, bio->buffer); |
586 | /* Now what ! and how can we tell them about errors ? So for now | ||
587 | lets just be verbose about the error but close the connection | ||
588 | anyway. */ | ||
541 | if (strncasecmp (bio->buffer, "+OK", 3) != 0) | 589 | if (strncasecmp (bio->buffer, "+OK", 3) != 0) |
542 | return EINVAL; | 590 | fprintf (stderr, "pop_close: %s\n", bio->buffer); |
543 | case 3: | 591 | |
544 | stream_close (bio->stream); | 592 | stream_close (bio->stream); |
545 | bio->stream = NULL; | 593 | bio->stream = NULL; |
594 | break; | ||
595 | default: | ||
596 | /* | ||
597 | fprintf (stderr, "pop_close unknow state"); | ||
598 | */ | ||
599 | } /* UPDATE state. */ | ||
600 | |||
601 | /* free the messages */ | ||
602 | for (i = 0; i < mpd->pmessages_count; i++) | ||
603 | { | ||
604 | if (mpd->pmessages[i]) | ||
605 | { | ||
606 | message_destroy (&(mpd->pmessages[i]->message), | ||
607 | mpd->pmessages[i]); | ||
608 | free (mpd->pmessages[i]); | ||
546 | } | 609 | } |
547 | } | 610 | } |
611 | free (mpd->pmessages); | ||
612 | mpd->pmessages = NULL; | ||
613 | mpd->pmessages_count = 0; | ||
614 | mpd->is_updated = 0; | ||
615 | bio_destroy (&(mpd->bio)); | ||
548 | 616 | ||
549 | mpd->func = mpd->id = NULL; | 617 | CLEAR_STATE (mpd); |
550 | mpd->state = 0; | ||
551 | return 0; | 618 | return 0; |
552 | } | 619 | } |
553 | 620 | ||
554 | static int | 621 | static int |
555 | mailbox_pop_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) | 622 | pop_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) |
556 | { | 623 | { |
557 | mailbox_pop_data_t mpd; | 624 | pop_data_t mpd; |
558 | bio_t bio; | ||
559 | int status; | 625 | int status; |
626 | pop_message_t mpm; | ||
560 | size_t i; | 627 | size_t i; |
561 | void *func = (void *)mailbox_pop_get_message; | ||
562 | 628 | ||
563 | /* Sanity. */ | 629 | /* Sanity. */ |
564 | if (mbox == NULL || pmsg == NULL || (mpd = mbox->data) == NULL) | 630 | if (mbox == NULL || pmsg == NULL || (mpd = mbox->data) == NULL) |
565 | return EINVAL; | 631 | return EINVAL; |
566 | 632 | ||
567 | /* See if we already have this message. */ | 633 | /* See if we have already this message. */ |
568 | for (i = 0; i < mpd->pmessages_count; i++) | 634 | for (i = 0; i < mpd->pmessages_count; i++) |
569 | { | 635 | { |
570 | if (mpd->pmessages[i]) | 636 | if (mpd->pmessages[i]) |
... | @@ -577,280 +643,120 @@ mailbox_pop_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) | ... | @@ -577,280 +643,120 @@ mailbox_pop_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) |
577 | } | 643 | } |
578 | } | 644 | } |
579 | 645 | ||
580 | /* Are we busy in another function ? */ | ||
581 | if (mpd->func && mpd->func != func) | ||
582 | return EBUSY; | ||
583 | |||
584 | /* In the function, but are we busy with an other message/request ? */ | ||
585 | if (mpd->id && mpd->id != *pmsg) | ||
586 | return EBUSY; | ||
587 | |||
588 | mpd->func = func; | ||
589 | bio = mpd->bio; | ||
590 | |||
591 | /* Ok men, we're going in. */ | ||
592 | switch (mpd->state) | ||
593 | { | ||
594 | /* The message. */ | ||
595 | case 0: | ||
596 | { | ||
597 | message_t msg; | ||
598 | mailbox_pop_message_t mpm ; | ||
599 | |||
600 | mpm = calloc (1, sizeof (*mpm)); | 646 | mpm = calloc (1, sizeof (*mpm)); |
601 | if (mpm == NULL) | 647 | if (mpm == NULL) |
602 | return ENOMEM; | 648 | return ENOMEM; |
603 | 649 | /* back pointer */ | |
604 | /* We'll use the bio to store headers. */ | 650 | mpm->mpd = mpd; |
605 | mpm->bio = calloc (1, sizeof (*(mpm->bio))); | 651 | mpm->num = msgno; |
606 | if (mpm->bio == NULL) | ||
607 | { | ||
608 | free (mpm); | ||
609 | mpd->func = NULL; | ||
610 | return ENOMEM; | ||
611 | } | ||
612 | 652 | ||
613 | /* Create the message. */ | 653 | /* Create the message. */ |
654 | { | ||
655 | message_t msg; | ||
614 | status = message_create (&msg, mpm); | 656 | status = message_create (&msg, mpm); |
615 | if (status != 0) | 657 | if (status != 0) |
616 | { | 658 | { |
617 | free (mpm->bio); | ||
618 | free (mpm); | 659 | free (mpm); |
619 | mpd->func = NULL; | ||
620 | return status; | 660 | return status; |
621 | } | 661 | } |
622 | |||
623 | /* The message. */ | 662 | /* The message. */ |
624 | mpm->message = msg; | 663 | mpm->message = msg; |
625 | mpm->num = msgno; | ||
626 | mpd->mpm = mpm; | ||
627 | /* back pointer */ | ||
628 | mpm->mpd = mpd; | ||
629 | /* set the busy request state */ | ||
630 | mpd->id = (void *)msg; | ||
631 | |||
632 | /* Get the header. | ||
633 | FIXME: TOP is an optionnal command, if we want to | ||
634 | be compliant we can not count on it to exists. | ||
635 | So we should be prepare when it fails and fall to | ||
636 | a second scheme. */ | ||
637 | /*bio->len = snprintf (bio->buffer, POP_BUFSIZ, "TOP %d 0\r\n", msgno);*/ | ||
638 | bio->len = sprintf (bio->buffer, "TOP %d 0\r\n", msgno); | ||
639 | bio->ptr = bio->buffer; | ||
640 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_PROT, bio->buffer); | ||
641 | mpd->state = 1; | ||
642 | } | ||
643 | /* Send the TOP. */ | ||
644 | case 1: | ||
645 | { | ||
646 | status = bio_write (bio); | ||
647 | if (status != 0) | ||
648 | { | ||
649 | if (status != EAGAIN && status != EINTR) | ||
650 | { | ||
651 | mpd->func = mpd->id = NULL; | ||
652 | mpd->state = 0; | ||
653 | message_destroy (&(mpd->mpm->message), mpd->mpm); | ||
654 | bio_destroy (&(mpd->mpm->bio)); | ||
655 | free (mpd->mpm); | ||
656 | mpd->mpm = NULL; | ||
657 | } | ||
658 | return status; | ||
659 | } | ||
660 | mpd->state = 2; | ||
661 | } | ||
662 | /* Ack from TOP. */ | ||
663 | case 2: | ||
664 | { | ||
665 | status = bio_readline (bio); | ||
666 | if (status != 0) | ||
667 | { | ||
668 | if (status != EAGAIN && status != EINTR) | ||
669 | { | ||
670 | mpd->func = mpd->id = NULL; | ||
671 | mpd->state = 0; | ||
672 | message_destroy (&(mpd->mpm->message), mpd->mpm); | ||
673 | bio_destroy (&(mpd->mpm->bio)); | ||
674 | free (mpd->mpm); | ||
675 | mpd->mpm = NULL; | ||
676 | } | 664 | } |
677 | return status; | ||
678 | } | ||
679 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_PROT, bio->buffer); | ||
680 | if (strncasecmp (bio->buffer, "+OK", 3) != 0) | ||
681 | { | ||
682 | mpd->func = mpd->id = NULL; | ||
683 | mpd->state = 0; | ||
684 | message_destroy (&(mpd->mpm->message), mpd->mpm); | ||
685 | bio_destroy (&(mpd->mpm->bio)); | ||
686 | free (mpd->mpm); | ||
687 | mpd->mpm = NULL; | ||
688 | return ERANGE; | ||
689 | } | ||
690 | } | ||
691 | mpd->state = 5; | ||
692 | /* Get the header. */ | ||
693 | case 5: | ||
694 | { | ||
695 | char *tbuf; | ||
696 | int nread; | ||
697 | while (1) | ||
698 | { | ||
699 | status = bio_readline (bio); | ||
700 | if (status != 0) | ||
701 | { | ||
702 | /* Recoverable. */ | ||
703 | if (status != EAGAIN && status != EINTR) | ||
704 | { | ||
705 | mpd->func = mpd->id = NULL; | ||
706 | mpd->state = 0; | ||
707 | message_destroy (&(mpd->mpm->message), mpd->mpm); | ||
708 | bio_destroy (&(mpd->mpm->bio)); | ||
709 | free (mpd->mpm); | ||
710 | mpd->mpm = NULL; | ||
711 | } | ||
712 | return status; | ||
713 | } | ||
714 | |||
715 | /* Our ticket out. */ | ||
716 | if (bio->buffer[0] == '\0') | ||
717 | break; | ||
718 | |||
719 | nread = bio->nl - bio->buffer; | ||
720 | |||
721 | tbuf = realloc (mpd->mpm->bio->buffer, | ||
722 | mpd->mpm->bio->maxlen + nread); | ||
723 | if (tbuf == NULL) | ||
724 | { | ||
725 | mpd->func = mpd->id = NULL; | ||
726 | mpd->state = 0; | ||
727 | message_destroy (&(mpd->mpm->message), mpd->mpm); | ||
728 | bio_destroy (&(mpd->mpm->bio)); | ||
729 | free (mpd->mpm); | ||
730 | mpd->mpm = NULL; | ||
731 | return ENOMEM; | ||
732 | } | ||
733 | else | ||
734 | mpd->mpm->bio->buffer = tbuf; | ||
735 | memcpy (mpd->mpm->bio->buffer + mpd->mpm->bio->maxlen, | ||
736 | bio->buffer, nread); | ||
737 | mpd->mpm->bio->maxlen += nread; | ||
738 | } /* while () */ | ||
739 | } /* case 5: */ | ||
740 | break; | ||
741 | default: | ||
742 | /* Error here unknow case. */ | ||
743 | fprintf (stderr, "Pop unknown state(get_message)\n"); | ||
744 | } /* switch (state) */ | ||
745 | |||
746 | /* No need to carry a state anymore. */ | ||
747 | mpd->func = mpd->id = NULL; | ||
748 | mpd->state = 0; | ||
749 | 665 | ||
750 | /* Create the header. */ | 666 | /* Create the header. */ |
751 | { | 667 | { |
752 | header_t header; | 668 | header_t header; |
753 | status = header_create (&header, mpd->mpm->bio->buffer, | 669 | stream_t stream; |
754 | mpd->mpm->bio->maxlen, mpd->mpm); | 670 | if ((status = header_create (&header, NULL, 0, mpm)) != 0 |
755 | bio_destroy (&(mpd->mpm->bio)); | 671 | || (status = stream_create (&stream, MU_STREAM_READ, mpm)) != 0) |
756 | if (status != 0) | ||
757 | { | 672 | { |
758 | message_destroy (&(mpd->mpm->message), mpd->mpm); | 673 | message_destroy (&(mpm->message), mpm); |
759 | free (mpd->mpm); | 674 | free (mpm); |
760 | mpd->mpm = NULL; | ||
761 | return status; | 675 | return status; |
762 | } | 676 | } |
763 | message_set_header ((mpd->mpm->message), header, mpd->mpm); | 677 | stream_set_read (stream, pop_header_read, mpm); |
678 | stream_set_fd (stream, pop_get_fd, mpm); | ||
679 | stream_set_flags (stream, MU_STREAM_READ, mpm); | ||
680 | header_set_stream (header, stream, mpm); | ||
681 | message_set_header (mpm->message, header, mpm); | ||
764 | } | 682 | } |
765 | 683 | ||
766 | /* Reallocate the working I/O buffer. */ | ||
767 | bio_create (&(mpd->mpm->bio), bio->stream); | ||
768 | |||
769 | /* Create the attribute. */ | 684 | /* Create the attribute. */ |
770 | { | 685 | { |
771 | attribute_t attribute; | 686 | attribute_t attribute; |
772 | char hdr_status[64]; | 687 | status = attribute_create (&attribute, mpm); |
773 | header_t header = NULL; | ||
774 | hdr_status[0] = '\0'; | ||
775 | message_get_header (mpd->mpm->message, &header); | ||
776 | header_get_value (header, "Status", hdr_status, sizeof (hdr_status), NULL); | ||
777 | /* Create the attribute. */ | ||
778 | status = string_to_attribute (hdr_status, &attribute); | ||
779 | if (status != 0) | 688 | if (status != 0) |
780 | { | 689 | { |
781 | message_destroy (&(mpd->mpm->message), mpd->mpm); | 690 | message_destroy (&(mpm->message), mpm); |
782 | bio_destroy (&(mpd->mpm->bio)); | 691 | free (mpm); |
783 | free (mpd->mpm); | ||
784 | mpd->mpm = NULL; | ||
785 | return status; | 692 | return status; |
786 | } | 693 | } |
787 | message_set_attribute (mpd->mpm->message, attribute, mpd->mpm); | 694 | attribute_set_get_flags (attribute, pop_get_flags, mpm); |
695 | message_set_attribute (mpm->message, attribute, mpm); | ||
788 | } | 696 | } |
789 | 697 | ||
790 | /* Create the body. */ | 698 | /* Create the body and its stream. */ |
791 | { | 699 | { |
792 | stream_t stream; | 700 | stream_t stream; |
793 | body_t body; | 701 | body_t body; |
794 | status = body_create (&body, mpd->mpm); | 702 | status = body_create (&body, mpm); |
795 | if (status != 0) | 703 | if (status != 0) |
796 | { | 704 | { |
797 | message_destroy (&(mpd->mpm->message), mpd->mpm); | 705 | message_destroy (&(mpm->message), mpm); |
798 | bio_destroy (&(mpd->mpm->bio)); | 706 | free (mpm); |
799 | free (mpd->mpm); | ||
800 | mpd->mpm = NULL; | ||
801 | return status; | 707 | return status; |
802 | } | 708 | } |
803 | message_set_body (mpd->mpm->message, body, mpd->mpm); | 709 | status = stream_create (&stream, MU_STREAM_READ, mpm); |
804 | status = stream_create (&stream, MU_STREAM_READ, mpd->mpm); | ||
805 | if (status != 0) | 710 | if (status != 0) |
806 | { | 711 | { |
807 | message_destroy (&(mpd->mpm->message), mpd->mpm); | 712 | message_destroy (&(mpm->message), mpm); |
808 | bio_destroy (&(mpd->mpm->bio)); | 713 | free (mpm); |
809 | free (mpd->mpm); | ||
810 | mpd->mpm = NULL; | ||
811 | return status; | 714 | return status; |
812 | } | 715 | } |
813 | stream_set_read (stream, mailbox_pop_readstream, mpd->mpm); | 716 | stream_set_read (stream, pop_readstream, mpm); |
814 | stream_set_fd (stream, mailbox_pop_getfd, mpd->mpm); | 717 | stream_set_fd (stream, pop_get_fd, mpm); |
815 | stream_set_flags (stream, mpd->flags, mpd->mpm); | 718 | stream_set_flags (stream, mpd->flags, mpm); |
816 | body_set_size (body, mailbox_pop_body_size, mpd->mpm); | 719 | body_set_size (body, pop_body_size, mpm); |
817 | //body_set_lines (body, mailbox_pop_body_lines, mpd->mpm); | 720 | body_set_lines (body, pop_body_lines, mpm); |
818 | body_set_stream (body, stream, mpd->mpm); | 721 | body_set_stream (body, stream, mpm); |
722 | message_set_body (mpm->message, body, mpm); | ||
819 | } | 723 | } |
820 | 724 | ||
725 | /* Set the UIDL call on the message. */ | ||
726 | message_set_uidl (mpm->message, pop_uidl, mpm); | ||
727 | |||
821 | /* Add it to the list. */ | 728 | /* Add it to the list. */ |
822 | { | 729 | { |
823 | mailbox_pop_message_t *m ; | 730 | pop_message_t *m ; |
824 | m = realloc (mpd->pmessages, (mpd->pmessages_count + 1)*sizeof (*m)); | 731 | m = realloc (mpd->pmessages, (mpd->pmessages_count + 1)*sizeof (*m)); |
825 | if (m == NULL) | 732 | if (m == NULL) |
826 | { | 733 | { |
827 | message_destroy (&(mpd->mpm->message), mpd->mpm); | 734 | message_destroy (&(mpm->message), mpm); |
828 | free (mpd->mpm); | 735 | free (mpm); |
829 | mpd->mpm = NULL; | ||
830 | return ENOMEM; | 736 | return ENOMEM; |
831 | } | 737 | } |
832 | mpd->pmessages = m; | 738 | mpd->pmessages = m; |
833 | mpd->pmessages[mpd->pmessages_count] = mpd->mpm; | 739 | mpd->pmessages[mpd->pmessages_count] = mpm; |
834 | mpd->pmessages_count++; | 740 | mpd->pmessages_count++; |
835 | } | 741 | } |
836 | 742 | ||
837 | *pmsg = mpd->mpm->message; | 743 | *pmsg = mpm->message; |
838 | 744 | ||
839 | return 0; | 745 | return 0; |
840 | } | 746 | } |
841 | 747 | ||
842 | static int | 748 | static int |
843 | mailbox_pop_messages_count (mailbox_t mbox, size_t *pcount) | 749 | pop_messages_count (mailbox_t mbox, size_t *pcount) |
844 | { | 750 | { |
845 | mailbox_pop_data_t mpd; | 751 | pop_data_t mpd; |
846 | int status; | 752 | int status; |
847 | void *func = (void *)mailbox_pop_messages_count; | 753 | void *func = (void *)pop_messages_count; |
848 | bio_t bio; | 754 | bio_t bio; |
849 | 755 | ||
850 | if (mbox == NULL || (mpd = (mailbox_pop_data_t)mbox->data) == NULL) | 756 | if (mbox == NULL || (mpd = (pop_data_t)mbox->data) == NULL) |
851 | return EINVAL; | 757 | return EINVAL; |
852 | 758 | ||
853 | if (mailbox_pop_is_updated (mbox)) | 759 | if (pop_is_updated (mbox)) |
854 | { | 760 | { |
855 | if (pcount) | 761 | if (pcount) |
856 | *pcount = mpd->messages_count; | 762 | *pcount = mpd->messages_count; |
... | @@ -862,34 +768,39 @@ mailbox_pop_messages_count (mailbox_t mbox, size_t *pcount) | ... | @@ -862,34 +768,39 @@ mailbox_pop_messages_count (mailbox_t mbox, size_t *pcount) |
862 | 768 | ||
863 | mpd->func = func; | 769 | mpd->func = func; |
864 | bio = mpd->bio; | 770 | bio = mpd->bio; |
771 | |||
772 | /* TRANSACTION state. */ | ||
865 | switch (mpd->state) | 773 | switch (mpd->state) |
866 | { | 774 | { |
867 | case 0: | 775 | case POP_NO_STATE: |
868 | bio->len = sprintf (bio->buffer, "STAT\r\n"); | 776 | bio->len = sprintf (bio->buffer, "STAT\r\n"); |
869 | bio->ptr = bio->buffer; | 777 | bio->ptr = bio->buffer; |
870 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_PROT, bio->buffer); | 778 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_PROT, bio->buffer); |
871 | mpd->state = 1; | 779 | mpd->state = POP_STAT_TX; |
780 | |||
781 | case POP_STAT_TX: | ||
872 | /* Send the STAT. */ | 782 | /* Send the STAT. */ |
873 | case 1: | ||
874 | status = bio_write (bio); | 783 | status = bio_write (bio); |
875 | if (status != 0) | 784 | CHECK_NON_RECOVERABLE (mpd, status); |
876 | return status; | 785 | mpd->state = POP_STAT_ACK; |
877 | mpd->state = 2; | 786 | |
787 | case POP_STAT_ACK: | ||
878 | /* Get the ACK. */ | 788 | /* Get the ACK. */ |
879 | case 2: | ||
880 | status = bio_readline (bio); | 789 | status = bio_readline (bio); |
881 | if (status != 0) | 790 | CHECK_NON_RECOVERABLE (mpd, status); |
882 | return status; | ||
883 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_PROT, bio->buffer); | 791 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_PROT, bio->buffer); |
884 | break; | 792 | break; |
885 | default: | 793 | default: |
886 | fprintf (stderr, "unknow state(messages_count)\n"); | 794 | /* |
795 | fprintf (stderr, "pomp_messages_count: unknow state\n"); | ||
796 | */ | ||
887 | } | 797 | } |
888 | mpd->id = mpd->func = NULL; | ||
889 | mpd->state = 0; | ||
890 | 798 | ||
891 | status = sscanf (bio->buffer, "+OK %d %d", &(mpd->messages_count), | 799 | status = sscanf (bio->buffer, "+OK %d %d", &(mpd->messages_count), |
892 | &(mpd->size)); | 800 | &(mpd->size)); |
801 | |||
802 | CLEAR_STATE (mpd); | ||
803 | |||
893 | mpd->is_updated = 1; | 804 | mpd->is_updated = 1; |
894 | if (pcount) | 805 | if (pcount) |
895 | *pcount = mpd->messages_count; | 806 | *pcount = mpd->messages_count; |
... | @@ -901,23 +812,24 @@ mailbox_pop_messages_count (mailbox_t mbox, size_t *pcount) | ... | @@ -901,23 +812,24 @@ mailbox_pop_messages_count (mailbox_t mbox, size_t *pcount) |
901 | 812 | ||
902 | /* Update and scanning. */ | 813 | /* Update and scanning. */ |
903 | static int | 814 | static int |
904 | mailbox_pop_is_updated (mailbox_t mbox) | 815 | pop_is_updated (mailbox_t mbox) |
905 | { | 816 | { |
906 | mailbox_pop_data_t mpd; | 817 | pop_data_t mpd; |
907 | if ((mpd = (mailbox_pop_data_t)mbox->data) == NULL) | 818 | if ((mpd = (pop_data_t)mbox->data) == NULL) |
908 | return 0; | 819 | return 0; |
909 | return mpd->is_updated; | 820 | return mpd->is_updated; |
910 | } | 821 | } |
911 | 822 | ||
912 | static int | 823 | static int |
913 | mailbox_pop_num_deleted (mailbox_t mbox, size_t *pnum) | 824 | pop_num_deleted (mailbox_t mbox, size_t *pnum) |
914 | { | 825 | { |
915 | mailbox_pop_data_t mpd; | 826 | pop_data_t mpd; |
916 | size_t i, total; | 827 | size_t i, total; |
917 | attribute_t attr; | 828 | attribute_t attr; |
918 | if (mbox == NULL || | 829 | |
919 | (mpd = (mailbox_pop_data_t) mbox->data) == NULL) | 830 | if (mbox == NULL || (mpd = (pop_data_t) mbox->data) == NULL) |
920 | return EINVAL; | 831 | return EINVAL; |
832 | |||
921 | for (i = total = 0; i < mpd->messages_count; i++) | 833 | for (i = total = 0; i < mpd->messages_count; i++) |
922 | { | 834 | { |
923 | if (message_get_attribute (mpd->pmessages[i]->message, &attr) != 0) | 835 | if (message_get_attribute (mpd->pmessages[i]->message, &attr) != 0) |
... | @@ -934,11 +846,12 @@ mailbox_pop_num_deleted (mailbox_t mbox, size_t *pnum) | ... | @@ -934,11 +846,12 @@ mailbox_pop_num_deleted (mailbox_t mbox, size_t *pnum) |
934 | 846 | ||
935 | /* We just simulated. */ | 847 | /* We just simulated. */ |
936 | static int | 848 | static int |
937 | mailbox_pop_scan (mailbox_t mbox, size_t msgno, size_t *pcount) | 849 | pop_scan (mailbox_t mbox, size_t msgno, size_t *pcount) |
938 | { | 850 | { |
939 | int status; | 851 | int status; |
940 | size_t i; | 852 | size_t i; |
941 | status = mailbox_pop_messages_count (mbox, pcount); | 853 | |
854 | status = pop_messages_count (mbox, pcount); | ||
942 | if (status != 0) | 855 | if (status != 0) |
943 | return status; | 856 | return status; |
944 | for (i = msgno; i <= *pcount; i++) | 857 | for (i = msgno; i <= *pcount; i++) |
... | @@ -949,17 +862,16 @@ mailbox_pop_scan (mailbox_t mbox, size_t msgno, size_t *pcount) | ... | @@ -949,17 +862,16 @@ mailbox_pop_scan (mailbox_t mbox, size_t msgno, size_t *pcount) |
949 | 862 | ||
950 | /* This were we actually sending the DELE command. */ | 863 | /* This were we actually sending the DELE command. */ |
951 | static int | 864 | static int |
952 | mailbox_pop_expunge (mailbox_t mbox) | 865 | pop_expunge (mailbox_t mbox) |
953 | { | 866 | { |
954 | mailbox_pop_data_t mpd; | 867 | pop_data_t mpd; |
955 | size_t i; | 868 | size_t i; |
956 | attribute_t attr; | 869 | attribute_t attr; |
957 | bio_t bio; | 870 | bio_t bio; |
958 | int status; | 871 | int status; |
959 | void *func = (void *)mailbox_pop_expunge; | 872 | void *func = (void *)pop_expunge; |
960 | 873 | ||
961 | if (mbox == NULL || | 874 | if (mbox == NULL || (mpd = (pop_data_t) mbox->data) == NULL) |
962 | (mpd = (mailbox_pop_data_t) mbox->data) == NULL) | ||
963 | return EINVAL; | 875 | return EINVAL; |
964 | 876 | ||
965 | /* Busy ? */ | 877 | /* Busy ? */ |
... | @@ -969,94 +881,96 @@ mailbox_pop_expunge (mailbox_t mbox) | ... | @@ -969,94 +881,96 @@ mailbox_pop_expunge (mailbox_t mbox) |
969 | mpd->func = func; | 881 | mpd->func = func; |
970 | bio = mpd->bio; | 882 | bio = mpd->bio; |
971 | 883 | ||
972 | for (i = (int)mpd->id; i < mpd->pmessages_count; mpd->id = (void *)++i) | 884 | for (i = (int)mpd->id; i < mpd->pmessages_count; mpd->id = ++i) |
973 | { | 885 | { |
974 | if (message_get_attribute (mpd->pmessages[i]->message, &attr) == 0) | 886 | if (message_get_attribute (mpd->pmessages[i]->message, &attr) == 0) |
975 | { | 887 | { |
976 | /* Send DELETE. */ | ||
977 | if (attribute_is_deleted (attr)) | 888 | if (attribute_is_deleted (attr)) |
978 | { | 889 | { |
979 | switch (mpd->state) | 890 | switch (mpd->state) |
980 | { | 891 | { |
981 | case 0: | 892 | case POP_NO_STATE: |
982 | bio->len = sprintf (bio->buffer, "DELE %d\r\n", | 893 | bio->len = sprintf (bio->buffer, "DELE %d\r\n", |
983 | mpd->pmessages[i]->num); | 894 | mpd->pmessages[i]->num); |
984 | bio->ptr = bio->buffer; | 895 | bio->ptr = bio->buffer; |
985 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_PROT, bio->buffer); | 896 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_PROT, bio->buffer); |
986 | mpd->state = 1; | 897 | mpd->state = POP_DELE_TX; |
987 | case 1: | 898 | |
899 | case POP_DELE_TX: | ||
900 | /* Send DELETE. */ | ||
988 | status = bio_write (bio); | 901 | status = bio_write (bio); |
989 | if (status != 0) | 902 | if (status != 0) |
990 | { | 903 | { |
904 | /* Clear the state for non recoverable error. */ | ||
991 | if (status != EAGAIN && status != EINTR) | 905 | if (status != EAGAIN && status != EINTR) |
992 | { | 906 | { |
993 | mpd->func = mpd->id = NULL; | 907 | mpd->func = NULL; |
994 | mpd->state = 0; | 908 | mpd->id = 0; |
995 | fprintf(stderr, "PROBLEM write %d\n", status); | 909 | mpd->state = POP_NO_STATE; |
996 | } | 910 | } |
997 | return status; | 911 | return status; |
998 | } | 912 | } |
999 | mpd->state = 2; | 913 | mpd->state = POP_DELE_ACK; |
1000 | case 2: | 914 | |
915 | case POP_DELE_ACK: | ||
1001 | status = bio_readline (bio); | 916 | status = bio_readline (bio); |
1002 | if (status != 0) | 917 | if (status != 0) |
1003 | { | 918 | { |
919 | /* Clear the state for non recoverable error. */ | ||
1004 | if (status != EAGAIN && status != EINTR) | 920 | if (status != EAGAIN && status != EINTR) |
1005 | { | 921 | { |
1006 | mpd->func = mpd->id = NULL; | 922 | mpd->func = NULL; |
1007 | mpd->state = 0; | 923 | mpd->id = 0; |
1008 | fprintf(stderr, "PROBLEM readline %d\n", status); | 924 | mpd->state = POP_NO_STATE; |
1009 | } | 925 | } |
1010 | return status; | 926 | return status; |
1011 | } | 927 | } |
1012 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_PROT, bio->buffer); | 928 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_PROT, bio->buffer); |
1013 | if (strncasecmp (bio->buffer, "+OK", 3) != 0) | 929 | if (strncasecmp (bio->buffer, "+OK", 3) != 0) |
1014 | { | 930 | { |
1015 | mpd->func = mpd->id = NULL; | 931 | mpd->func = NULL; |
1016 | mpd->state = 0; | 932 | mpd->id = 0; |
1017 | fprintf(stderr, "PROBLEM strcmp\n"); | 933 | mpd->state = POP_NO_STATE; |
1018 | return ERANGE; | 934 | return ERANGE; |
1019 | } | 935 | } |
1020 | mpd->state = 0; | 936 | mpd->state = POP_NO_STATE; |
937 | break; | ||
938 | default: | ||
939 | /* fprintf (stderr, "pop_expunge: unknow state\n"); */ | ||
1021 | } /* switch (state) */ | 940 | } /* switch (state) */ |
1022 | } /* if attribute_is_deleted() */ | 941 | } /* if attribute_is_deleted() */ |
1023 | } /* message_get_attribute() */ | 942 | } /* message_get_attribute() */ |
1024 | } /* for */ | 943 | } /* for */ |
1025 | mpd->func = mpd->id = NULL; | 944 | mpd->id = 0; |
1026 | mpd->state = 0; | 945 | mpd->func = NULL; |
1027 | /* Invalidate. */ | 946 | mpd->state = POP_NO_STATE; |
947 | /* Invalidate. But Really they should shutdown the challen POP protocol | ||
948 | is not meant for this like IMAP. */ | ||
1028 | mpd->is_updated = 0; | 949 | mpd->is_updated = 0; |
1029 | |||
1030 | return 0; | 950 | return 0; |
1031 | } | 951 | } |
1032 | 952 | ||
1033 | /* Mailbox size ? */ | 953 | /* Mailbox size ? */ |
1034 | static int | 954 | static int |
1035 | mailbox_pop_size (mailbox_t mbox, off_t *psize) | 955 | pop_size (mailbox_t mbox, off_t *psize) |
1036 | { | 956 | { |
1037 | mailbox_pop_data_t mpd; | 957 | pop_data_t mpd; |
1038 | size_t count; | 958 | int status = 0; |
1039 | int status; | ||
1040 | 959 | ||
1041 | if (mbox == NULL || (mpd = (mailbox_pop_data_t)mbox->data) == NULL) | 960 | if (mbox == NULL || (mpd = (pop_data_t)mbox->data) == NULL) |
1042 | return EINVAL; | 961 | return EINVAL; |
1043 | 962 | ||
1044 | if (mailbox_pop_is_updated (mbox)) | 963 | if (! pop_is_updated (mbox)) |
1045 | { | 964 | status = pop_messages_count (mbox, &mpd->size); |
1046 | if (psize) | ||
1047 | *psize = mpd->size; | ||
1048 | return 0; | ||
1049 | } | ||
1050 | status = mailbox_pop_messages_count (mbox, &count); | ||
1051 | if (psize) | 965 | if (psize) |
1052 | *psize = mpd->size; | 966 | *psize = mpd->size; |
1053 | return status; | 967 | return status; |
1054 | } | 968 | } |
1055 | 969 | ||
1056 | static int | 970 | static int |
1057 | mailbox_pop_body_size (body_t body, size_t *psize) | 971 | pop_body_size (body_t body, size_t *psize) |
1058 | { | 972 | { |
1059 | mailbox_pop_message_t mpm; | 973 | pop_message_t mpm; |
1060 | if (body == NULL || (mpm = body->owner) == NULL) | 974 | if (body == NULL || (mpm = body->owner) == NULL) |
1061 | return EINVAL; | 975 | return EINVAL; |
1062 | if (psize) | 976 | if (psize) |
... | @@ -1065,29 +979,235 @@ mailbox_pop_body_size (body_t body, size_t *psize) | ... | @@ -1065,29 +979,235 @@ mailbox_pop_body_size (body_t body, size_t *psize) |
1065 | } | 979 | } |
1066 | 980 | ||
1067 | static int | 981 | static int |
1068 | mailbox_pop_getfd (stream_t stream, int *pfd) | 982 | pop_body_lines (body_t body, size_t *plines) |
983 | { | ||
984 | pop_message_t mpm; | ||
985 | if (body == NULL || (mpm = body->owner) == NULL) | ||
986 | return EINVAL; | ||
987 | if (plines) | ||
988 | *plines = mpm->body_lines; | ||
989 | return 0; | ||
990 | } | ||
991 | |||
992 | static int | ||
993 | pop_get_flags (attribute_t attr, int *pflags) | ||
1069 | { | 994 | { |
1070 | mailbox_pop_message_t mpm; | 995 | pop_message_t mpm; |
996 | char hdr_status[64]; | ||
997 | header_t header = NULL; | ||
998 | int err; | ||
999 | |||
1000 | if (attr == NULL || (mpm = attr->owner) == NULL) | ||
1001 | return EINVAL; | ||
1002 | hdr_status[0] = '\0'; | ||
1003 | message_get_header (mpm->message, &header); | ||
1004 | err = header_get_value (header, "Status", | ||
1005 | hdr_status, sizeof (hdr_status), NULL); | ||
1006 | if (err != 0) | ||
1007 | err = string_to_flags (hdr_status, pflags); | ||
1008 | return err; | ||
1009 | } | ||
1010 | |||
1011 | static int | ||
1012 | pop_get_fd (stream_t stream, int *pfd) | ||
1013 | { | ||
1014 | pop_message_t mpm; | ||
1071 | if (stream == NULL || (mpm = stream->owner) == NULL) | 1015 | if (stream == NULL || (mpm = stream->owner) == NULL) |
1072 | return EINVAL; | 1016 | return EINVAL; |
1073 | return stream_get_fd (mpm->bio->stream, pfd); | 1017 | if (mpm->mpd->bio) |
1018 | return stream_get_fd (mpm->mpd->bio->stream, pfd); | ||
1019 | return EINVAL; | ||
1020 | } | ||
1021 | |||
1022 | static int | ||
1023 | pop_uidl (message_t msg, char *buffer, size_t buflen, size_t *pnwriten) | ||
1024 | { | ||
1025 | pop_message_t mpm; | ||
1026 | pop_data_t mpd; | ||
1027 | bio_t bio; | ||
1028 | int status = 0; | ||
1029 | void *func = (void *)pop_uidl; | ||
1030 | size_t num; | ||
1031 | /* According to the RFC uidl's are no longer then 70 chars. */ | ||
1032 | char uniq[128]; | ||
1033 | |||
1034 | if (msg == NULL || (mpm = msg->owner) == NULL) | ||
1035 | return EINVAL; | ||
1036 | |||
1037 | mpd = mpm->mpd; | ||
1038 | bio = mpd->bio; | ||
1039 | |||
1040 | /* Busy ? */ | ||
1041 | if (mpd->func && mpd->func != func) | ||
1042 | return EBUSY; | ||
1043 | |||
1044 | mpd->func = func; | ||
1045 | |||
1046 | /* Get the UIDL. */ | ||
1047 | switch (mpd->state) | ||
1048 | { | ||
1049 | case POP_NO_STATE: | ||
1050 | bio->len = sprintf (bio->buffer, "UIDL %d\r\n", mpm->num); | ||
1051 | bio->ptr = bio->buffer; | ||
1052 | mailbox_debug (mpd->mbox, MU_MAILBOX_DEBUG_PROT, bio->buffer); | ||
1053 | mpd->state = POP_UIDL_TX; | ||
1054 | |||
1055 | case POP_UIDL_TX: | ||
1056 | /* Send the UIDL. */ | ||
1057 | status = bio_write (bio); | ||
1058 | CHECK_NON_RECOVERABLE (mpd, status); | ||
1059 | mpd->state = POP_UIDL_ACK; | ||
1060 | |||
1061 | case POP_UIDL_ACK: | ||
1062 | /* Resp from TOP. */ | ||
1063 | status = bio_readline (bio); | ||
1064 | CHECK_NON_RECOVERABLE (mpd, status); | ||
1065 | mailbox_debug (mpd->mbox, MU_MAILBOX_DEBUG_PROT, bio->buffer); | ||
1066 | break; | ||
1067 | default: | ||
1068 | /* | ||
1069 | fprintf (stderr, "pop_uidl state\n"); | ||
1070 | */ | ||
1071 | } | ||
1072 | |||
1073 | CLEAR_STATE (mpd); | ||
1074 | |||
1075 | *uniq = '\0'; | ||
1076 | status = sscanf (bio->buffer, "+OK %d %127s\n", &num, uniq); | ||
1077 | if (status != 2) | ||
1078 | { | ||
1079 | status = EINVAL; | ||
1080 | buflen = 0; | ||
1081 | } | ||
1082 | else | ||
1083 | { | ||
1084 | num = strlen (uniq); | ||
1085 | uniq[num - 1] = '\0'; /* Nuke newline. */ | ||
1086 | buflen = (buflen < num) ? buflen : num; | ||
1087 | memcpy (buffer, uniq, buflen); | ||
1088 | buffer [buflen - 1] = '\0'; | ||
1089 | status = 0; | ||
1090 | } | ||
1091 | if (pnwriten) | ||
1092 | *pnwriten = buflen; | ||
1093 | return status; | ||
1094 | } | ||
1095 | |||
1096 | static int | ||
1097 | pop_header_read (stream_t is, char *buffer, size_t buflen, | ||
1098 | off_t offset, size_t *pnread) | ||
1099 | { | ||
1100 | pop_message_t mpm; | ||
1101 | pop_data_t mpd; | ||
1102 | bio_t bio; | ||
1103 | size_t nread = 0; | ||
1104 | int status = 0; | ||
1105 | void *func = (void *)pop_header_read; | ||
1106 | |||
1107 | if (is == NULL || (mpm = is->owner) == NULL) | ||
1108 | return EINVAL; | ||
1109 | |||
1110 | (void)offset; | ||
1111 | mpd = mpm->mpd; | ||
1112 | bio = mpd->bio; | ||
1113 | |||
1114 | /* Busy ? */ | ||
1115 | if (mpd->func && mpd->func != func) | ||
1116 | return EBUSY; | ||
1117 | |||
1118 | mpd->func = func; | ||
1119 | |||
1120 | /* Get the header. */ | ||
1121 | switch (mpd->state) | ||
1122 | { | ||
1123 | case POP_NO_STATE: | ||
1124 | /* TOP is an optionnal command, if we want to be compliant we can not | ||
1125 | count on it to exists. So we should be prepare when it fails and | ||
1126 | fall to a second scheme. */ | ||
1127 | bio->len = sprintf (bio->buffer, "TOP %d 0\r\n", mpm->num); | ||
1128 | bio->ptr = bio->buffer; | ||
1129 | mailbox_debug (mpd->mbox, MU_MAILBOX_DEBUG_PROT, bio->buffer); | ||
1130 | mpd->state = POP_TOP_TX; | ||
1131 | |||
1132 | case POP_TOP_TX: | ||
1133 | /* Send the TOP. */ | ||
1134 | status = bio_write (bio); | ||
1135 | CHECK_NON_RECOVERABLE (mpd, status); | ||
1136 | mpd->state = POP_TOP_ACK; | ||
1137 | |||
1138 | case POP_TOP_ACK: | ||
1139 | /* Ack from TOP. */ | ||
1140 | status = bio_readline (bio); | ||
1141 | CHECK_NON_RECOVERABLE (mpd, status); | ||
1142 | mailbox_debug (mpd->mbox, MU_MAILBOX_DEBUG_PROT, bio->buffer); | ||
1143 | if (strncasecmp (bio->buffer, "+OK", 3) != 0) | ||
1144 | { | ||
1145 | fprintf (stderr, "TOP not implmented\n"); | ||
1146 | CLEAR_STATE (mpd); | ||
1147 | return ENOSYS; | ||
1148 | } | ||
1149 | mpd->state = POP_TOP_RX; | ||
1150 | bio->current = bio->nl; | ||
1151 | |||
1152 | case POP_TOP_RX: | ||
1153 | /* Get the header. */ | ||
1154 | { | ||
1155 | int nleft, n; | ||
1156 | /* Do we need to fill up. */ | ||
1157 | if (bio->current >= bio->nl) | ||
1158 | { | ||
1159 | bio->current = bio->buffer; | ||
1160 | status = bio_readline (bio); | ||
1161 | CHECK_NON_RECOVERABLE (mpd, status); | ||
1162 | } | ||
1163 | n = bio->nl - bio->current; | ||
1164 | nleft = buflen - n; | ||
1165 | /* We got more then requested. */ | ||
1166 | if (nleft <= 0) | ||
1167 | { | ||
1168 | memcpy (buffer, bio->current, buflen); | ||
1169 | bio->current += buflen; | ||
1170 | nread = buflen; | ||
1171 | } | ||
1172 | else | ||
1173 | { | ||
1174 | /* Drain the buffer. */ | ||
1175 | memcpy (buffer, bio->current, n); | ||
1176 | bio->current += n; | ||
1177 | nread = n; | ||
1178 | } | ||
1179 | break; | ||
1180 | } | ||
1181 | break; | ||
1182 | default: | ||
1183 | /* fprintf (stderr, "pop_header_blurb unknown state\n"); */ | ||
1184 | } /* switch (state) */ | ||
1185 | |||
1186 | if (nread == 0) | ||
1187 | { | ||
1188 | CLEAR_STATE (mpd); | ||
1189 | } | ||
1190 | if (pnread) | ||
1191 | *pnread = nread; | ||
1192 | return 0; | ||
1074 | } | 1193 | } |
1075 | 1194 | ||
1076 | static int | 1195 | static int |
1077 | mailbox_pop_readstream (stream_t is, char *buffer, size_t buflen, | 1196 | pop_readstream (stream_t is, char *buffer, size_t buflen, |
1078 | off_t offset, size_t *pnread) | 1197 | off_t offset, size_t *pnread) |
1079 | { | 1198 | { |
1080 | mailbox_pop_message_t mpm; | 1199 | pop_message_t mpm; |
1081 | mailbox_pop_data_t mpd; | 1200 | pop_data_t mpd; |
1082 | size_t nread = 0; | 1201 | size_t nread = 0; |
1083 | bio_t bio; | 1202 | bio_t bio; |
1084 | int status = 0; | 1203 | int status = 0; |
1085 | void *func = (void *)mailbox_pop_readstream; | 1204 | void *func = (void *)pop_readstream; |
1086 | 1205 | ||
1087 | (void)offset; | 1206 | (void)offset; |
1088 | if (is == NULL || (mpm = is->owner) == NULL) | 1207 | if (is == NULL || (mpm = is->owner) == NULL) |
1089 | return EINVAL; | 1208 | return EINVAL; |
1090 | 1209 | ||
1210 | /* Take care of the obvious. */ | ||
1091 | if (buffer == NULL || buflen == 0) | 1211 | if (buffer == NULL || buflen == 0) |
1092 | { | 1212 | { |
1093 | if (pnread) | 1213 | if (pnread) |
... | @@ -1095,67 +1215,44 @@ mailbox_pop_readstream (stream_t is, char *buffer, size_t buflen, | ... | @@ -1095,67 +1215,44 @@ mailbox_pop_readstream (stream_t is, char *buffer, size_t buflen, |
1095 | return 0; | 1215 | return 0; |
1096 | } | 1216 | } |
1097 | 1217 | ||
1098 | bio = mpm->bio; | ||
1099 | mpd = mpm->mpd; | 1218 | mpd = mpm->mpd; |
1219 | bio = mpd->bio; | ||
1100 | 1220 | ||
1101 | /* Busy ? */ | 1221 | /* Busy ? */ |
1102 | if (mpd->func && mpd->func != func) | 1222 | if (mpd->func && mpd->func != func) |
1103 | return EBUSY; | 1223 | return EBUSY; |
1104 | 1224 | ||
1105 | /* Which request. */ | ||
1106 | if (mpd->id && mpd->id != mpm) | ||
1107 | return EBUSY; | ||
1108 | |||
1109 | mpd->func = func; | 1225 | mpd->func = func; |
1110 | mpd->id = mpm; | ||
1111 | 1226 | ||
1112 | switch (mpd->state) | 1227 | switch (mpd->state) |
1113 | { | 1228 | { |
1114 | /* Send the RETR command. */ | 1229 | case POP_NO_STATE: |
1115 | case 0: | ||
1116 | bio->len = sprintf (bio->buffer, "RETR %d\r\n", mpm->num); | 1230 | bio->len = sprintf (bio->buffer, "RETR %d\r\n", mpm->num); |
1117 | mpd->state = 1; | 1231 | mpd->state = POP_RETR_TX; |
1118 | case 1: | 1232 | |
1233 | case POP_RETR_TX: | ||
1234 | /* Send the RETR command. */ | ||
1119 | status = bio_write (bio); | 1235 | status = bio_write (bio); |
1120 | if (status != 0) | 1236 | CHECK_NON_RECOVERABLE (mpd, status); |
1121 | { | 1237 | mpd->state = POP_RETR_ACK; |
1122 | if (status != EAGAIN && status != EINTR) | 1238 | |
1123 | { | 1239 | case POP_RETR_ACK: |
1124 | mpd->func = mpd->id = NULL; | ||
1125 | mpd->state = 0; | ||
1126 | } | ||
1127 | return status; | ||
1128 | } | ||
1129 | mpd->state = 2; | ||
1130 | /* RETR ACK. */ | 1240 | /* RETR ACK. */ |
1131 | case 2: | ||
1132 | status = bio_readline (bio); | 1241 | status = bio_readline (bio); |
1133 | if (status != 0) | 1242 | CHECK_NON_RECOVERABLE (mpd, status); |
1134 | { | 1243 | if (strncasecmp (bio->buffer, "+OK", 3) != 0) |
1135 | if (status != EAGAIN && status != EINTR) | ||
1136 | { | 1244 | { |
1137 | mpd->func = mpd->id = NULL; | 1245 | CLEAR_STATE (mpd); |
1138 | mpd->state = 0; | 1246 | return EACCES; |
1139 | } | ||
1140 | return status; | ||
1141 | } | 1247 | } |
1142 | if (strncasecmp (bio->buffer, "+OK", 3) != 0) | 1248 | mpd->state = POP_RETR_RX_HDR; |
1143 | return EINVAL; | 1249 | |
1144 | mpd->state = 3; | 1250 | case POP_RETR_RX_HDR: |
1145 | /* Skip the header. */ | 1251 | /* Skip the header. */ |
1146 | case 3: | ||
1147 | while (!mpm->inbody) | 1252 | while (!mpm->inbody) |
1148 | { | 1253 | { |
1149 | status = bio_readline (bio); | 1254 | status = bio_readline (bio); |
1150 | if (status != 0) | 1255 | CHECK_NON_RECOVERABLE (mpd, status); |
1151 | { | ||
1152 | if (status != EAGAIN && status != EINTR) | ||
1153 | { | ||
1154 | mpd->func = mpd->id = NULL; | ||
1155 | mpd->state = 0; | ||
1156 | } | ||
1157 | return status; | ||
1158 | } | ||
1159 | if (bio->buffer[0] == '\n') | 1256 | if (bio->buffer[0] == '\n') |
1160 | { | 1257 | { |
1161 | mpm->inbody = 1; | 1258 | mpm->inbody = 1; |
... | @@ -1164,10 +1261,11 @@ mailbox_pop_readstream (stream_t is, char *buffer, size_t buflen, | ... | @@ -1164,10 +1261,11 @@ mailbox_pop_readstream (stream_t is, char *buffer, size_t buflen, |
1164 | } | 1261 | } |
1165 | /* Skip the newline. */ | 1262 | /* Skip the newline. */ |
1166 | bio_readline (bio); | 1263 | bio_readline (bio); |
1167 | /* Start taking the header. */ | 1264 | bio->current = bio->current; |
1168 | mpd->state = 4; | 1265 | mpd->state = POP_RETR_RX_BODY; |
1169 | bio->current = bio->buffer; | 1266 | |
1170 | case 4: | 1267 | case POP_RETR_RX_BODY: |
1268 | /* Start taking the body. */ | ||
1171 | { | 1269 | { |
1172 | int nleft, n; | 1270 | int nleft, n; |
1173 | /* Do we need to fill up. */ | 1271 | /* Do we need to fill up. */ |
... | @@ -1175,14 +1273,7 @@ mailbox_pop_readstream (stream_t is, char *buffer, size_t buflen, | ... | @@ -1175,14 +1273,7 @@ mailbox_pop_readstream (stream_t is, char *buffer, size_t buflen, |
1175 | { | 1273 | { |
1176 | bio->current = bio->buffer; | 1274 | bio->current = bio->buffer; |
1177 | status = bio_readline (bio); | 1275 | status = bio_readline (bio); |
1178 | if (status != 0) | 1276 | CHECK_NON_RECOVERABLE (mpd, status); |
1179 | { | ||
1180 | if (status != EAGAIN && status != EINTR) | ||
1181 | { | ||
1182 | mpd->func = mpd->id = NULL; | ||
1183 | mpd->state = 0; | ||
1184 | } | ||
1185 | } | ||
1186 | } | 1277 | } |
1187 | n = bio->nl - bio->current; | 1278 | n = bio->nl - bio->current; |
1188 | nleft = buflen - n; | 1279 | nleft = buflen - n; |
... | @@ -1200,13 +1291,15 @@ mailbox_pop_readstream (stream_t is, char *buffer, size_t buflen, | ... | @@ -1200,13 +1291,15 @@ mailbox_pop_readstream (stream_t is, char *buffer, size_t buflen, |
1200 | bio->current += n; | 1291 | bio->current += n; |
1201 | nread = n; | 1292 | nread = n; |
1202 | } | 1293 | } |
1294 | break; | ||
1203 | } | 1295 | } |
1296 | default: | ||
1297 | /* fprintf (stderr, "pop_readstream unknow state\n"); */ | ||
1204 | } /* Switch state. */ | 1298 | } /* Switch state. */ |
1205 | 1299 | ||
1206 | if (nread == 0) | 1300 | if (nread == 0) |
1207 | { | 1301 | { |
1208 | mpd->func = mpd->id = NULL; | 1302 | CLEAR_STATE (mpd); |
1209 | mpd->state = 0; | ||
1210 | } | 1303 | } |
1211 | if (pnread) | 1304 | if (pnread) |
1212 | *pnread = nread; | 1305 | *pnread = nread; |
... | @@ -1221,12 +1314,7 @@ bio_create (bio_t *pbio, stream_t stream) | ... | @@ -1221,12 +1314,7 @@ bio_create (bio_t *pbio, stream_t stream) |
1221 | if (bio == NULL) | 1314 | if (bio == NULL) |
1222 | return ENOMEM; | 1315 | return ENOMEM; |
1223 | bio->maxlen = POP_BUFSIZ + 1; | 1316 | bio->maxlen = POP_BUFSIZ + 1; |
1224 | bio->current = bio->ptr = bio->buffer = calloc (1, POP_BUFSIZ + 1); | 1317 | bio->current = bio->ptr = bio->buffer = calloc (1, bio->maxlen); |
1225 | if (bio->buffer == NULL) | ||
1226 | { | ||
1227 | free (bio); | ||
1228 | return ENOMEM; | ||
1229 | } | ||
1230 | bio->stream = stream; | 1318 | bio->stream = stream; |
1231 | *pbio = bio; | 1319 | *pbio = bio; |
1232 | return 0; | 1320 | return 0; |
... | @@ -1273,8 +1361,8 @@ bio_read (bio_t bio) | ... | @@ -1273,8 +1361,8 @@ bio_read (bio_t bio) |
1273 | status = stream_read (bio->stream, bio->ptr, len, 0, &nread); | 1361 | status = stream_read (bio->stream, bio->ptr, len, 0, &nread); |
1274 | if (status != 0) | 1362 | if (status != 0) |
1275 | return status; | 1363 | return status; |
1276 | else if (nread == 0) | 1364 | else if (nread == 0) /* EOF ???? We got a situation here ??? */ |
1277 | { /* EOF ???? We got a situation here ??? */ | 1365 | { |
1278 | bio->buffer[0] = '.'; | 1366 | bio->buffer[0] = '.'; |
1279 | bio->buffer[1] = '\r'; | 1367 | bio->buffer[1] = '\r'; |
1280 | bio->buffer[2] = '\n'; | 1368 | bio->buffer[2] = '\n'; |
... | @@ -1312,7 +1400,7 @@ bio_readline (bio_t bio) | ... | @@ -1312,7 +1400,7 @@ bio_readline (bio_t bio) |
1312 | for (;;) | 1400 | for (;;) |
1313 | { | 1401 | { |
1314 | status = bio_read (bio); | 1402 | status = bio_read (bio); |
1315 | if (status < 0) | 1403 | if (status != 0) |
1316 | return status; | 1404 | return status; |
1317 | len = bio->ptr - bio->buffer; | 1405 | len = bio->ptr - bio->buffer; |
1318 | /* Newline. */ | 1406 | /* Newline. */ | ... | ... |
... | @@ -49,57 +49,57 @@ | ... | @@ -49,57 +49,57 @@ |
49 | #include <ctype.h> | 49 | #include <ctype.h> |
50 | #include <limits.h> | 50 | #include <limits.h> |
51 | 51 | ||
52 | static int mailbox_unix_create (mailbox_t *pmbox, const char *name); | 52 | #define ATTRIBUTE_IS_DELETED(flag) (flag & MU_ATTRIBUTE_DELETED) |
53 | static void mailbox_unix_destroy (mailbox_t *pmbox); | 53 | #define ATTRIBUTE_IS_EQUAL(flag1, flag2) (flag1 == flag2) |
54 | |||
55 | static int unix_create (mailbox_t *pmbox, const char *name); | ||
56 | static void unix_destroy (mailbox_t *pmbox); | ||
54 | 57 | ||
55 | struct mailbox_registrar _mailbox_unix_registrar = | 58 | struct mailbox_registrar _mailbox_unix_registrar = |
56 | { | 59 | { |
57 | "UNIX MBOX", | 60 | "UNIX MBOX", |
58 | mailbox_unix_create, mailbox_unix_destroy | 61 | unix_create, unix_destroy |
59 | }; | 62 | }; |
60 | 63 | ||
61 | /* | 64 | /* Keep the position of where the header and body starts and ends. |
62 | * Keep the position of where the header and body starts | 65 | old_flags is the "Status:" message. */ |
63 | * and ends. old_attr is the "Status:" message. | 66 | typedef struct _unix_message |
64 | */ | ||
65 | typedef struct _mailbox_unix_message | ||
66 | { | 67 | { |
67 | /* offset of the parts of the messages in the mailbox*/ | 68 | /* Offset of the parts of the messages in the mailbox. */ |
68 | off_t header_from; | 69 | off_t header_from; |
69 | off_t header_from_end; | 70 | off_t header_from_end; |
70 | /* little hack to make things easier | 71 | /* Little hack to make things easier * when updating the attribute. */ |
71 | * when updating the attribute | ||
72 | */ | ||
73 | off_t header_status; | 72 | off_t header_status; |
74 | off_t header_status_end; | 73 | off_t header_status_end; |
75 | off_t body; | 74 | off_t body; |
76 | off_t body_end; | 75 | off_t body_end; |
77 | 76 | ||
78 | /* old_attr contains the definition of Header: */ | 77 | /* The old_flags contains the definition of Header. */ |
79 | /* new_attr what we want when expunging */ | 78 | int old_flags; |
80 | attribute_t old_attr; | 79 | /* The new_flags holds the attributes changes for the current session. We |
81 | attribute_t new_attr; | 80 | use this so when expunging we can tell when an attribute been modified. |
81 | This is a big help so we can jump to the first modify email for speed | ||
82 | in expunging (see mark dirty). */ | ||
83 | int new_flags; | ||
82 | 84 | ||
83 | size_t header_lines; | 85 | size_t header_lines; |
84 | size_t body_lines; | 86 | size_t body_lines; |
85 | stream_t stream; | 87 | stream_t stream; |
86 | 88 | ||
87 | /* if we have a message attach to it */ | 89 | /* A message attach to it. */ |
88 | message_t message; | 90 | message_t message; |
89 | 91 | ||
90 | } *mailbox_unix_message_t; | 92 | } *unix_message_t; |
91 | 93 | ||
92 | /* | 94 | /* The umessages is an array of pointers that contains umessages_count of |
93 | * umessages is an array of pointers that contains umessages_count | 95 | unix_message_t*; umessages[umessages_count]. We do it this because |
94 | * of mailbox_unix_message_t*; umessages[umessages_count]. | 96 | realloc() can move everything to a new memory region and invalidating all |
95 | * We do it this because realloc() can move everything to | 97 | the pointers someone has on the messages. Thanks to <Dave Inglis> for |
96 | * a new memory region and invalidating all the pointers someone | 98 | pointing this out. The messages_count is the count number of messages |
97 | * has on the messages. Thanks to <Dave Inglis> for pointing this out. | 99 | parsed so far. */ |
98 | * messages_count is the count number of messages parsed so far. | 100 | typedef struct _unix_data |
99 | */ | ||
100 | typedef struct _mailbox_unix_data | ||
101 | { | 101 | { |
102 | mailbox_unix_message_t *umessages; | 102 | unix_message_t *umessages; |
103 | size_t umessages_count; | 103 | size_t umessages_count; |
104 | size_t messages_count; | 104 | size_t messages_count; |
105 | stream_t stream; | 105 | stream_t stream; |
... | @@ -110,59 +110,55 @@ typedef struct _mailbox_unix_data | ... | @@ -110,59 +110,55 @@ typedef struct _mailbox_unix_data |
110 | #endif | 110 | #endif |
111 | off_t size; | 111 | off_t size; |
112 | 112 | ||
113 | } *mailbox_unix_data_t; | 113 | } *unix_data_t; |
114 | |||
115 | static int mailbox_unix_open (mailbox_t mbox, int flag); | ||
116 | static int mailbox_unix_close (mailbox_t mbox); | ||
117 | |||
118 | static int mailbox_unix_get_message (mailbox_t, size_t msgno, message_t *msg); | ||
119 | static int mailbox_unix_append_message (mailbox_t, message_t msg); | ||
120 | static int mailbox_unix_messages_count (mailbox_t, size_t *msgno); | ||
121 | static int mailbox_unix_expunge (mailbox_t); | ||
122 | static int mailbox_unix_num_deleted (mailbox_t, size_t *); | ||
123 | 114 | ||
124 | static int mailbox_unix_scan0 (mailbox_t, size_t count, size_t *pcount, int); | 115 | static int unix_open (mailbox_t mbox, int flag); |
125 | static int mailbox_unix_scan (mailbox_t, size_t count, size_t *pcount); | 116 | static int unix_close (mailbox_t mbox); |
126 | static int mailbox_unix_is_updated (mailbox_t); | 117 | static int unix_get_message (mailbox_t, size_t msgno, message_t *msg); |
127 | 118 | static int unix_append_message (mailbox_t, message_t msg); | |
128 | static int mailbox_unix_size (mailbox_t, off_t *size); | 119 | static int unix_messages_count (mailbox_t, size_t *msgno); |
120 | static int unix_expunge (mailbox_t); | ||
121 | static int unix_num_deleted (mailbox_t, size_t *); | ||
122 | static int unix_scan (mailbox_t, size_t count, size_t *pcount); | ||
123 | static int unix_is_updated (mailbox_t); | ||
124 | static int unix_size (mailbox_t, off_t *size); | ||
129 | 125 | ||
130 | 126 | ||
131 | /* private stuff */ | 127 | /* private stuff */ |
132 | 128 | static int unix_scan0 (mailbox_t, size_t count, size_t *pcount, int); | |
133 | static int mailbox_unix_get_header (mailbox_unix_message_t mum, char *buffer, | 129 | static int unix_get_header_read (stream_t is, char *buffer, size_t len, |
134 | size_t len, off_t off, ssize_t *pnread); | ||
135 | static int mailbox_unix_getfd (stream_t is, int *pfd); | ||
136 | static int mailbox_unix_readstream (stream_t is, char *buffer, size_t buflen, | ||
137 | off_t off, size_t *pnread); | 130 | off_t off, size_t *pnread); |
138 | static int mailbox_unix_body_size (body_t body, size_t *psize); | 131 | static int unix_get_fd (stream_t is, int *pfd); |
139 | static int mailbox_unix_body_lines (body_t body, size_t *plines); | 132 | static int unix_get_flags (attribute_t, int *); |
140 | static int mailbox_unix_msg_from (message_t msg, char *buf, size_t len, | 133 | static int unix_set_flags (attribute_t, int); |
134 | static int unix_unset_flags (attribute_t, int); | ||
135 | static int unix_readstream (stream_t is, char *buffer, size_t buflen, | ||
136 | off_t off, size_t *pnread); | ||
137 | static int unix_body_size (body_t body, size_t *psize); | ||
138 | static int unix_body_lines (body_t body, size_t *plines); | ||
139 | static int unix_msg_from (message_t msg, char *buf, size_t len, | ||
141 | size_t *pnwrite); | 140 | size_t *pnwrite); |
142 | static int mailbox_unix_msg_received (message_t msg, char *buf, size_t len, | 141 | static int unix_msg_received (message_t msg, char *buf, size_t len, |
143 | size_t *pnwrite); | 142 | size_t *pnwrite); |
144 | static int mailbox_unix_lock (mailbox_t mbox, int flag); | 143 | static int unix_lock (mailbox_t mbox, int flag); |
145 | static int mailbox_unix_touchlock (mailbox_t mbox); | 144 | static int unix_touchlock (mailbox_t mbox); |
146 | static int mailbox_unix_unlock (mailbox_t mbox); | 145 | static int unix_unlock (mailbox_t mbox); |
147 | static int mailbox_unix_ilock (mailbox_t mbox, int flag); | 146 | static int unix_ilock (mailbox_t mbox, int flag); |
148 | static int mailbox_unix_iunlock (mailbox_t mbox); | 147 | static int unix_iunlock (mailbox_t mbox); |
149 | 148 | ||
150 | /* We allocate the mailbox_t struct, but don't do any | 149 | /* We allocate the mailbox_t struct, but don't do any parsing on the name or |
151 | * parsing on the name or even test for existence. | 150 | even test for existence. However we do strip any leading "unix:" part of |
152 | * However we do strip any leading "unix:" part of | 151 | the name, this is suppose to be the protocol/scheme name. Hopefully there |
153 | * the name, this is suppose to be the protocol/scheme name. | 152 | will not be a mailbox name "unix:". */ |
154 | * Hopefully there will not be a mailbox name "unix:" | ||
155 | */ | ||
156 | static int | 153 | static int |
157 | mailbox_unix_create (mailbox_t *pmbox, const char *name) | 154 | unix_create (mailbox_t *pmbox, const char *name) |
158 | { | 155 | { |
159 | mailbox_t mbox; | 156 | mailbox_t mbox; |
160 | mailbox_unix_data_t mud; | 157 | unix_data_t mud; |
161 | const char *sep; | 158 | const char *sep; |
162 | size_t name_len; | 159 | size_t name_len; |
163 | int i; | ||
164 | 160 | ||
165 | /* sanity check */ | 161 | /* Sanity check. */ |
166 | if (name == NULL || *name == '\0') | 162 | if (name == NULL || *name == '\0') |
167 | return MU_ERROR_INVALID_ARG; | 163 | return MU_ERROR_INVALID_ARG; |
168 | 164 | ||
... | @@ -172,7 +168,7 @@ mailbox_unix_create (mailbox_t *pmbox, const char *name) | ... | @@ -172,7 +168,7 @@ mailbox_unix_create (mailbox_t *pmbox, const char *name) |
172 | #define UNIX_SCHEME_LEN 5 | 168 | #define UNIX_SCHEME_LEN 5 |
173 | #define SEPARATOR '/' | 169 | #define SEPARATOR '/' |
174 | 170 | ||
175 | /* skip the url scheme */ | 171 | /* Skip the url scheme. */ |
176 | if (name_len > UNIX_SCHEME_LEN && | 172 | if (name_len > UNIX_SCHEME_LEN && |
177 | (name[0] == 'u' || name[0] == 'U') && | 173 | (name[0] == 'u' || name[0] == 'U') && |
178 | (name[1] == 'n' || name[1] == 'N') && | 174 | (name[1] == 'n' || name[1] == 'N') && |
... | @@ -184,50 +180,38 @@ mailbox_unix_create (mailbox_t *pmbox, const char *name) | ... | @@ -184,50 +180,38 @@ mailbox_unix_create (mailbox_t *pmbox, const char *name) |
184 | name_len -= UNIX_SCHEME_LEN; | 180 | name_len -= UNIX_SCHEME_LEN; |
185 | } | 181 | } |
186 | 182 | ||
187 | /* allocate memory for mbox */ | 183 | /* Allocate memory for mbox. */ |
188 | mbox = calloc (1, sizeof (*mbox)); | 184 | mbox = calloc (1, sizeof (*mbox)); |
189 | if (mbox == NULL) | 185 | if (mbox == NULL) |
190 | return MU_ERROR_OUT_OF_MEMORY; | 186 | return MU_ERROR_OUT_OF_MEMORY; |
191 | 187 | ||
192 | /* allocate specific unix mbox data */ | 188 | /* Allocate specific unix mbox data. */ |
193 | mud = mbox->data = calloc (1, sizeof (*mud)); | 189 | mud = mbox->data = calloc (1, sizeof (*mud)); |
194 | if (mbox->data == NULL) | 190 | if (mbox->data == NULL) |
195 | { | 191 | { |
196 | mailbox_unix_destroy (&mbox); | 192 | unix_destroy (&mbox); |
197 | return MU_ERROR_OUT_OF_MEMORY; | 193 | return MU_ERROR_OUT_OF_MEMORY; |
198 | } | 194 | } |
199 | 195 | ||
200 | /* copy the name */ | 196 | /* Copy the name. */ |
201 | mbox->name = calloc (name_len + 1, sizeof (char)); | 197 | mbox->name = calloc (name_len + 1, sizeof (char)); |
202 | if (mbox->name == NULL) | 198 | if (mbox->name == NULL) |
203 | { | 199 | { |
204 | mailbox_unix_destroy (&mbox); | 200 | unix_destroy (&mbox); |
205 | return MU_ERROR_OUT_OF_MEMORY; | 201 | return MU_ERROR_OUT_OF_MEMORY; |
206 | } | 202 | } |
207 | memcpy (mbox->name, name, name_len); | 203 | memcpy (mbox->name, name, name_len); |
208 | 204 | ||
209 | /* save the basename and dirname | 205 | /* Save the basename and dirname. We split the name, but this should |
210 | * So we split the name. But this should probably be | 206 | probably be supported via "maildir:" or the mailbox mgr. */ |
211 | * supported via "maildir:" or the mailbox mgr. | 207 | sep = strrchr (name, SEPARATOR); |
212 | */ | ||
213 | /* equivalent to strrchr (name, '/'); */ | ||
214 | for (i = name_len, sep = NULL; i >= 0; i--) | ||
215 | { | ||
216 | /* break on the first separator */ | ||
217 | if (name[i] == SEPARATOR) | ||
218 | { | ||
219 | sep = &(name[i]); | ||
220 | break; | ||
221 | } | ||
222 | } | ||
223 | |||
224 | if (sep) | 208 | if (sep) |
225 | { | 209 | { |
226 | /* split it into two */ | 210 | /* Split it into two. */ |
227 | mud->dirname = calloc ((sep - name) + 1, sizeof (char)); | 211 | mud->dirname = calloc ((sep - name) + 1, sizeof (char)); |
228 | if (mud->dirname == NULL) | 212 | if (mud->dirname == NULL) |
229 | { | 213 | { |
230 | mailbox_unix_destroy (&mbox); | 214 | unix_destroy (&mbox); |
231 | return MU_ERROR_OUT_OF_MEMORY; | 215 | return MU_ERROR_OUT_OF_MEMORY; |
232 | } | 216 | } |
233 | memcpy (mud->dirname, name, sep - name); | 217 | memcpy (mud->dirname, name, sep - name); |
... | @@ -236,19 +220,19 @@ mailbox_unix_create (mailbox_t *pmbox, const char *name) | ... | @@ -236,19 +220,19 @@ mailbox_unix_create (mailbox_t *pmbox, const char *name) |
236 | mud->basename = calloc (name_len - (sep - name) + 1, sizeof (char)); | 220 | mud->basename = calloc (name_len - (sep - name) + 1, sizeof (char)); |
237 | if (mud->basename == NULL) | 221 | if (mud->basename == NULL) |
238 | { | 222 | { |
239 | mailbox_unix_destroy (&mbox); | 223 | unix_destroy (&mbox); |
240 | return MU_ERROR_OUT_OF_MEMORY; | 224 | return MU_ERROR_OUT_OF_MEMORY; |
241 | } | 225 | } |
242 | memcpy (mud->basename, sep, name_len - (sep - name)); | 226 | memcpy (mud->basename, sep, name_len - (sep - name)); |
243 | } | 227 | } |
244 | else | 228 | else |
245 | { | 229 | { |
246 | /* use the relative directory "." */ | 230 | /* Use the relative directory ".". */ |
247 | /* FIXME: should we call getcwd() instead ? */ | 231 | /* FIXME: should we call getcwd () instead ? */ |
248 | mud->dirname = calloc (2 , sizeof (char)); | 232 | mud->dirname = calloc (2 , sizeof (char)); |
249 | if (mud->dirname == NULL) | 233 | if (mud->dirname == NULL) |
250 | { | 234 | { |
251 | mailbox_unix_destroy (&mbox); | 235 | unix_destroy (&mbox); |
252 | return MU_ERROR_OUT_OF_MEMORY; | 236 | return MU_ERROR_OUT_OF_MEMORY; |
253 | } | 237 | } |
254 | mud->dirname[0] = '.'; | 238 | mud->dirname[0] = '.'; |
... | @@ -256,37 +240,37 @@ mailbox_unix_create (mailbox_t *pmbox, const char *name) | ... | @@ -256,37 +240,37 @@ mailbox_unix_create (mailbox_t *pmbox, const char *name) |
256 | mud->basename = calloc (name_len + 1, sizeof (char)); | 240 | mud->basename = calloc (name_len + 1, sizeof (char)); |
257 | if (mud->basename == NULL) | 241 | if (mud->basename == NULL) |
258 | { | 242 | { |
259 | mailbox_unix_destroy (&mbox); | 243 | unix_destroy (&mbox); |
260 | return MU_ERROR_OUT_OF_MEMORY; | 244 | return MU_ERROR_OUT_OF_MEMORY; |
261 | } | 245 | } |
262 | memcpy (mud->basename, name, name_len); | 246 | memcpy (mud->basename, name, name_len); |
263 | } | 247 | } |
264 | 248 | ||
265 | #ifdef HAVE_PHTREAD_H | 249 | #ifdef HAVE_PHTREAD_H |
266 | /* mutex when accessing the structure fields */ | 250 | /* Mutex when accessing the structure fields. */ |
267 | /* FIXME: should we use rdwr locks instead ?? */ | 251 | /* FIXME: should we use rdwr locks instead ?? */ |
268 | pthread_mutex_init (&(mbox->mutex), NULL); | 252 | pthread_mutex_init (&(mbox->mutex), NULL); |
269 | #endif | 253 | #endif |
270 | 254 | ||
271 | mbox->_create = mailbox_unix_create; | 255 | mbox->_create = unix_create; |
272 | mbox->_destroy = mailbox_unix_destroy; | 256 | mbox->_destroy = unix_destroy; |
273 | 257 | ||
274 | mbox->_open = mailbox_unix_open; | 258 | mbox->_open = unix_open; |
275 | mbox->_close = mailbox_unix_close; | 259 | mbox->_close = unix_close; |
276 | 260 | ||
277 | /* messages */ | 261 | /* Messages. */ |
278 | mbox->_get_message = mailbox_unix_get_message; | 262 | mbox->_get_message = unix_get_message; |
279 | mbox->_append_message = mailbox_unix_append_message; | 263 | mbox->_append_message = unix_append_message; |
280 | mbox->_messages_count = mailbox_unix_messages_count; | 264 | mbox->_messages_count = unix_messages_count; |
281 | mbox->_expunge = mailbox_unix_expunge; | 265 | mbox->_expunge = unix_expunge; |
282 | mbox->_num_deleted = mailbox_unix_num_deleted; | 266 | mbox->_num_deleted = unix_num_deleted; |
283 | 267 | ||
284 | mbox->_scan = mailbox_unix_scan; | 268 | mbox->_scan = unix_scan; |
285 | mbox->_is_updated = mailbox_unix_is_updated; | 269 | mbox->_is_updated = unix_is_updated; |
286 | 270 | ||
287 | mbox->_size = mailbox_unix_size; | 271 | mbox->_size = unix_size; |
288 | 272 | ||
289 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_TRACE, "mailbox_unix_create (%s/%s)\n", | 273 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_TRACE, "unix_create (%s/%s)\n", |
290 | mud->dirname, mud->basename); | 274 | mud->dirname, mud->basename); |
291 | (*pmbox) = mbox; | 275 | (*pmbox) = mbox; |
292 | 276 | ||
... | @@ -294,40 +278,37 @@ mailbox_unix_create (mailbox_t *pmbox, const char *name) | ... | @@ -294,40 +278,37 @@ mailbox_unix_create (mailbox_t *pmbox, const char *name) |
294 | } | 278 | } |
295 | 279 | ||
296 | static void | 280 | static void |
297 | mailbox_unix_destroy (mailbox_t *pmbox) | 281 | unix_destroy (mailbox_t *pmbox) |
298 | { | 282 | { |
299 | if (pmbox && *pmbox) | 283 | if (pmbox && *pmbox) |
300 | { | 284 | { |
301 | mailbox_t mbox = *pmbox; | 285 | mailbox_t mbox = *pmbox; |
302 | mailbox_unix_close (mbox); | 286 | unix_close (mbox); |
303 | if (mbox->data) | 287 | if (mbox->data) |
304 | { | 288 | { |
305 | size_t i; | 289 | size_t i; |
306 | mailbox_unix_data_t mud = mbox->data; | 290 | unix_data_t mud = mbox->data; |
307 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_TRACE, | 291 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_TRACE, |
308 | "mailbox_unix_destroy (%s/%s)\n", | 292 | "unix_destroy (%s/%s)\n", |
309 | mud->dirname, mud->basename); | 293 | mud->dirname, mud->basename); |
310 | free (mud->dirname); | 294 | free (mud->dirname); |
311 | free (mud->basename); | 295 | free (mud->basename); |
312 | for (i = 0; i < mud->umessages_count; i++) | 296 | for (i = 0; i < mud->umessages_count; i++) |
313 | { | 297 | { |
314 | mailbox_unix_message_t mum = mud->umessages[i]; | 298 | unix_message_t mum = mud->umessages[i]; |
315 | if (mum == NULL) | 299 | if (mum == NULL) |
316 | continue; | 300 | { |
317 | /* Destroy the attach messages */ | ||
318 | attribute_destroy (&(mum->old_attr)); | ||
319 | message_destroy (&(mum->message), mum); | 301 | message_destroy (&(mum->message), mum); |
320 | /* new_attr free by message_destroy() */ | ||
321 | /* attribute_destroy (&(mum->new_attr)); */ | ||
322 | free (mum); | 302 | free (mum); |
323 | } | 303 | } |
304 | } | ||
324 | free (mud->umessages); | 305 | free (mud->umessages); |
325 | free (mbox->data); | 306 | free (mbox->data); |
326 | } | 307 | } |
327 | free (mbox->name); | 308 | free (mbox->name); |
328 | /* free the event array */ | 309 | /* Free the event array. */ |
329 | free (mbox->event); | 310 | free (mbox->event); |
330 | /* destroy the url */ | 311 | /* Destroy the url. */ |
331 | if (mbox->url) | 312 | if (mbox->url) |
332 | url_destroy (&(mbox->url)); | 313 | url_destroy (&(mbox->url)); |
333 | if (mbox->locker) | 314 | if (mbox->locker) |
... | @@ -336,38 +317,38 @@ mailbox_unix_destroy (mailbox_t *pmbox) | ... | @@ -336,38 +317,38 @@ mailbox_unix_destroy (mailbox_t *pmbox) |
336 | auth_destroy (&(mbox->auth), mbox); | 317 | auth_destroy (&(mbox->auth), mbox); |
337 | if(mbox->stream) | 318 | if(mbox->stream) |
338 | stream_destroy (&(mbox->stream), mbox); | 319 | stream_destroy (&(mbox->stream), mbox); |
339 | mailbox_unix_iunlock (mbox); | 320 | unix_iunlock (mbox); |
340 | #ifdef HAVE_PTHREAD_H | 321 | #ifdef HAVE_PTHREAD_H |
341 | if (mbox->mutex) | 322 | if (mbox->mutex) |
342 | ptread_mutex_destroy (&(mbox->mutex)); | 323 | ptread_mutex_destroy (&(mbox->mutex)); |
343 | #endif | 324 | #endif |
344 | free (*pmbox); | 325 | free (mbox); |
345 | *pmbox = NULL; | 326 | *pmbox = NULL; |
346 | } | 327 | } |
347 | } | 328 | } |
348 | 329 | ||
349 | /* Open the file. */ | 330 | /* Open the file. */ |
350 | static int | 331 | static int |
351 | mailbox_unix_open (mailbox_t mbox, int flags) | 332 | unix_open (mailbox_t mbox, int flags) |
352 | { | 333 | { |
353 | mailbox_unix_data_t mud; | 334 | unix_data_t mud; |
354 | int status = 0; | 335 | int status = 0; |
355 | 336 | ||
356 | if (mbox == NULL || | 337 | if (mbox == NULL || |
357 | (mud = (mailbox_unix_data_t)mbox->data) == NULL) | 338 | (mud = (unix_data_t)mbox->data) == NULL) |
358 | return EINVAL; | 339 | return EINVAL; |
359 | 340 | ||
360 | /* Authentication prologues */ | 341 | /* Authentication prologues. */ |
361 | if (mbox->auth) | 342 | if (mbox->auth) |
362 | auth_prologue (mbox->auth); | 343 | auth_prologue (mbox->auth); |
363 | 344 | ||
364 | /* get a stream */ | 345 | /* Get a stream. */ |
365 | if (mbox->stream == NULL) | 346 | if (mbox->stream == NULL) |
366 | { | 347 | { |
367 | /* FIXME: for small mbox we shout try to mmap() */ | 348 | /* FIXME: for small mbox we shout try to mmap (). */ |
368 | 349 | ||
369 | status = (flags & MU_STREAM_CREAT) || (flags & MU_STREAM_APPEND); | 350 | int trymap = (flags & MU_STREAM_CREAT) || (flags & MU_STREAM_APPEND); |
370 | if (status == 0) | 351 | if (trymap == 0) |
371 | status = mapfile_stream_create (&(mbox->stream)); | 352 | status = mapfile_stream_create (&(mbox->stream)); |
372 | if (status != 0) | 353 | if (status != 0) |
373 | { | 354 | { |
... | @@ -377,77 +358,56 @@ mailbox_unix_open (mailbox_t mbox, int flags) | ... | @@ -377,77 +358,56 @@ mailbox_unix_open (mailbox_t mbox, int flags) |
377 | } | 358 | } |
378 | status = stream_open (mbox->stream, mbox->name, 0, flags); | 359 | status = stream_open (mbox->stream, mbox->name, 0, flags); |
379 | if (status != 0) | 360 | if (status != 0) |
380 | { | ||
381 | stream_destroy (&(mbox->stream), mbox); | ||
382 | return status; | 361 | return status; |
383 | } | 362 | } |
384 | } | ||
385 | else | 363 | else |
386 | { | 364 | { |
387 | status = stream_open (mbox->stream, mbox->name, 0, flags); | 365 | status = stream_open (mbox->stream, mbox->name, 0, flags); |
388 | if (status != 0) | 366 | if (status != 0) |
389 | { | ||
390 | stream_destroy (&(mbox->stream), mbox); | ||
391 | return status; | ||
392 | } | ||
393 | } | ||
394 | |||
395 | /* Authentication */ | ||
396 | if (mbox->auth) | ||
397 | { | ||
398 | char *user = NULL; | ||
399 | char *passwd = NULL; | ||
400 | status = auth_authenticate (mbox->auth, &user, &passwd); | ||
401 | free (user); | ||
402 | free (passwd); | ||
403 | if (status != 0) | ||
404 | return status; | 367 | return status; |
405 | } | 368 | } |
406 | 369 | ||
407 | /* Authentication epilogues */ | 370 | /* Authentication epilogue. */ |
408 | if (mbox->auth) | 371 | if (mbox->auth) |
409 | auth_epilogue (mbox->auth); | 372 | auth_epilogue (mbox->auth); |
410 | 373 | ||
411 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_TRACE, "mailbox_unix_open(%s, %d)\n", | 374 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_TRACE, "unix_open(%s, %d)\n", |
412 | mbox->name, flags); | 375 | mbox->name, flags); |
413 | /* give an appopriate way to lock */ | 376 | |
377 | /* Give an appopriate way to lock. */ | ||
414 | if (mbox->locker == NULL) | 378 | if (mbox->locker == NULL) |
415 | locker_create (&(mbox->locker), mbox->name, | 379 | locker_create (&(mbox->locker), mbox->name, strlen (mbox->name), |
416 | strlen (mbox->name), MU_LOCKER_PID | MU_LOCKER_FCNTL); | 380 | MU_LOCKER_PID | MU_LOCKER_FCNTL); |
417 | return 0; | 381 | return 0; |
418 | } | 382 | } |
419 | 383 | ||
420 | static int | 384 | static int |
421 | mailbox_unix_close (mailbox_t mbox) | 385 | unix_close (mailbox_t mbox) |
422 | { | 386 | { |
423 | mailbox_unix_data_t mud; | 387 | unix_data_t mud; |
424 | size_t i; | 388 | size_t i; |
425 | 389 | ||
426 | if (mbox == NULL || | 390 | if (mbox == NULL || (mud = (unix_data_t)mbox->data) == NULL) |
427 | (mud = (mailbox_unix_data_t)mbox->data) == NULL) | ||
428 | return EINVAL; | 391 | return EINVAL; |
429 | 392 | ||
430 | /* make sure we do not hold any lock for that file */ | 393 | /* Make sure we do not hold any lock for that file. */ |
431 | mailbox_unix_unlock (mbox); | 394 | unix_unlock (mbox); |
432 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_TRACE, "mailbox_unix_close(%s)\n", | 395 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_TRACE, "unix_close(%s)\n", |
433 | mbox->name); | 396 | mbox->name); |
434 | 397 | ||
435 | /* before closing we need to remove all the messages | 398 | /* Before closing we need to remove all the messages |
436 | * - to reclaim the memory | 399 | - to reclaim the memory |
437 | * - to prepare for another scan. | 400 | - to prepare for another scan. */ |
438 | */ | ||
439 | for (i = 0; i < mud->umessages_count; i++) | 401 | for (i = 0; i < mud->umessages_count; i++) |
440 | { | 402 | { |
441 | mailbox_unix_message_t mum = mud->umessages[i]; | 403 | unix_message_t mum = mud->umessages[i]; |
404 | /* Destroy the attach messages. */ | ||
442 | if (mum == NULL) | 405 | if (mum == NULL) |
443 | continue; | 406 | { |
444 | /* Destroy the attach messages */ | ||
445 | attribute_destroy (&(mum->old_attr)); | ||
446 | message_destroy (&(mum->message), mum); | 407 | message_destroy (&(mum->message), mum); |
447 | /* new_attr free by message_destroy() */ | ||
448 | /* attribute_destroy (&(mum->new_attr)); */ | ||
449 | free (mum); | 408 | free (mum); |
450 | } | 409 | } |
410 | } | ||
451 | free (mud->umessages); | 411 | free (mud->umessages); |
452 | mud->umessages = NULL; | 412 | mud->umessages = NULL; |
453 | mud->messages_count = mud->umessages_count = 0; | 413 | mud->messages_count = mud->umessages_count = 0; |
... | @@ -455,30 +415,26 @@ mailbox_unix_close (mailbox_t mbox) | ... | @@ -455,30 +415,26 @@ mailbox_unix_close (mailbox_t mbox) |
455 | return stream_close (mbox->stream); | 415 | return stream_close (mbox->stream); |
456 | } | 416 | } |
457 | 417 | ||
458 | /* Mailbox Parsing */ | 418 | /* Mailbox Parsing. */ |
459 | #include "mbx_unixscan.c" | 419 | #include "mbx_unixscan.c" |
460 | 420 | ||
461 | static int | 421 | static int |
462 | mailbox_unix_scan (mailbox_t mbox, size_t msgno, size_t *pcount) | 422 | unix_scan (mailbox_t mbox, size_t msgno, size_t *pcount) |
463 | { | 423 | { |
464 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_TRACE, "mailbox_unix_scan(%s)\n", | 424 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_TRACE, "unix_scan(%s)\n", mbox->name); |
465 | mbox->name); | 425 | return unix_scan0 (mbox, msgno, pcount, 1); |
466 | return mailbox_unix_scan0 (mbox, msgno, pcount, 1); | ||
467 | } | 426 | } |
468 | 427 | ||
469 | 428 | ||
470 | /* FIXME: How to handle a shrink ? meaning, the &^$^@%#@^& user | 429 | /* FIXME: How to handle a shrink ? meaning, the &^$^@%#@^& user start two |
471 | * start two browsers and delete files in one. My views | 430 | browsers and delete files in one. My views is that we should scream |
472 | * is that we should scream bloody murder and hunt them with | 431 | bloody murder and hunt them with a machette. */ |
473 | * a machette. | ||
474 | */ | ||
475 | static int | 432 | static int |
476 | mailbox_unix_is_updated (mailbox_t mbox) | 433 | unix_is_updated (mailbox_t mbox) |
477 | { | 434 | { |
478 | off_t size; | 435 | off_t size; |
479 | mailbox_unix_data_t mud; | 436 | unix_data_t mud; |
480 | if (mbox == NULL || | 437 | if (mbox == NULL || (mud = (unix_data_t) mbox->data) == NULL) |
481 | (mud = (mailbox_unix_data_t) mbox->data) == NULL) | ||
482 | return EINVAL; | 438 | return EINVAL; |
483 | if (stream_size (mbox->stream, &size) != 0) | 439 | if (stream_size (mbox->stream, &size) != 0) |
484 | return 0; | 440 | return 0; |
... | @@ -486,18 +442,17 @@ mailbox_unix_is_updated (mailbox_t mbox) | ... | @@ -486,18 +442,17 @@ mailbox_unix_is_updated (mailbox_t mbox) |
486 | } | 442 | } |
487 | 443 | ||
488 | static int | 444 | static int |
489 | mailbox_unix_num_deleted (mailbox_t mbox, size_t *pnum) | 445 | unix_num_deleted (mailbox_t mbox, size_t *pnum) |
490 | { | 446 | { |
491 | mailbox_unix_data_t mud; | 447 | unix_data_t mud; |
492 | mailbox_unix_message_t mum; | 448 | unix_message_t mum; |
493 | size_t i, total; | 449 | size_t i, total; |
494 | if (mbox == NULL || | 450 | if (mbox == NULL || (mud = (unix_data_t) mbox->data) == NULL) |
495 | (mud = (mailbox_unix_data_t) mbox->data) == NULL) | ||
496 | return EINVAL; | 451 | return EINVAL; |
497 | for (i = total = 0; i < mud->messages_count; i++) | 452 | for (i = total = 0; i < mud->messages_count; i++) |
498 | { | 453 | { |
499 | mum = mud->umessages[i]; | 454 | mum = mud->umessages[i]; |
500 | if (attribute_is_deleted (mum->new_attr)) | 455 | if (ATTRIBUTE_IS_DELETED (mum->new_flags)) |
501 | total++; | 456 | total++; |
502 | } | 457 | } |
503 | 458 | ||
... | @@ -506,42 +461,41 @@ mailbox_unix_num_deleted (mailbox_t mbox, size_t *pnum) | ... | @@ -506,42 +461,41 @@ mailbox_unix_num_deleted (mailbox_t mbox, size_t *pnum) |
506 | return 0; | 461 | return 0; |
507 | } | 462 | } |
508 | 463 | ||
509 | /* | 464 | /* FIXME: the use of tmpfile() on some system can lead to race condition, We |
510 | FIXME: the use of tmpfile() on some system can lead to | 465 | should use a safer approach. We take a very naive approach for this, it |
511 | race condition, We should use a safer approach. | 466 | involves unfortunately two copies. */ |
512 | We take a very naive approach for this, it involves unfortunately | ||
513 | two copies. | ||
514 | */ | ||
515 | static FILE * | 467 | static FILE * |
516 | mailbox_unix_tmpfile (mailbox_t mbox, char **pbox) | 468 | unix_tmpfile (mailbox_t mbox, char **pbox) |
517 | { | 469 | { |
518 | mailbox_unix_data_t mud = (mailbox_unix_data_t)mbox->data; | 470 | const char *tmpdir; |
519 | int fd; | 471 | int fd; |
520 | FILE *fp; | 472 | FILE *fp; |
473 | unix_data_t mud = (unix_data_t)mbox->data; | ||
521 | 474 | ||
475 | /* P_tmpdir should be define in <stdio.h>. */ | ||
522 | #ifndef P_tmpdir | 476 | #ifndef P_tmpdir |
523 | # define P_tmpdir "/tmp" | 477 | # define P_tmpdir "/tmp" |
524 | #endif | 478 | #endif |
525 | 479 | ||
526 | *pbox = calloc (1, strlen (P_tmpdir) + strlen ("MBOX_") + | 480 | tmpdir = getenv ("TEMPDIR") ? getenv ("TEMPDIR") : P_tmpdir; |
481 | *pbox = calloc (1, strlen (tmpdir) + strlen ("MBOX_") + | ||
527 | strlen (mud->basename) + 1); | 482 | strlen (mud->basename) + 1); |
528 | if (*pbox == NULL) | 483 | if (*pbox == NULL) |
529 | return NULL; | 484 | return NULL; |
530 | sprintf (*pbox, "%s/%s%s", P_tmpdir, "MBOX_", mud->basename); | 485 | sprintf (*pbox, "%s/%s%s", tmpdir, "MBOX_", mud->basename); |
531 | 486 | ||
532 | /* FIXME: I don't think this is the righ approach | 487 | /* FIXME: I don't think this is the righ approach, creating an anonymous |
533 | * Creating an anonymous file would be better ? | 488 | file would be better ? no trace left behind. */ |
534 | * no trace left behind. | ||
535 | */ | ||
536 | /* Create the file. It must not exist. If it does exist, fail. */ | 489 | /* Create the file. It must not exist. If it does exist, fail. */ |
537 | fd = open(*pbox, O_RDWR|O_CREAT|O_EXCL, 0600); | 490 | fd = open (*pbox, O_RDWR|O_CREAT|O_EXCL, 0600); |
538 | if (fd < 0) | 491 | if (fd < 0) |
539 | { | 492 | { |
540 | fprintf(stderr,"Can't create %s\n", *pbox); | 493 | fprintf (stderr,"Can't create %s\n", *pbox); |
541 | fprintf(stderr,"delete file <%s>, Please\n", *pbox); | 494 | fprintf (stderr,"delete file <%s>, Please\n", *pbox); |
495 | fprintf (stderr, "It was likely due to an error when expunging\n"); | ||
542 | return NULL; | 496 | return NULL; |
543 | } | 497 | } |
544 | fp = fdopen(fd, "w+"); | 498 | fp = fdopen (fd, "w+"); |
545 | if (fp == 0) | 499 | if (fp == 0) |
546 | { | 500 | { |
547 | close(fd); | 501 | close(fd); |
... | @@ -549,16 +503,16 @@ mailbox_unix_tmpfile (mailbox_t mbox, char **pbox) | ... | @@ -549,16 +503,16 @@ mailbox_unix_tmpfile (mailbox_t mbox, char **pbox) |
549 | *pbox = NULL; | 503 | *pbox = NULL; |
550 | } | 504 | } |
551 | 505 | ||
552 | /* really I should just remove the file here */ | 506 | /* Really I should just remove the file here. */ |
553 | /* remove(*pbox); */ | 507 | /* remove(*pbox); */ |
554 | return fp; | 508 | return fp; |
555 | } | 509 | } |
556 | 510 | ||
557 | static int | 511 | static int |
558 | mailbox_unix_expunge (mailbox_t mbox) | 512 | unix_expunge (mailbox_t mbox) |
559 | { | 513 | { |
560 | mailbox_unix_data_t mud; | 514 | unix_data_t mud; |
561 | mailbox_unix_message_t mum; | 515 | unix_message_t mum; |
562 | int status = 0; | 516 | int status = 0; |
563 | sigset_t sigset; | 517 | sigset_t sigset; |
564 | FILE *tempfile; | 518 | FILE *tempfile; |
... | @@ -569,74 +523,65 @@ mailbox_unix_expunge (mailbox_t mbox) | ... | @@ -569,74 +523,65 @@ mailbox_unix_expunge (mailbox_t mbox) |
569 | char buffer [BUFSIZ]; | 523 | char buffer [BUFSIZ]; |
570 | char *tmpmbox = NULL; | 524 | char *tmpmbox = NULL; |
571 | 525 | ||
572 | if (mbox == NULL || | 526 | if (mbox == NULL || (mud = (unix_data_t)mbox->data) == NULL) |
573 | (mud = (mailbox_unix_data_t)mbox->data) == NULL) | ||
574 | return EINVAL; | 527 | return EINVAL; |
575 | 528 | ||
576 | /* noop */ | 529 | /* Noop. */ |
577 | if (mud->messages_count == 0) | 530 | if (mud->messages_count == 0) |
578 | return 0; | 531 | return 0; |
579 | 532 | ||
580 | /* Do we have a consistent view of the mailbox */ | 533 | /* Do we have a consistent view of the mailbox. */ |
581 | /* FIXME: this is not enough, we can do better | 534 | /* FIXME: this is not enough, we can do better |
582 | * - by checking the file size and scream bloody murder | 535 | - by checking the file size and scream bloody murder if it has shrink. |
583 | * if it has shrink. | 536 | - if its bigger we should be able to handle it before the ftruncate () |
584 | * - if its bigger we should be able to handle it | 537 | by copying back the new messages. */ |
585 | * before the ftruncate() by copying back the new messages. | 538 | if (! unix_is_updated (mbox)) |
586 | */ | 539 | { |
587 | if (! mailbox_unix_is_updated (mbox)) | 540 | fprintf (stderr, "mailbox is not updated, try again.\n"); |
588 | return EAGAIN; | 541 | return EAGAIN; |
542 | } | ||
589 | 543 | ||
590 | /* mark dirty the first mail with an attribute change */ | 544 | /* Mark dirty the first mail with an attribute change. */ |
591 | for (dirty = 0; dirty < mud->messages_count; dirty++) | 545 | for (dirty = 0; dirty < mud->messages_count; dirty++) |
592 | { | 546 | { |
593 | mum = mud->umessages[dirty]; | 547 | mum = mud->umessages[dirty]; |
594 | if (mum->new_attr && | 548 | if (mum->new_flags && |
595 | ! attribute_is_equal (mum->old_attr, mum->new_attr)) | 549 | ! ATTRIBUTE_IS_EQUAL (mum->old_flags, mum->new_flags)) |
596 | break; | 550 | break; |
597 | } | 551 | } |
598 | 552 | ||
599 | /* did something change ? */ | 553 | /* Did something change ? */ |
600 | if (dirty == mud->messages_count) | 554 | if (dirty == mud->messages_count) |
601 | return 0; /* nothing change, bail out */ | 555 | return 0; /* Nothing change, bail out. */ |
602 | 556 | ||
603 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_TRACE, "mailbox_unix_expunge (%s)\n", | 557 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_TRACE, "unix_expunge (%s)\n", |
604 | mbox->name); | 558 | mbox->name); |
605 | 559 | ||
606 | /* Send notification to all the listeners | 560 | /* This is redundant, we go to the loop again. But it's more secure here |
607 | * this is redundant, we go to the loop again | 561 | since we don't want to be disturb when expunging. */ |
608 | * But it's more secure here since we don't | ||
609 | * want to be disturb when expunging. | ||
610 | */ | ||
611 | for (j = 0; j < mud->messages_count; j++) | 562 | for (j = 0; j < mud->messages_count; j++) |
612 | { | 563 | { |
613 | mum = mud->umessages[j]; | 564 | mum = mud->umessages[j]; |
614 | if (mum && mum->new_attr && attribute_is_deleted (mum->new_attr)) | 565 | if (mum && mum->new_flags && ATTRIBUTE_IS_DELETED (mum->new_flags)) |
615 | { | ||
616 | attribute_t attr; | ||
617 | attribute_create (&attr); | ||
618 | attribute_copy (attr, mum->new_attr); | ||
619 | /* Hack: message_destroy() will free() the attribute, save it */ | ||
620 | message_destroy (&(mum->message), mum); | 566 | message_destroy (&(mum->message), mum); |
621 | mum->new_attr = attr; | ||
622 | } | ||
623 | } | 567 | } |
624 | 568 | ||
625 | /* create a tempory file */ | 569 | /* Create a tempory file. */ |
626 | tempfile = mailbox_unix_tmpfile (mbox, &tmpmbox); | 570 | tempfile = unix_tmpfile (mbox, &tmpmbox); |
627 | if (tempfile == NULL) | 571 | if (tempfile == NULL) |
628 | return errno; | 572 | return errno; |
629 | 573 | ||
630 | /* Get the lock */ | 574 | /* Get the lock. */ |
631 | if (mailbox_unix_lock (mbox, MU_LOCKER_WRLOCK) < 0) | 575 | if (unix_lock (mbox, MU_LOCKER_WRLOCK) < 0) |
632 | { | 576 | { |
633 | fclose (tempfile); | 577 | fclose (tempfile); |
634 | remove (tmpmbox); | 578 | remove (tmpmbox); |
635 | free (tmpmbox); | 579 | free (tmpmbox); |
580 | fprintf (stderr, "Failed to grab the lock\n"); | ||
636 | return ENOLCK; | 581 | return ENOLCK; |
637 | } | 582 | } |
638 | 583 | ||
639 | /* Critical section, we can not allowed signal here */ | 584 | /* Critical section, we can not allowed signal here. */ |
640 | sigemptyset (&sigset); | 585 | sigemptyset (&sigset); |
641 | sigaddset (&sigset, SIGTERM); | 586 | sigaddset (&sigset, SIGTERM); |
642 | sigaddset (&sigset, SIGHUP); | 587 | sigaddset (&sigset, SIGHUP); |
... | @@ -645,21 +590,21 @@ mailbox_unix_expunge (mailbox_t mbox) | ... | @@ -645,21 +590,21 @@ mailbox_unix_expunge (mailbox_t mbox) |
645 | sigaddset (&sigset, SIGWINCH); | 590 | sigaddset (&sigset, SIGWINCH); |
646 | sigprocmask (SIG_BLOCK, &sigset, 0); | 591 | sigprocmask (SIG_BLOCK, &sigset, 0); |
647 | 592 | ||
648 | mailbox_unix_ilock (mbox, MU_LOCKER_RDLOCK); | 593 | unix_ilock (mbox, MU_LOCKER_RDLOCK); |
649 | 594 | ||
650 | /* set the marker position */ | 595 | /* Set the marker position. */ |
651 | total = marker = mud->umessages[dirty]->header_from; | 596 | total = marker = mud->umessages[dirty]->header_from; |
652 | 597 | ||
653 | /* copy to tempfile emails not mark deleted */ | 598 | /* Copy to tempfile emails not mark deleted. */ |
654 | for (first = 1, i = dirty; i < mud->messages_count; i++) | 599 | for (first = 1, i = dirty; i < mud->messages_count; i++) |
655 | { | 600 | { |
656 | mum = mud->umessages[i]; | 601 | mum = mud->umessages[i]; |
657 | 602 | ||
658 | /* skip it, if mark for deletion */ | 603 | /* Skip it, if mark for deletion. */ |
659 | if (attribute_is_deleted (mum->new_attr)) | 604 | if (ATTRIBUTE_IS_DELETED (mum->new_flags)) |
660 | continue; | 605 | continue; |
661 | 606 | ||
662 | /* add a NL separator between messages */ | 607 | /* Add a NL separator between messages. */ |
663 | if (first) | 608 | if (first) |
664 | first = 0; | 609 | first = 0; |
665 | else | 610 | else |
... | @@ -668,19 +613,18 @@ mailbox_unix_expunge (mailbox_t mbox) | ... | @@ -668,19 +613,18 @@ mailbox_unix_expunge (mailbox_t mbox) |
668 | total++; | 613 | total++; |
669 | } | 614 | } |
670 | 615 | ||
671 | /* Begining of header copy */ | 616 | /* Begining of header copy. */ |
672 | { | 617 | { |
673 | off_t current; | 618 | off_t current; |
674 | /* This is done in two parts first we check if the attribute | 619 | /* This is done in two parts first we check if the attribute changed, |
675 | * changed, if yes then we have to update the "Status:" field. | 620 | if yes then we have to update the "Status:" field. Unfortunately |
676 | * Unfortunately there is no requirement for the "Status:" | 621 | there is no requirement for the "Status:" to be the last field, so |
677 | * to be the last field, so we take the long approach; | 622 | we take the long approach; Copy up to the Status, update the |
678 | * Copy up to the Status, update the Status and copy the rest. | 623 | Status and copy the rest. */ |
679 | */ | 624 | |
680 | 625 | /* Attribute change ? */ | |
681 | /* attribute change ? */ | 626 | if (mum->new_flags |
682 | if (mum->new_attr | 627 | &&! ATTRIBUTE_IS_EQUAL (mum->old_flags, mum->new_flags) |
683 | &&! attribute_is_equal (mum->old_attr, mum->new_attr) | ||
684 | && mum->header_status > mum->header_from) | 628 | && mum->header_status > mum->header_from) |
685 | { | 629 | { |
686 | size_t n = 0; | 630 | size_t n = 0; |
... | @@ -696,6 +640,8 @@ mailbox_unix_expunge (mailbox_t mbox) | ... | @@ -696,6 +640,8 @@ mailbox_unix_expunge (mailbox_t mbox) |
696 | { | 640 | { |
697 | if (status == 0) | 641 | if (status == 0) |
698 | status = errno; | 642 | status = errno; |
643 | fprintf (stderr, "expunge:%d: (%s)\n", __LINE__, | ||
644 | strerror (status)); | ||
699 | goto bailout; | 645 | goto bailout; |
700 | } | 646 | } |
701 | len -= n; | 647 | len -= n; |
... | @@ -703,20 +649,20 @@ mailbox_unix_expunge (mailbox_t mbox) | ... | @@ -703,20 +649,20 @@ mailbox_unix_expunge (mailbox_t mbox) |
703 | offset += n; | 649 | offset += n; |
704 | } | 650 | } |
705 | 651 | ||
706 | /* put the new attributes */ | 652 | /* Put the new attributes. */ |
707 | { | 653 | { |
708 | char abuf[64]; | 654 | char abuf[64]; |
709 | size_t na = 0; | 655 | size_t na = 0; |
710 | abuf[0] = '\0'; | 656 | abuf[0] = '\0'; |
711 | attribute_to_string (mum->new_attr, abuf, sizeof(abuf), &na); | 657 | flags_to_string (mum->new_flags, abuf, sizeof(abuf), &na); |
712 | fputs (abuf, tempfile); | 658 | fputs (abuf, tempfile); |
713 | total += na; | 659 | total += na; |
714 | } | 660 | } |
715 | } | 661 | } |
716 | else /* attribute did not change */ | 662 | else /* Attribute did not change. */ |
717 | current = mum->header_from; | 663 | current = mum->header_from; |
718 | 664 | ||
719 | /* copy the rest of header without changes */ | 665 | /* Copy the rest of header without changes. */ |
720 | { | 666 | { |
721 | size_t n = 0; | 667 | size_t n = 0; |
722 | off_t offset = current; | 668 | off_t offset = current; |
... | @@ -730,6 +676,8 @@ mailbox_unix_expunge (mailbox_t mbox) | ... | @@ -730,6 +676,8 @@ mailbox_unix_expunge (mailbox_t mbox) |
730 | { | 676 | { |
731 | if (status == 0) | 677 | if (status == 0) |
732 | status = errno; | 678 | status = errno; |
679 | fprintf (stderr, "expunge:%d: %s", __LINE__, | ||
680 | strerror (status)); | ||
733 | goto bailout; | 681 | goto bailout; |
734 | } | 682 | } |
735 | len -= n; | 683 | len -= n; |
... | @@ -737,9 +685,9 @@ mailbox_unix_expunge (mailbox_t mbox) | ... | @@ -737,9 +685,9 @@ mailbox_unix_expunge (mailbox_t mbox) |
737 | offset += n; | 685 | offset += n; |
738 | } | 686 | } |
739 | } | 687 | } |
740 | } /* end of header copy */ | 688 | } /* End of header copy. */ |
741 | 689 | ||
742 | /* copy the body */ | 690 | /* Copy the body. */ |
743 | { | 691 | { |
744 | size_t n = 0; | 692 | size_t n = 0; |
745 | off_t offset = mum->body; | 693 | off_t offset = mum->body; |
... | @@ -753,21 +701,20 @@ mailbox_unix_expunge (mailbox_t mbox) | ... | @@ -753,21 +701,20 @@ mailbox_unix_expunge (mailbox_t mbox) |
753 | { | 701 | { |
754 | if (status == 0) | 702 | if (status == 0) |
755 | status = errno; | 703 | status = errno; |
704 | fprintf (stderr, "expunge:%d: %s", __LINE__, | ||
705 | strerror (status)); | ||
756 | goto bailout; | 706 | goto bailout; |
757 | } | 707 | } |
758 | len -= n; | 708 | len -= n; |
759 | total += n; | 709 | total += n; |
760 | offset += n; | 710 | offset += n; |
761 | } | 711 | } |
762 | } /* end of body copy */ | 712 | } /* End of body copy. */ |
763 | } /* for (;;) */ | 713 | } /* for (;;) */ |
764 | 714 | ||
765 | /* | 715 | /* Caution: before ftruncate()ing the file see if we've receiving new mail |
766 | * Caution: | 716 | Some program may not respect the lock, or the lock was held for too |
767 | * before ftruncate()ing the file see if we've receiving new mail | 717 | long. */ |
768 | * Some program may not respect the lock, or the lock was held | ||
769 | * for too long. | ||
770 | */ | ||
771 | { | 718 | { |
772 | off_t size = 0; | 719 | off_t size = 0; |
773 | if (stream_size (mbox->stream, &size) == 0) | 720 | if (stream_size (mbox->stream, &size) == 0) |
... | @@ -784,6 +731,8 @@ mailbox_unix_expunge (mailbox_t mbox) | ... | @@ -784,6 +731,8 @@ mailbox_unix_expunge (mailbox_t mbox) |
784 | { | 731 | { |
785 | if (status == 0) | 732 | if (status == 0) |
786 | status = errno; | 733 | status = errno; |
734 | fprintf (stderr, "expunge:%d: %s", __LINE__, | ||
735 | strerror (status)); | ||
787 | goto bailout; | 736 | goto bailout; |
788 | } | 737 | } |
789 | len -= n; | 738 | len -= n; |
... | @@ -791,9 +740,9 @@ mailbox_unix_expunge (mailbox_t mbox) | ... | @@ -791,9 +740,9 @@ mailbox_unix_expunge (mailbox_t mbox) |
791 | offset += n; | 740 | offset += n; |
792 | } | 741 | } |
793 | } | 742 | } |
794 | } /* end of precaution */ | 743 | } /* End of precaution. */ |
795 | 744 | ||
796 | /* Seek and rewrite it */ | 745 | /* Seek and rewrite it. */ |
797 | rewind (tempfile); | 746 | rewind (tempfile); |
798 | if (total > 0) | 747 | if (total > 0) |
799 | { | 748 | { |
... | @@ -813,39 +762,42 @@ mailbox_unix_expunge (mailbox_t mbox) | ... | @@ -813,39 +762,42 @@ mailbox_unix_expunge (mailbox_t mbox) |
813 | } | 762 | } |
814 | } | 763 | } |
815 | 764 | ||
816 | /* how can I handle error here ?? */ | 765 | /* How can I handle error here ?? */ |
817 | clearerr (tempfile); | 766 | clearerr (tempfile); |
818 | 767 | ||
819 | /* flush/truncation */ | 768 | /* Flush/truncation. */ |
820 | stream_flush (mbox->stream); | 769 | stream_flush (mbox->stream); |
821 | status = stream_truncate (mbox->stream, total); | 770 | status = stream_truncate (mbox->stream, total); |
822 | if (status != 0) | 771 | if (status != 0) |
772 | { | ||
773 | fprintf (stderr, "expunge:%d: %s", __LINE__, | ||
774 | strerror (status)); | ||
823 | goto bailout; | 775 | goto bailout; |
776 | } | ||
824 | 777 | ||
825 | /* Don't remove the tmp mbox in case of errors */ | 778 | /* Don't remove the tmp mbox in case of errors. */ |
826 | remove (tmpmbox); | 779 | remove (tmpmbox); |
827 | 780 | ||
828 | bailout: | 781 | bailout: |
829 | 782 | ||
830 | free (tmpmbox); | 783 | free (tmpmbox); |
831 | /* Release the locks */ | 784 | /* Release the locks. */ |
832 | mailbox_unix_unlock (mbox); | 785 | unix_unlock (mbox); |
833 | mailbox_unix_iunlock (mbox); | 786 | unix_iunlock (mbox); |
834 | fclose (tempfile); | 787 | fclose (tempfile); |
835 | sigprocmask (SIG_UNBLOCK, &sigset, 0); | 788 | sigprocmask (SIG_UNBLOCK, &sigset, 0); |
836 | 789 | ||
837 | /* we need to readjust the pointers */ | 790 | /* We need to readjust the pointers. */ |
838 | if (status == 0) | 791 | if (status == 0) |
839 | { | 792 | { |
840 | size_t dlast; | 793 | size_t dlast; |
841 | for (j = dirty, dlast = mud->messages_count - 1; | 794 | for (j = dirty, dlast = mud->messages_count - 1; |
842 | j < mud->messages_count; j++) | 795 | j < mud->messages_count; j++) |
843 | { | 796 | { |
844 | /* clear all the references, | 797 | /* Clear all the references, any attach messages been already |
845 | * any attach messages been already destroy above | 798 | destroy above. */ |
846 | */ | ||
847 | mum = mud->umessages[j]; | 799 | mum = mud->umessages[j]; |
848 | if (mum->new_attr && attribute_is_deleted (mum->new_attr)) | 800 | if (mum->new_flags && ATTRIBUTE_IS_DELETED (mum->new_flags)) |
849 | { | 801 | { |
850 | memmove (mud->umessages + j, mud->umessages + j + 1, | 802 | memmove (mud->umessages + j, mud->umessages + j + 1, |
851 | (dlast - dirty) * sizeof (mum)); | 803 | (dlast - dirty) * sizeof (mum)); |
... | @@ -853,7 +805,6 @@ mailbox_unix_expunge (mailbox_t mbox) | ... | @@ -853,7 +805,6 @@ mailbox_unix_expunge (mailbox_t mbox) |
853 | mum->header_status = mum->header_status_end = 0; | 805 | mum->header_status = mum->header_status_end = 0; |
854 | mum->body = mum->body_end = 0; | 806 | mum->body = mum->body_end = 0; |
855 | mum->header_lines = mum->body_lines = 0; | 807 | mum->header_lines = mum->body_lines = 0; |
856 | attribute_destroy (&(mum->new_attr)); | ||
857 | mud->umessages[dlast] = mum; | 808 | mud->umessages[dlast] = mum; |
858 | dlast--; | 809 | dlast--; |
859 | mum = mud->umessages[j]; | 810 | mum = mud->umessages[j]; |
... | @@ -863,18 +814,17 @@ mailbox_unix_expunge (mailbox_t mbox) | ... | @@ -863,18 +814,17 @@ mailbox_unix_expunge (mailbox_t mbox) |
863 | mum->body = mum->body_end = 0; | 814 | mum->body = mum->body_end = 0; |
864 | mum->header_lines = mum->body_lines = 0; | 815 | mum->header_lines = mum->body_lines = 0; |
865 | } | 816 | } |
866 | /* this is should reset the messages_count, the last | 817 | /* This is should reset the messages_count, the last * argument 0 means |
867 | * argument 0 means not to send event notification | 818 | not to send event notification. */ |
868 | */ | 819 | unix_scan0 (mbox, dirty, NULL, 0); |
869 | mailbox_unix_scan0 (mbox, dirty, NULL, 0); | ||
870 | } | 820 | } |
871 | return status; | 821 | return status; |
872 | } | 822 | } |
873 | 823 | ||
874 | static int | 824 | static int |
875 | mailbox_unix_getfd (stream_t is, int *pfd) | 825 | unix_get_fd (stream_t is, int *pfd) |
876 | { | 826 | { |
877 | mailbox_unix_message_t mum; | 827 | unix_message_t mum; |
878 | 828 | ||
879 | if (is == NULL || (mum = is->owner) == NULL) | 829 | if (is == NULL || (mum = is->owner) == NULL) |
880 | return EINVAL; | 830 | return EINVAL; |
... | @@ -883,13 +833,50 @@ mailbox_unix_getfd (stream_t is, int *pfd) | ... | @@ -883,13 +833,50 @@ mailbox_unix_getfd (stream_t is, int *pfd) |
883 | } | 833 | } |
884 | 834 | ||
885 | static int | 835 | static int |
886 | mailbox_unix_readstream (stream_t is, char *buffer, size_t buflen, | 836 | unix_get_flags (attribute_t attr, int *pflags) |
837 | { | ||
838 | unix_message_t mum; | ||
839 | |||
840 | if (attr == NULL || (mum = attr->owner) == NULL) | ||
841 | return EINVAL; | ||
842 | |||
843 | if (pflags) | ||
844 | *pflags = mum->new_flags; | ||
845 | return 0; | ||
846 | } | ||
847 | |||
848 | static int | ||
849 | unix_set_flags (attribute_t attr, int flags) | ||
850 | { | ||
851 | unix_message_t mum; | ||
852 | |||
853 | if (attr == NULL || (mum = attr->owner) == NULL) | ||
854 | return EINVAL; | ||
855 | |||
856 | mum->new_flags |= flags; | ||
857 | return 0; | ||
858 | } | ||
859 | |||
860 | static int | ||
861 | unix_unset_flags (attribute_t attr, int flags) | ||
862 | { | ||
863 | unix_message_t mum; | ||
864 | |||
865 | if (attr == NULL || (mum = attr->owner) == NULL) | ||
866 | return EINVAL; | ||
867 | |||
868 | mum->new_flags &= flags; | ||
869 | return 0; | ||
870 | } | ||
871 | |||
872 | static int | ||
873 | unix_readstream (stream_t is, char *buffer, size_t buflen, | ||
887 | off_t off, size_t *pnread) | 874 | off_t off, size_t *pnread) |
888 | { | 875 | { |
889 | mailbox_unix_message_t mum; | 876 | unix_message_t mum; |
890 | size_t nread = 0; | 877 | size_t nread = 0; |
891 | 878 | ||
892 | if (is == NULL || (mum = (mailbox_unix_message_t)is->owner) == NULL) | 879 | if (is == NULL || (mum = (unix_message_t)is->owner) == NULL) |
893 | return EINVAL; | 880 | return EINVAL; |
894 | 881 | ||
895 | if (buffer == NULL || buflen == 0) | 882 | if (buffer == NULL || buflen == 0) |
... | @@ -906,7 +893,7 @@ mailbox_unix_readstream (stream_t is, char *buffer, size_t buflen, | ... | @@ -906,7 +893,7 @@ mailbox_unix_readstream (stream_t is, char *buffer, size_t buflen, |
906 | if (ln > 0) | 893 | if (ln > 0) |
907 | { | 894 | { |
908 | nread = ((size_t)ln < buflen) ? ln : buflen; | 895 | nread = ((size_t)ln < buflen) ? ln : buflen; |
909 | /* position the file pointer and the buffer */ | 896 | /* Position the file pointer and the buffer. */ |
910 | status = stream_read (mum->stream, buffer, nread, mum->body + off, &n); | 897 | status = stream_read (mum->stream, buffer, nread, mum->body + off, &n); |
911 | if (status != 0) | 898 | if (status != 0) |
912 | return status; | 899 | return status; |
... | @@ -919,30 +906,34 @@ mailbox_unix_readstream (stream_t is, char *buffer, size_t buflen, | ... | @@ -919,30 +906,34 @@ mailbox_unix_readstream (stream_t is, char *buffer, size_t buflen, |
919 | } | 906 | } |
920 | 907 | ||
921 | static int | 908 | static int |
922 | mailbox_unix_get_header (mailbox_unix_message_t mum, char *buffer, | 909 | unix_get_header_read (stream_t is, char *buffer, size_t len, |
923 | size_t len, off_t off, ssize_t *pnread) | 910 | off_t off, size_t *pnread) |
924 | { | 911 | { |
912 | unix_message_t mum; | ||
925 | size_t nread = 0; | 913 | size_t nread = 0; |
926 | size_t n = 0; | 914 | int status = 0; |
927 | int status; | 915 | off_t ln; |
928 | off_t ln = mum->body - (mum->header_from_end + off); | 916 | |
917 | if (is == NULL || (mum = is->owner) == NULL) | ||
918 | return EINVAL; | ||
919 | |||
920 | ln = mum->body - (mum->header_from_end + off); | ||
929 | if (ln > 0) | 921 | if (ln > 0) |
930 | { | 922 | { |
931 | nread = ((size_t)ln < len) ? ln : len; | 923 | nread = ((size_t)ln < len) ? ln : len; |
932 | /* position the file pointer and the buffer */ | 924 | /* Position the file pointer and the buffer. */ |
933 | status = stream_read (mum->stream, buffer, nread, | 925 | status = stream_read (mum->stream, buffer, nread, |
934 | mum->header_from_end + off, &n); | 926 | mum->header_from_end + off, &nread); |
935 | if (status != 0) | ||
936 | return status; | ||
937 | } | 927 | } |
928 | if (pnread) | ||
938 | *pnread = nread; | 929 | *pnread = nread; |
939 | return 0; | 930 | return status; |
940 | } | 931 | } |
941 | 932 | ||
942 | static int | 933 | static int |
943 | mailbox_unix_body_size (body_t body, size_t *psize) | 934 | unix_body_size (body_t body, size_t *psize) |
944 | { | 935 | { |
945 | mailbox_unix_message_t mum = body->owner; | 936 | unix_message_t mum = body->owner; |
946 | if (mum == NULL) | 937 | if (mum == NULL) |
947 | return EINVAL; | 938 | return EINVAL; |
948 | if (psize) | 939 | if (psize) |
... | @@ -951,9 +942,9 @@ mailbox_unix_body_size (body_t body, size_t *psize) | ... | @@ -951,9 +942,9 @@ mailbox_unix_body_size (body_t body, size_t *psize) |
951 | } | 942 | } |
952 | 943 | ||
953 | static int | 944 | static int |
954 | mailbox_unix_body_lines (body_t body, size_t *plines) | 945 | unix_body_lines (body_t body, size_t *plines) |
955 | { | 946 | { |
956 | mailbox_unix_message_t mum = body->owner; | 947 | unix_message_t mum = body->owner; |
957 | if (mum == NULL) | 948 | if (mum == NULL) |
958 | return EINVAL; | 949 | return EINVAL; |
959 | if (plines) | 950 | if (plines) |
... | @@ -962,10 +953,10 @@ mailbox_unix_body_lines (body_t body, size_t *plines) | ... | @@ -962,10 +953,10 @@ mailbox_unix_body_lines (body_t body, size_t *plines) |
962 | } | 953 | } |
963 | 954 | ||
964 | static int | 955 | static int |
965 | mailbox_unix_msg_received (message_t msg, char *buf, size_t len, | 956 | unix_msg_received (message_t msg, char *buf, size_t len, |
966 | size_t *pnwrite) | 957 | size_t *pnwrite) |
967 | { | 958 | { |
968 | mailbox_unix_message_t mum = msg->owner; | 959 | unix_message_t mum = msg->owner; |
969 | size_t n = 0; | 960 | size_t n = 0; |
970 | int status; | 961 | int status; |
971 | char buffer[512]; | 962 | char buffer[512]; |
... | @@ -975,7 +966,6 @@ mailbox_unix_msg_received (message_t msg, char *buf, size_t len, | ... | @@ -975,7 +966,6 @@ mailbox_unix_msg_received (message_t msg, char *buf, size_t len, |
975 | 966 | ||
976 | status = stream_readline (mum->stream, buffer, sizeof(buffer), | 967 | status = stream_readline (mum->stream, buffer, sizeof(buffer), |
977 | mum->header_from, &n); | 968 | mum->header_from, &n); |
978 | |||
979 | if (status != 0) | 969 | if (status != 0) |
980 | { | 970 | { |
981 | if (pnwrite) | 971 | if (pnwrite) |
... | @@ -1008,9 +998,9 @@ mailbox_unix_msg_received (message_t msg, char *buf, size_t len, | ... | @@ -1008,9 +998,9 @@ mailbox_unix_msg_received (message_t msg, char *buf, size_t len, |
1008 | } | 998 | } |
1009 | 999 | ||
1010 | static int | 1000 | static int |
1011 | mailbox_unix_msg_from (message_t msg, char *buf, size_t len, size_t *pnwrite) | 1001 | unix_msg_from (message_t msg, char *buf, size_t len, size_t *pnwrite) |
1012 | { | 1002 | { |
1013 | mailbox_unix_message_t mum = msg->owner; | 1003 | unix_message_t mum = msg->owner; |
1014 | size_t n = 0; | 1004 | size_t n = 0; |
1015 | int status; | 1005 | int status; |
1016 | char buffer[512]; | 1006 | char buffer[512]; |
... | @@ -1053,31 +1043,22 @@ mailbox_unix_msg_from (message_t msg, char *buf, size_t len, size_t *pnwrite) | ... | @@ -1053,31 +1043,22 @@ mailbox_unix_msg_from (message_t msg, char *buf, size_t len, size_t *pnwrite) |
1053 | } | 1043 | } |
1054 | 1044 | ||
1055 | static int | 1045 | static int |
1056 | mailbox_unix_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) | 1046 | unix_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) |
1057 | { | 1047 | { |
1058 | int status; | 1048 | int status; |
1059 | ssize_t nread; | 1049 | unix_data_t mud; |
1060 | char *pbuf = NULL; | 1050 | unix_message_t mum; |
1061 | char *tbuf = NULL; | ||
1062 | char buf[BUFSIZ]; | ||
1063 | off_t offset = 0; | ||
1064 | mailbox_unix_data_t mud; | ||
1065 | mailbox_unix_message_t mum; | ||
1066 | message_t msg = NULL; | 1051 | message_t msg = NULL; |
1067 | stream_t stream = NULL; | 1052 | |
1068 | header_t header = NULL; | 1053 | /* Sanity checks. */ |
1069 | body_t body = NULL; | 1054 | if (mbox == NULL || pmsg == NULL || (mud = (unix_data_t)mbox->data) == NULL |
1070 | int flags = 0; | 1055 | || (!(mud->messages_count > 0 && msgno > 0 |
1071 | 1056 | && msgno <= mud->messages_count))) | |
1072 | if (mbox == NULL || pmsg == NULL || | ||
1073 | (mud = (mailbox_unix_data_t)mbox->data) == NULL || | ||
1074 | (!(mud->messages_count > 0 && msgno > 0 && | ||
1075 | msgno <= mud->messages_count))) | ||
1076 | return EINVAL; | 1057 | return EINVAL; |
1077 | 1058 | ||
1078 | mum = mud->umessages[msgno - 1]; | 1059 | mum = mud->umessages[msgno - 1]; |
1079 | 1060 | ||
1080 | /* check if we already have it */ | 1061 | /* Check if we already have it. */ |
1081 | if (mum->message) | 1062 | if (mum->message) |
1082 | { | 1063 | { |
1083 | if (pmsg) | 1064 | if (pmsg) |
... | @@ -1086,89 +1067,72 @@ mailbox_unix_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) | ... | @@ -1086,89 +1067,72 @@ mailbox_unix_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) |
1086 | } | 1067 | } |
1087 | 1068 | ||
1088 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_TRACE, | 1069 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_TRACE, |
1089 | "mailbox_unix_get_message(%s, %d)\n", mbox->name, msgno); | 1070 | "unix_get_message(%s, %d)\n", mbox->name, msgno); |
1090 | /* get the headers */ | ||
1091 | do | ||
1092 | { | ||
1093 | status = mailbox_unix_get_header (mum, buf, sizeof(buf), offset, &nread); | ||
1094 | if (status != 0) | ||
1095 | { | ||
1096 | free (pbuf); | ||
1097 | return status; | ||
1098 | } | ||
1099 | |||
1100 | if (nread == 0) | ||
1101 | break; | ||
1102 | |||
1103 | tbuf = realloc (pbuf, offset + nread); | ||
1104 | if (tbuf == NULL) | ||
1105 | { | ||
1106 | free (pbuf); | ||
1107 | return ENOMEM; | ||
1108 | } | ||
1109 | else | ||
1110 | pbuf = tbuf; | ||
1111 | memcpy (pbuf + offset, buf, nread); | ||
1112 | offset += nread; | ||
1113 | } while (nread > 0); | ||
1114 | 1071 | ||
1115 | /* get an empty message struct */ | 1072 | /* Get an empty message struct. */ |
1116 | status = message_create (&msg, mum); | 1073 | status = message_create (&msg, mum); |
1117 | if (status != 0) | 1074 | if (status != 0) |
1118 | { | ||
1119 | free (pbuf); | ||
1120 | return status; | 1075 | return status; |
1121 | } | ||
1122 | 1076 | ||
1123 | /* set the header */ | 1077 | /* Set the header. */ |
1124 | status = header_create (&header, pbuf, offset, mum); | 1078 | { |
1125 | if (status != 0) | 1079 | header_t header; |
1080 | stream_t stream; | ||
1081 | if ((status = header_create (&header, NULL, 0, mum)) != 0 | ||
1082 | || (status = stream_create (&stream, MU_STREAM_READ, mum)) != 0) | ||
1126 | { | 1083 | { |
1127 | free (pbuf); | ||
1128 | message_destroy (&msg, mum); | 1084 | message_destroy (&msg, mum); |
1129 | return status; | 1085 | return status; |
1130 | } | 1086 | } |
1131 | free (pbuf); | 1087 | stream_set_read (stream, unix_get_header_read, mum); |
1088 | stream_set_fd (stream, unix_get_fd, mum); | ||
1089 | stream_set_flags (stream, MU_STREAM_READ, mum); | ||
1090 | header_set_stream (header, stream, mum); | ||
1132 | message_set_header (msg, header, mum); | 1091 | message_set_header (msg, header, mum); |
1092 | } | ||
1133 | 1093 | ||
1134 | /* prepare the body */ | 1094 | /* Set the attribute. */ |
1135 | status = body_create (&body, mum); | 1095 | { |
1096 | attribute_t attribute; | ||
1097 | status = attribute_create (&attribute, mum); | ||
1136 | if (status != 0) | 1098 | if (status != 0) |
1137 | { | 1099 | { |
1138 | message_destroy (&msg, mum); | 1100 | message_destroy (&msg, mum); |
1139 | return status; | 1101 | return status; |
1140 | } | 1102 | } |
1141 | message_set_body (msg, body, mum); | 1103 | mum->new_flags = mum->old_flags; |
1104 | attribute_set_get_flags (attribute, unix_get_flags, mum); | ||
1105 | attribute_set_set_flags (attribute, unix_set_flags, mum); | ||
1106 | attribute_set_unset_flags (attribute, unix_unset_flags, mum); | ||
1107 | message_set_attribute (msg, attribute, mum); | ||
1108 | } | ||
1142 | 1109 | ||
1143 | status = stream_create (&stream, MU_STREAM_READ, mum); | 1110 | /* Prepare the body. */ |
1144 | if (status != 0) | 1111 | { |
1112 | body_t body; | ||
1113 | stream_t stream; | ||
1114 | int flags = MU_STREAM_READ; | ||
1115 | if ((status = body_create (&body, mum)) != 0 | ||
1116 | || (status = stream_create (&stream, flags, mum)) != 0) | ||
1145 | { | 1117 | { |
1146 | message_destroy (&msg, mum); | 1118 | message_destroy (&msg, mum); |
1147 | return status; | 1119 | return status; |
1148 | } | 1120 | } |
1149 | stream_set_read (stream, mailbox_unix_readstream, mum); | 1121 | stream_set_read (stream, unix_readstream, mum); |
1150 | stream_set_fd (stream, mailbox_unix_getfd, mum); | 1122 | stream_set_fd (stream, unix_get_fd, mum); |
1151 | stream_get_flags (mbox->stream, &flags); | 1123 | stream_get_flags (mbox->stream, &flags); |
1152 | stream_set_flags (stream, flags, mum); | 1124 | stream_set_flags (stream, flags, mum); |
1153 | body_set_stream (body, stream, mum); | 1125 | body_set_stream (body, stream, mum); |
1154 | body_set_size (body, mailbox_unix_body_size, mum); | 1126 | body_set_size (body, unix_body_size, mum); |
1155 | body_set_lines (body, mailbox_unix_body_lines, mum); | 1127 | body_set_lines (body, unix_body_lines, mum); |
1156 | 1128 | message_set_body (msg, body, mum); | |
1157 | /* set the attribute */ | ||
1158 | attribute_create (&(mum->new_attr)); | ||
1159 | mum->new_attr->flag = mum->old_attr->flag; | ||
1160 | status = message_set_attribute (msg, mum->new_attr, mum); | ||
1161 | if (status != 0) | ||
1162 | { | ||
1163 | message_destroy (&msg, mum); | ||
1164 | return status; | ||
1165 | } | 1129 | } |
1166 | 1130 | ||
1167 | /* set the envelope */ | 1131 | /* Set the envelope. */ |
1168 | message_set_from (msg, mailbox_unix_msg_from, mum); | 1132 | message_set_from (msg, unix_msg_from, mum); |
1169 | message_set_received (msg, mailbox_unix_msg_received, mum); | 1133 | message_set_received (msg, unix_msg_received, mum); |
1170 | 1134 | ||
1171 | /* attach the message to the mailbox unix data */ | 1135 | /* Attach the message to the mailbox unix data. */ |
1172 | mum->message = msg; | 1136 | mum->message = msg; |
1173 | 1137 | ||
1174 | if (pmsg) | 1138 | if (pmsg) |
... | @@ -1177,17 +1141,17 @@ mailbox_unix_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) | ... | @@ -1177,17 +1141,17 @@ mailbox_unix_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) |
1177 | } | 1141 | } |
1178 | 1142 | ||
1179 | static int | 1143 | static int |
1180 | mailbox_unix_append_message (mailbox_t mbox, message_t msg) | 1144 | unix_append_message (mailbox_t mbox, message_t msg) |
1181 | { | 1145 | { |
1182 | mailbox_unix_data_t mud; | 1146 | unix_data_t mud; |
1183 | if (mbox == NULL || msg == NULL || | 1147 | if (mbox == NULL || msg == NULL || |
1184 | (mud = (mailbox_unix_data_t)mbox->data) == NULL) | 1148 | (mud = (unix_data_t)mbox->data) == NULL) |
1185 | return EINVAL; | 1149 | return EINVAL; |
1186 | 1150 | ||
1187 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_TRACE, | 1151 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_TRACE, |
1188 | "mailbox_unix_append_message (%s)\n", mbox->name); | 1152 | "unix_append_message (%s)\n", mbox->name); |
1189 | 1153 | ||
1190 | mailbox_unix_lock (mbox, MU_LOCKER_WRLOCK); | 1154 | unix_lock (mbox, MU_LOCKER_WRLOCK); |
1191 | { | 1155 | { |
1192 | off_t size; | 1156 | off_t size; |
1193 | char buffer[BUFSIZ]; | 1157 | char buffer[BUFSIZ]; |
... | @@ -1199,16 +1163,16 @@ mailbox_unix_append_message (mailbox_t mbox, message_t msg) | ... | @@ -1199,16 +1163,16 @@ mailbox_unix_append_message (mailbox_t mbox, message_t msg) |
1199 | size_t n = 0; | 1163 | size_t n = 0; |
1200 | char nl = '\n'; | 1164 | char nl = '\n'; |
1201 | 1165 | ||
1202 | /* move to the end of the file, not necesary if _APPEND mode */ | 1166 | /* Move to the end of the file, not necesary if _APPEND mode. */ |
1203 | status = stream_size (mbox->stream, &size); | 1167 | status = stream_size (mbox->stream, &size); |
1204 | if (status != 0) | 1168 | if (status != 0) |
1205 | { | 1169 | { |
1206 | mailbox_unix_unlock (mbox); | 1170 | unix_unlock (mbox); |
1207 | return status; | 1171 | return status; |
1208 | } | 1172 | } |
1209 | /* header */ | 1173 | /* Header. */ |
1210 | message_get_header (msg, &hdr); | 1174 | message_get_header (msg, &hdr); |
1211 | /* generate a "From " separator */ | 1175 | /* Generate a "From " separator. */ |
1212 | { | 1176 | { |
1213 | char from[128]; | 1177 | char from[128]; |
1214 | char date[128]; | 1178 | char date[128]; |
... | @@ -1249,10 +1213,10 @@ mailbox_unix_append_message (mailbox_t mbox, message_t msg) | ... | @@ -1249,10 +1213,10 @@ mailbox_unix_append_message (mailbox_t mbox, message_t msg) |
1249 | } while (nread > 0); | 1213 | } while (nread > 0); |
1250 | 1214 | ||
1251 | *buffer = '\0'; | 1215 | *buffer = '\0'; |
1252 | /* separator */ | 1216 | /* Separator. */ |
1253 | /*fputc ('\n', mud->file);*/ | 1217 | /*fputc ('\n', mud->file);*/ |
1254 | 1218 | ||
1255 | /* body */ | 1219 | /* Body. */ |
1256 | message_get_stream (msg, &is); | 1220 | message_get_stream (msg, &is); |
1257 | do { | 1221 | do { |
1258 | stream_read (is, buffer, sizeof (buffer), off, &nread); | 1222 | stream_read (is, buffer, sizeof (buffer), off, &nread); |
... | @@ -1263,12 +1227,12 @@ mailbox_unix_append_message (mailbox_t mbox, message_t msg) | ... | @@ -1263,12 +1227,12 @@ mailbox_unix_append_message (mailbox_t mbox, message_t msg) |
1263 | stream_write (mbox->stream, &nl, 1, size, &n); | 1227 | stream_write (mbox->stream, &nl, 1, size, &n); |
1264 | } | 1228 | } |
1265 | stream_flush (mbox->stream); | 1229 | stream_flush (mbox->stream); |
1266 | mailbox_unix_unlock (mbox); | 1230 | unix_unlock (mbox); |
1267 | return 0; | 1231 | return 0; |
1268 | } | 1232 | } |
1269 | 1233 | ||
1270 | static int | 1234 | static int |
1271 | mailbox_unix_size (mailbox_t mbox, off_t *psize) | 1235 | unix_size (mailbox_t mbox, off_t *psize) |
1272 | { | 1236 | { |
1273 | off_t size; | 1237 | off_t size; |
1274 | int status; | 1238 | int status; |
... | @@ -1276,7 +1240,7 @@ mailbox_unix_size (mailbox_t mbox, off_t *psize) | ... | @@ -1276,7 +1240,7 @@ mailbox_unix_size (mailbox_t mbox, off_t *psize) |
1276 | if (mbox == NULL) | 1240 | if (mbox == NULL) |
1277 | return EINVAL; | 1241 | return EINVAL; |
1278 | 1242 | ||
1279 | /* maybe was not open yet ?? */ | 1243 | /* Maybe was not open yet ?? */ |
1280 | status = stream_size (mbox->stream, &size); | 1244 | status = stream_size (mbox->stream, &size); |
1281 | if (status != 0) | 1245 | if (status != 0) |
1282 | return status; | 1246 | return status; |
... | @@ -1286,14 +1250,14 @@ mailbox_unix_size (mailbox_t mbox, off_t *psize) | ... | @@ -1286,14 +1250,14 @@ mailbox_unix_size (mailbox_t mbox, off_t *psize) |
1286 | } | 1250 | } |
1287 | 1251 | ||
1288 | static int | 1252 | static int |
1289 | mailbox_unix_messages_count (mailbox_t mbox, size_t *pcount) | 1253 | unix_messages_count (mailbox_t mbox, size_t *pcount) |
1290 | { | 1254 | { |
1291 | mailbox_unix_data_t mud; | 1255 | unix_data_t mud; |
1292 | if (mbox == NULL || (mud = (mailbox_unix_data_t) mbox->data) == NULL) | 1256 | if (mbox == NULL || (mud = (unix_data_t) mbox->data) == NULL) |
1293 | return EINVAL; | 1257 | return EINVAL; |
1294 | 1258 | ||
1295 | if (! mailbox_unix_is_updated (mbox)) | 1259 | if (! unix_is_updated (mbox)) |
1296 | return mailbox_unix_scan0 (mbox, 1, pcount, 1); | 1260 | return unix_scan0 (mbox, 1, pcount, 1); |
1297 | 1261 | ||
1298 | if (pcount) | 1262 | if (pcount) |
1299 | *pcount = mud->messages_count; | 1263 | *pcount = mud->messages_count; |
... | @@ -1301,9 +1265,9 @@ mailbox_unix_messages_count (mailbox_t mbox, size_t *pcount) | ... | @@ -1301,9 +1265,9 @@ mailbox_unix_messages_count (mailbox_t mbox, size_t *pcount) |
1301 | return 0; | 1265 | return 0; |
1302 | } | 1266 | } |
1303 | 1267 | ||
1304 | /* locking */ | 1268 | /* Locking. */ |
1305 | static int | 1269 | static int |
1306 | mailbox_unix_lock (mailbox_t mbox, int flag) | 1270 | unix_lock (mailbox_t mbox, int flag) |
1307 | { | 1271 | { |
1308 | if (mbox && mbox->locker != NULL) | 1272 | if (mbox && mbox->locker != NULL) |
1309 | { | 1273 | { |
... | @@ -1314,7 +1278,7 @@ mailbox_unix_lock (mailbox_t mbox, int flag) | ... | @@ -1314,7 +1278,7 @@ mailbox_unix_lock (mailbox_t mbox, int flag) |
1314 | } | 1278 | } |
1315 | 1279 | ||
1316 | static int | 1280 | static int |
1317 | mailbox_unix_touchlock (mailbox_t mbox) | 1281 | unix_touchlock (mailbox_t mbox) |
1318 | { | 1282 | { |
1319 | if (mbox && mbox->locker != NULL) | 1283 | if (mbox && mbox->locker != NULL) |
1320 | { | 1284 | { |
... | @@ -1325,7 +1289,7 @@ mailbox_unix_touchlock (mailbox_t mbox) | ... | @@ -1325,7 +1289,7 @@ mailbox_unix_touchlock (mailbox_t mbox) |
1325 | } | 1289 | } |
1326 | 1290 | ||
1327 | static int | 1291 | static int |
1328 | mailbox_unix_unlock (mailbox_t mbox) | 1292 | unix_unlock (mailbox_t mbox) |
1329 | { | 1293 | { |
1330 | if (mbox && mbox->locker != NULL) | 1294 | if (mbox && mbox->locker != NULL) |
1331 | { | 1295 | { |
... | @@ -1336,10 +1300,10 @@ mailbox_unix_unlock (mailbox_t mbox) | ... | @@ -1336,10 +1300,10 @@ mailbox_unix_unlock (mailbox_t mbox) |
1336 | } | 1300 | } |
1337 | 1301 | ||
1338 | static int | 1302 | static int |
1339 | mailbox_unix_ilock (mailbox_t mbox, int flag) | 1303 | unix_ilock (mailbox_t mbox, int flag) |
1340 | { | 1304 | { |
1341 | #ifdef HAVE_PTHREAD_H | 1305 | #ifdef HAVE_PTHREAD_H |
1342 | (void)flag; /* we should use rwlocks for more concurency */ | 1306 | (void)flag; /* We should use rwlocks for more concurency. */ |
1343 | if (mbox == NULL) | 1307 | if (mbox == NULL) |
1344 | return EINVAL; | 1308 | return EINVAL; |
1345 | return pthread_mutex_lock (&(mbox->mutex)); | 1309 | return pthread_mutex_lock (&(mbox->mutex)); |
... | @@ -1350,7 +1314,7 @@ mailbox_unix_ilock (mailbox_t mbox, int flag) | ... | @@ -1350,7 +1314,7 @@ mailbox_unix_ilock (mailbox_t mbox, int flag) |
1350 | } | 1314 | } |
1351 | 1315 | ||
1352 | static int | 1316 | static int |
1353 | mailbox_unix_iunlock (mailbox_t mbox) | 1317 | unix_iunlock (mailbox_t mbox) |
1354 | { | 1318 | { |
1355 | #ifdef HAVE_PTHREAD_H | 1319 | #ifdef HAVE_PTHREAD_H |
1356 | if (mbox == NULL) | 1320 | if (mbox == NULL) | ... | ... |
... | @@ -173,7 +173,7 @@ do \ | ... | @@ -173,7 +173,7 @@ do \ |
173 | { \ | 173 | { \ |
174 | if (*s == c0 || *s == c1) \ | 174 | if (*s == c0 || *s == c1) \ |
175 | { \ | 175 | { \ |
176 | (mum)->old_attr->flag |= (type); \ | 176 | (mum)->old_flags |= (type); \ |
177 | break; \ | 177 | break; \ |
178 | } \ | 178 | } \ |
179 | } \ | 179 | } \ |
... | @@ -206,16 +206,16 @@ do \ | ... | @@ -206,16 +206,16 @@ do \ |
206 | do \ | 206 | do \ |
207 | { \ | 207 | { \ |
208 | int bailing = 0; \ | 208 | int bailing = 0; \ |
209 | mailbox_unix_iunlock (mbox); \ | 209 | unix_iunlock (mbox); \ |
210 | MAILBOX_NOTIFICATION (mbox, MU_EVT_MBX_MSG_ADD, bailing); \ | 210 | MAILBOX_NOTIFICATION (mbox, MU_EVT_MBX_MSG_ADD, bailing); \ |
211 | if (bailing != 0) \ | 211 | if (bailing != 0) \ |
212 | { \ | 212 | { \ |
213 | if (pcount) \ | 213 | if (pcount) \ |
214 | *pcount = (mud)->messages_count; \ | 214 | *pcount = (mud)->messages_count; \ |
215 | mailbox_unix_unlock (mbox); \ | 215 | unix_unlock (mbox); \ |
216 | return EINTR; \ | 216 | return EINTR; \ |
217 | } \ | 217 | } \ |
218 | mailbox_unix_ilock (mbox, MU_LOCKER_WRLOCK); \ | 218 | unix_ilock (mbox, MU_LOCKER_WRLOCK); \ |
219 | } while (0); | 219 | } while (0); |
220 | 220 | ||
221 | /* notification MBX_PROGRESS | 221 | /* notification MBX_PROGRESS |
... | @@ -234,33 +234,38 @@ do \ | ... | @@ -234,33 +234,38 @@ do \ |
234 | { \ | 234 | { \ |
235 | { \ | 235 | { \ |
236 | int bailing = 0; \ | 236 | int bailing = 0; \ |
237 | mailbox_unix_iunlock (mbox); \ | 237 | unix_iunlock (mbox); \ |
238 | mud->messages_count--; \ | 238 | mud->messages_count--; \ |
239 | MAILBOX_NOTIFICATION (mbox, MU_EVT_MBX_PROGRESS,bailing); \ | 239 | MAILBOX_NOTIFICATION (mbox, MU_EVT_MBX_PROGRESS,bailing); \ |
240 | if (bailing != 0) \ | 240 | if (bailing != 0) \ |
241 | { \ | 241 | { \ |
242 | if (pcount) \ | 242 | if (pcount) \ |
243 | *pcount = (mud)->messages_count; \ | 243 | *pcount = (mud)->messages_count; \ |
244 | mailbox_unix_unlock (mbox); \ | 244 | unix_unlock (mbox); \ |
245 | return EINTR; \ | 245 | return EINTR; \ |
246 | } \ | 246 | } \ |
247 | mud->messages_count++; \ | 247 | mud->messages_count++; \ |
248 | mailbox_unix_ilock (mbox, MU_LOCKER_WRLOCK); \ | 248 | unix_ilock (mbox, MU_LOCKER_WRLOCK); \ |
249 | } \ | 249 | } \ |
250 | } while (0) | 250 | } while (0) |
251 | 251 | ||
252 | #if 0 | ||
252 | /* skip a function call, ?? do we gain that much */ | 253 | /* skip a function call, ?? do we gain that much */ |
253 | #define ATTRIBUTE_CREATE(attr,mbox) \ | 254 | #define ATTRIBUTE_CREATE(attr, m, mbox) \ |
254 | do \ | 255 | do \ |
255 | { \ | 256 | { \ |
256 | attr = calloc (1, sizeof(*(attr))); \ | 257 | attr = calloc (1, sizeof(*(attr))); \ |
258 | attr->owner = m; \ | ||
257 | if ((attr) == NULL) \ | 259 | if ((attr) == NULL) \ |
258 | { \ | 260 | { \ |
259 | mailbox_unix_iunlock (mbox); \ | 261 | unix_iunlock (mbox); \ |
260 | mailbox_unix_unlock (mbox); \ | 262 | unix_unlock (mbox); \ |
261 | return ENOMEM; \ | 263 | return ENOMEM; \ |
262 | } \ | 264 | } \ |
263 | } while (0) | 265 | } while (0) |
266 | #else | ||
267 | # define ATTRIBUTE_CREATE | ||
268 | #endif | ||
264 | 269 | ||
265 | /* allocate slots for the new messages */ | 270 | /* allocate slots for the new messages */ |
266 | /* size_t num = 2 * ((mud)->messages_count) + 10; */ | 271 | /* size_t num = 2 * ((mud)->messages_count) + 10; */ |
... | @@ -269,38 +274,37 @@ do \ | ... | @@ -269,38 +274,37 @@ do \ |
269 | { \ | 274 | { \ |
270 | if ((mud)->messages_count >= (mud)->umessages_count) \ | 275 | if ((mud)->messages_count >= (mud)->umessages_count) \ |
271 | { \ | 276 | { \ |
272 | mailbox_unix_message_t *m; \ | 277 | unix_message_t *m; \ |
273 | size_t num = ((mud)->umessages_count) + 1; \ | 278 | size_t num = ((mud)->umessages_count) + 1; \ |
274 | m = realloc ((mud)->umessages, num * sizeof (*m)); \ | 279 | m = realloc ((mud)->umessages, num * sizeof (*m)); \ |
275 | if (m == NULL) \ | 280 | if (m == NULL) \ |
276 | { \ | 281 | { \ |
277 | mailbox_unix_iunlock (mbox); \ | 282 | unix_iunlock (mbox); \ |
278 | mailbox_unix_unlock (mbox); \ | 283 | unix_unlock (mbox); \ |
279 | return ENOMEM; \ | 284 | return ENOMEM; \ |
280 | } \ | 285 | } \ |
281 | (mud)->umessages = m; \ | 286 | (mud)->umessages = m; \ |
282 | (mud)->umessages[num - 1] = calloc (1, sizeof (*(mum))); \ | 287 | (mud)->umessages[num - 1] = calloc (1, sizeof (*(mum))); \ |
283 | if ((mud)->umessages[num - 1] == NULL) \ | 288 | if ((mud)->umessages[num - 1] == NULL) \ |
284 | { \ | 289 | { \ |
285 | mailbox_unix_iunlock (mbox); \ | 290 | unix_iunlock (mbox); \ |
286 | mailbox_unix_unlock (mbox); \ | 291 | unix_unlock (mbox); \ |
287 | return ENOMEM; \ | 292 | return ENOMEM; \ |
288 | } \ | 293 | } \ |
289 | ATTRIBUTE_CREATE (((mud)->umessages[num - 1])->old_attr, mbox); \ | ||
290 | (mud)->umessages_count = num; \ | 294 | (mud)->umessages_count = num; \ |
291 | } \ | 295 | } \ |
292 | } while (0) | 296 | } while (0) |
293 | 297 | ||
294 | static int | 298 | static int |
295 | mailbox_unix_scan0 (mailbox_t mbox, size_t msgno, size_t *pcount, int do_notif) | 299 | unix_scan0 (mailbox_t mbox, size_t msgno, size_t *pcount, int do_notif) |
296 | { | 300 | { |
297 | #define MSGLINELEN 1024 | 301 | #define MSGLINELEN 1024 |
298 | char buf[MSGLINELEN]; | 302 | char buf[MSGLINELEN]; |
299 | int inheader; | 303 | int inheader; |
300 | int inbody; | 304 | int inbody; |
301 | off_t total = 0; | 305 | off_t total = 0; |
302 | mailbox_unix_data_t mud; | 306 | unix_data_t mud; |
303 | mailbox_unix_message_t mum = NULL; | 307 | unix_message_t mum = NULL; |
304 | int status = 0; | 308 | int status = 0; |
305 | size_t lines; | 309 | size_t lines; |
306 | int newline; | 310 | int newline; |
... | @@ -311,7 +315,7 @@ mailbox_unix_scan0 (mailbox_t mbox, size_t msgno, size_t *pcount, int do_notif) | ... | @@ -311,7 +315,7 @@ mailbox_unix_scan0 (mailbox_t mbox, size_t msgno, size_t *pcount, int do_notif) |
311 | 315 | ||
312 | /* sanity */ | 316 | /* sanity */ |
313 | if (mbox == NULL || | 317 | if (mbox == NULL || |
314 | (mud = (mailbox_unix_data_t)mbox->data) == NULL) | 318 | (mud = (unix_data_t)mbox->data) == NULL) |
315 | return EINVAL; | 319 | return EINVAL; |
316 | 320 | ||
317 | /* save the timestamp and size */ | 321 | /* save the timestamp and size */ |
... | @@ -320,8 +324,8 @@ mailbox_unix_scan0 (mailbox_t mbox, size_t msgno, size_t *pcount, int do_notif) | ... | @@ -320,8 +324,8 @@ mailbox_unix_scan0 (mailbox_t mbox, size_t msgno, size_t *pcount, int do_notif) |
320 | return status; | 324 | return status; |
321 | 325 | ||
322 | /* grab the locks */ | 326 | /* grab the locks */ |
323 | mailbox_unix_ilock (mbox, MU_LOCKER_WRLOCK); | 327 | unix_ilock (mbox, MU_LOCKER_WRLOCK); |
324 | mailbox_unix_lock (mbox, MU_LOCKER_RDLOCK); | 328 | unix_lock (mbox, MU_LOCKER_RDLOCK); |
325 | 329 | ||
326 | /* seek to the starting point */ | 330 | /* seek to the starting point */ |
327 | if (mud->umessages && msgno > 0 && mud->messages_count > 0 | 331 | if (mud->umessages && msgno > 0 && mud->messages_count > 0 |
... | @@ -403,7 +407,7 @@ mailbox_unix_scan0 (mailbox_t mbox, size_t msgno, size_t *pcount, int do_notif) | ... | @@ -403,7 +407,7 @@ mailbox_unix_scan0 (mailbox_t mbox, size_t msgno, size_t *pcount, int do_notif) |
403 | 407 | ||
404 | /* every 50 mesgs update the lock, it should be every minute */ | 408 | /* every 50 mesgs update the lock, it should be every minute */ |
405 | if ((mud->messages_count % 50) == 0) | 409 | if ((mud->messages_count % 50) == 0) |
406 | mailbox_unix_touchlock (mbox); | 410 | unix_touchlock (mbox); |
407 | 411 | ||
408 | /* ping them every 1000 lines */ | 412 | /* ping them every 1000 lines */ |
409 | if (do_notif) | 413 | if (do_notif) |
... | @@ -419,8 +423,8 @@ mailbox_unix_scan0 (mailbox_t mbox, size_t msgno, size_t *pcount, int do_notif) | ... | @@ -419,8 +423,8 @@ mailbox_unix_scan0 (mailbox_t mbox, size_t msgno, size_t *pcount, int do_notif) |
419 | if (do_notif) | 423 | if (do_notif) |
420 | DISPATCH_ADD_MSG(mbox, mud); | 424 | DISPATCH_ADD_MSG(mbox, mud); |
421 | } | 425 | } |
422 | mailbox_unix_iunlock (mbox); | 426 | unix_iunlock (mbox); |
423 | mailbox_unix_unlock (mbox); | 427 | unix_unlock (mbox); |
424 | if (pcount) | 428 | if (pcount) |
425 | *pcount = mud->messages_count; | 429 | *pcount = mud->messages_count; |
426 | return status; | 430 | return status; | ... | ... |
... | @@ -68,7 +68,7 @@ message_destroy (message_t *pmsg, void *owner) | ... | @@ -68,7 +68,7 @@ message_destroy (message_t *pmsg, void *owner) |
68 | /* header */ | 68 | /* header */ |
69 | header_destroy (&(msg->header), owner); | 69 | header_destroy (&(msg->header), owner); |
70 | /* attribute */ | 70 | /* attribute */ |
71 | attribute_destroy (&(msg->attribute)); | 71 | attribute_destroy (&(msg->attribute), owner); |
72 | /* stream */ | 72 | /* stream */ |
73 | stream_destroy (&(msg->stream), owner); | 73 | stream_destroy (&(msg->stream), owner); |
74 | 74 | ||
... | @@ -325,7 +325,7 @@ message_get_attribute (message_t msg, attribute_t *pattribute) | ... | @@ -325,7 +325,7 @@ message_get_attribute (message_t msg, attribute_t *pattribute) |
325 | if (msg->attribute == NULL) | 325 | if (msg->attribute == NULL) |
326 | { | 326 | { |
327 | attribute_t attribute; | 327 | attribute_t attribute; |
328 | int status = attribute_create (&attribute); | 328 | int status = attribute_create (&attribute, msg); |
329 | if (status != 0) | 329 | if (status != 0) |
330 | return status; | 330 | return status; |
331 | msg->attribute = attribute; | 331 | msg->attribute = attribute; |
... | @@ -341,7 +341,7 @@ message_set_attribute (message_t msg, attribute_t attribute, void *owner) | ... | @@ -341,7 +341,7 @@ message_set_attribute (message_t msg, attribute_t attribute, void *owner) |
341 | return EINVAL; | 341 | return EINVAL; |
342 | if (msg->owner != owner) | 342 | if (msg->owner != owner) |
343 | return EACCES; | 343 | return EACCES; |
344 | attribute_destroy (&(msg->attribute)); | 344 | attribute_destroy (&(msg->attribute), owner); |
345 | msg->attribute = attribute; | 345 | msg->attribute = attribute; |
346 | return 0; | 346 | return 0; |
347 | } | 347 | } |
... | @@ -532,7 +532,11 @@ message_read (stream_t is, char *buf, size_t buflen, | ... | @@ -532,7 +532,11 @@ message_read (stream_t is, char *buf, size_t buflen, |
532 | header_size (msg->header, &hsize); | 532 | header_size (msg->header, &hsize); |
533 | body_size (msg->body, &bsize); | 533 | body_size (msg->body, &bsize); |
534 | 534 | ||
535 | if ((size_t)off <= hsize) | 535 | /* On some remote sever (POP) the size of the header and body is not known |
536 | until you start reading them. So by checking hsize == bsize == 0, we | ||
537 | This kludge of a way of detecting the anomalie and start by the | ||
538 | header. */ | ||
539 | if ((size_t)off <= hsize || (hsize == 0 && bsize == 0)) | ||
536 | { | 540 | { |
537 | header_get_stream (msg->header, &his); | 541 | header_get_stream (msg->header, &his); |
538 | stream_read (his, buf, buflen, off, &hread); | 542 | stream_read (his, buf, buflen, off, &hread); | ... | ... |
... | @@ -25,13 +25,12 @@ | ... | @@ -25,13 +25,12 @@ |
25 | #include <string.h> | 25 | #include <string.h> |
26 | #include <errno.h> | 26 | #include <errno.h> |
27 | 27 | ||
28 | /* | 28 | /* Builtin mailbox types. A circular list is use for the builtin. |
29 | Builtin mailbox types. | ||
30 | A circular list is use for the builtin. | ||
31 | Proper locking is not done when accessing the list. | 29 | Proper locking is not done when accessing the list. |
32 | FIXME: not thread-safe. */ | 30 | FIXME: not thread-safe. */ |
33 | 31 | ||
34 | static struct _registrar registrar [] = { | 32 | static struct _registrar registrar [] = |
33 | { | ||
35 | { NULL, NULL, 0, ®istrar[1] }, /* sentinel, head list */ | 34 | { NULL, NULL, 0, ®istrar[1] }, /* sentinel, head list */ |
36 | { &_url_file_registrar, &_mailbox_mbox_registrar, 0, ®istrar[2] }, | 35 | { &_url_file_registrar, &_mailbox_mbox_registrar, 0, ®istrar[2] }, |
37 | { &_url_mbox_registrar, &_mailbox_mbox_registrar, 0, ®istrar[3] }, | 36 | { &_url_mbox_registrar, &_mailbox_mbox_registrar, 0, ®istrar[3] }, | ... | ... |
-
Please register or sign in to post a comment