Mercurial > masqmail
comparison src/pop3_in.c @ 10:26e34ae9a3e3
changed indention and line wrapping to a more consistent style
author | meillo@marmaro.de |
---|---|
date | Mon, 27 Oct 2008 16:23:10 +0100 |
parents | 08114f7dcc23 |
children | f671821d8222 |
comparison
equal
deleted
inserted
replaced
9:31cc8a89cb74 | 10:26e34ae9a3e3 |
---|---|
2 * | 2 * |
3 * This program is free software; you can redistribute it and/or modify | 3 * This program is free software; you can redistribute it and/or modify |
4 * it under the terms of the GNU General Public License as published by | 4 * it under the terms of the GNU General Public License as published by |
5 * the Free Software Foundation; either version 2 of the License, or | 5 * the Free Software Foundation; either version 2 of the License, or |
6 * (at your option) any later version. | 6 * (at your option) any later version. |
7 * | 7 * |
8 * This program is distributed in the hope that it will be useful, | 8 * This program is distributed in the hope that it will be useful, |
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
11 * GNU General Public License for more details. | 11 * GNU General Public License for more details. |
12 * | 12 * |
34 #ifdef ENABLE_POP3 | 34 #ifdef ENABLE_POP3 |
35 | 35 |
36 /* experimental feature */ | 36 /* experimental feature */ |
37 #define DO_WRITE_UIDL_EARLY 1 | 37 #define DO_WRITE_UIDL_EARLY 1 |
38 | 38 |
39 static | 39 static gchar* |
40 gchar *MD5String (char *string) | 40 MD5String(char *string) |
41 { | 41 { |
42 MD5_CTX context; | 42 MD5_CTX context; |
43 unsigned char digest[16]; | 43 unsigned char digest[16]; |
44 char str_digest[33]; | 44 char str_digest[33]; |
45 int i; | 45 int i; |
46 | 46 |
47 #ifdef USE_LIB_CRYPTO | 47 #ifdef USE_LIB_CRYPTO |
48 MD5(string, strlen(string), digest); | 48 MD5(string, strlen(string), digest); |
49 #else | 49 #else |
50 MD5Init(&context); | 50 MD5Init(&context); |
51 MD5Update(&context, string, strlen(string)); | 51 MD5Update(&context, string, strlen(string)); |
52 MD5Final(digest, &context); | 52 MD5Final(digest, &context); |
53 #endif | 53 #endif |
54 for (i = 0; i < 16; i++) | 54 for (i = 0; i < 16; i++) |
55 sprintf(str_digest+2*i, "%02x", digest[i]); | 55 sprintf(str_digest + 2 * i, "%02x", digest[i]); |
56 | 56 |
57 return g_strdup(str_digest); | 57 return g_strdup(str_digest); |
58 } | 58 } |
59 | 59 |
60 static | 60 static pop3_base* |
61 pop3_base *create_pop3base(gint sock, guint flags) | 61 create_pop3base(gint sock, guint flags) |
62 { | 62 { |
63 gint dup_sock; | 63 gint dup_sock; |
64 | 64 |
65 pop3_base *popb = (pop3_base *)g_malloc(sizeof(pop3_base)); | 65 pop3_base *popb = (pop3_base *) g_malloc(sizeof(pop3_base)); |
66 if(popb){ | 66 if (popb) { |
67 memset(popb, 0, sizeof(pop3_base)); | 67 memset(popb, 0, sizeof(pop3_base)); |
68 | 68 |
69 popb->error = pop3_ok; | 69 popb->error = pop3_ok; |
70 | 70 |
71 popb->buffer = (gchar *)g_malloc(POP3_BUF_LEN); | 71 popb->buffer = (gchar *) g_malloc(POP3_BUF_LEN); |
72 | 72 |
73 dup_sock = dup(sock); | 73 dup_sock = dup(sock); |
74 popb->out = fdopen(sock, "w"); | 74 popb->out = fdopen(sock, "w"); |
75 popb->in = fdopen(dup_sock, "r"); | 75 popb->in = fdopen(dup_sock, "r"); |
76 | 76 |
77 popb->flags = flags; | 77 popb->flags = flags; |
78 } | 78 } |
79 return popb; | 79 return popb; |
80 } | 80 } |
81 | 81 |
82 static | 82 static void |
83 void pop3_printf(FILE *out, gchar *fmt, ...) | 83 pop3_printf(FILE * out, gchar * fmt, ...) |
84 { | 84 { |
85 va_list args; | 85 va_list args; |
86 va_start(args, fmt); | 86 va_start(args, fmt); |
87 | 87 |
88 DEBUG(4){ | 88 DEBUG(4) { |
89 gchar buf[256]; | 89 gchar buf[256]; |
90 va_list args_copy; | 90 va_list args_copy; |
91 | 91 |
92 va_copy(args_copy, args); | 92 va_copy(args_copy, args); |
93 vsnprintf(buf, 255, fmt, args_copy); | 93 vsnprintf(buf, 255, fmt, args_copy); |
94 va_end(args_copy); | 94 va_end(args_copy); |
95 | 95 |
96 debugf(">>>%s", buf); | 96 debugf(">>>%s", buf); |
97 } | 97 } |
98 | 98 |
99 vfprintf(out, fmt, args); fflush(out); | 99 vfprintf(out, fmt, args); |
100 | 100 fflush(out); |
101 va_end(args); | 101 |
102 } | 102 va_end(args); |
103 | 103 } |
104 static | 104 |
105 gboolean find_uid(pop3_base *popb, gchar *str) | 105 static gboolean |
106 { | 106 find_uid(pop3_base * popb, gchar * str) |
107 GList *node, *node_next; | 107 { |
108 | 108 GList *node, *node_next; |
109 for(node = popb->list_uid_old; node; node=node_next){ | 109 |
110 gchar *uid = (gchar *)(node->data); | 110 for (node = popb->list_uid_old; node; node = node_next) { |
111 node_next = node->next; | 111 gchar *uid = (gchar *) (node->data); |
112 if(strcmp(uid, str) == 0){ | 112 node_next = node->next; |
113 if (strcmp(uid, str) == 0) { | |
113 #if 1 | 114 #if 1 |
114 popb->list_uid_old = g_list_remove_link(popb->list_uid_old, node); | 115 popb->list_uid_old = g_list_remove_link(popb->list_uid_old, node); |
115 g_list_free_1(node); | 116 g_list_free_1(node); |
116 g_free(uid); | 117 g_free(uid); |
117 #endif | 118 #endif |
118 return TRUE; | 119 return TRUE; |
119 } | 120 } |
120 } | 121 } |
121 return FALSE; | 122 return FALSE; |
122 } | 123 } |
123 | 124 |
124 static | 125 static gboolean |
125 gboolean write_uidl(pop3_base *popb, gchar *user) | 126 write_uidl(pop3_base * popb, gchar * user) |
126 { | 127 { |
127 gboolean ok = FALSE; | 128 gboolean ok = FALSE; |
128 GList *node; | 129 GList *node; |
129 gchar *filename = g_strdup_printf("%s/popuidl/%s@%s", | 130 gchar *filename = g_strdup_printf("%s/popuidl/%s@%s", conf.spool_dir, user, popb->remote_host); |
130 conf.spool_dir, | 131 gchar *tmpname = g_strdup_printf("%s.tmp", filename); |
131 user, popb->remote_host); | 132 FILE *fptr = fopen(tmpname, "wt"); |
132 gchar *tmpname = g_strdup_printf("%s.tmp", filename); | 133 |
133 FILE *fptr = fopen(tmpname, "wt"); | 134 if (fptr) { |
134 | 135 foreach(popb->drop_list, node) { |
135 if(fptr){ | 136 msg_info *info = (msg_info *) (node->data); |
136 foreach(popb->drop_list, node){ | 137 if (info->is_fetched || info->is_in_uidl) |
137 msg_info *info = (msg_info *)(node->data); | 138 fprintf(fptr, "%s\n", info->uid); |
138 if(info->is_fetched || info->is_in_uidl) | 139 } |
139 fprintf(fptr, "%s\n", info->uid); | 140 fclose(fptr); |
140 } | 141 ok = (rename(tmpname, filename) != -1); |
141 fclose(fptr); | 142 } |
142 ok = (rename(tmpname, filename) != -1); | 143 |
143 } | 144 g_free(tmpname); |
144 | 145 g_free(filename); |
145 g_free(tmpname); | 146 return ok; |
146 g_free(filename); | 147 } |
147 return ok; | 148 |
148 } | 149 static gboolean |
149 | 150 read_uidl_fname(pop3_base * popb, gchar * filename) |
150 static | 151 { |
151 gboolean read_uidl_fname(pop3_base *popb, gchar *filename) | 152 gboolean ok = FALSE; |
152 { | 153 FILE *fptr = fopen(filename, "rt"); |
153 gboolean ok = FALSE; | 154 gchar buf[256]; |
154 FILE *fptr = fopen(filename, "rt"); | 155 |
155 gchar buf[256]; | 156 if (fptr) { |
156 | 157 popb->list_uid_old = NULL; |
157 if(fptr){ | 158 while (fgets(buf, 255, fptr)) { |
158 popb->list_uid_old = NULL; | 159 if (buf[strlen(buf) - 1] == '\n') { |
159 while(fgets(buf, 255, fptr)){ | 160 g_strchomp(buf); |
160 if(buf[strlen(buf)-1] == '\n'){ | 161 popb->list_uid_old = g_list_append(popb->list_uid_old, g_strdup(buf)); |
161 g_strchomp(buf); | 162 } else { |
162 popb->list_uid_old = | 163 logwrite(LOG_ALERT, "broken uid: %s\n", buf); |
163 g_list_append(popb->list_uid_old, g_strdup(buf)); | 164 break; |
164 }else{ | 165 } |
165 logwrite(LOG_ALERT, "broken uid: %s\n", buf); | 166 } |
166 break; | 167 fclose(fptr); |
167 } | 168 ok = TRUE; |
168 } | 169 } else |
169 fclose(fptr); | 170 logwrite(LOG_ALERT, "opening of %s failed: %s", filename, strerror(errno)); |
170 ok = TRUE; | 171 return ok; |
171 }else | 172 } |
172 logwrite(LOG_ALERT, "opening of %s failed: %s", filename, strerror(errno)); | 173 |
173 return ok; | 174 static gboolean |
174 } | 175 read_uidl(pop3_base * popb, gchar * user) |
175 | 176 { |
176 static | 177 gboolean ok = FALSE; |
177 gboolean read_uidl(pop3_base *popb, gchar *user) | 178 struct stat statbuf; |
178 { | 179 gchar *filename = g_strdup_printf("%s/popuidl/%s@%s", conf.spool_dir, user, popb->remote_host); |
179 gboolean ok = FALSE; | 180 |
180 struct stat statbuf; | 181 if (stat(filename, &statbuf) == 0) { |
181 gchar *filename = g_strdup_printf("%s/popuidl/%s@%s", | 182 ok = read_uidl_fname(popb, filename); |
182 conf.spool_dir, | 183 if (ok) { |
183 user, popb->remote_host); | 184 GList *drop_node; |
184 | 185 foreach(popb->drop_list, drop_node) { |
185 if(stat(filename, &statbuf) == 0){ | 186 msg_info *info = (msg_info *) (drop_node->data); |
186 ok = read_uidl_fname(popb, filename); | 187 if (find_uid(popb, info->uid)) { |
187 if(ok){ | 188 DEBUG(5) debugf("msg with uid '%s' already known\n", info->uid); |
188 GList *drop_node; | 189 info->is_in_uidl = TRUE; |
189 foreach(popb->drop_list, drop_node){ | 190 popb->uidl_known_cnt++; |
190 msg_info *info = (msg_info *)(drop_node->data); | 191 } else |
191 if(find_uid(popb, info->uid)){ | 192 DEBUG(5) debugf("msg with uid '%s' not known\n", info->uid); |
192 DEBUG(5) debugf("msg with uid '%s' already known\n", info->uid); | 193 } |
193 info->is_in_uidl = TRUE; | 194 } |
194 popb->uidl_known_cnt++; | 195 } else { |
195 }else | 196 logwrite(LOG_DEBUG, "no uidl file '%s' found\n", filename); |
196 DEBUG(5) debugf("msg with uid '%s' not known\n", info->uid); | 197 ok = TRUE; |
197 } | 198 } |
198 } | 199 |
199 }else{ | 200 g_free(filename); |
200 logwrite(LOG_DEBUG, "no uidl file '%s' found\n", filename); | 201 return ok; /* return code is irrelevant, do not check... */ |
201 ok = TRUE; | 202 } |
202 } | 203 |
203 | 204 static gboolean |
204 g_free(filename); | 205 read_response(pop3_base * popb, int timeout) |
205 return ok; /* return code is irrelevant, do not check... */ | 206 { |
206 } | 207 gint len; |
207 | 208 |
208 static | 209 len = read_sockline(popb->in, popb->buffer, POP3_BUF_LEN, timeout, READSOCKL_CHUG); |
209 gboolean read_response(pop3_base *popb, int timeout) | 210 |
210 { | 211 if (len == -3) { |
211 gint len; | 212 popb->error = pop3_timeout; |
212 | 213 return FALSE; |
213 len = read_sockline(popb->in, popb->buffer, POP3_BUF_LEN, timeout, READSOCKL_CHUG); | 214 } else if (len == -2) { |
214 | 215 popb->error = pop3_syntax; |
215 if(len == -3){ | 216 return FALSE; |
216 popb->error = pop3_timeout; | 217 } else if (len == -1) { |
217 return FALSE; | 218 popb->error = pop3_eof; |
218 } | 219 return FALSE; |
219 else if(len == -2){ | 220 } |
220 popb->error = pop3_syntax; | 221 |
221 return FALSE; | |
222 } | |
223 else if(len == -1){ | |
224 popb->error = pop3_eof; | |
225 return FALSE; | |
226 } | |
227 | |
228 return TRUE; | |
229 } | |
230 | |
231 static | |
232 gboolean check_response(pop3_base *popb) | |
233 { | |
234 char c = popb->buffer[0]; | |
235 | |
236 if(c == '+'){ | |
237 popb->error = pop3_ok; | |
238 return TRUE; | |
239 }else if(c == '-') | |
240 popb->error = pop3_fail; | |
241 else | |
242 popb->error = pop3_syntax; | |
243 return FALSE; | |
244 } | |
245 | |
246 static | |
247 gboolean strtoi(gchar *p, gchar **pend, gint *val) | |
248 { | |
249 gchar buf[12]; | |
250 gint i = 0; | |
251 | |
252 while(*p && isspace(*p)) p++; | |
253 if(*p){ | |
254 while((i < 11) && isdigit(*p)) | |
255 buf[i++] = *(p++); | |
256 buf[i] = 0; | |
257 *val = atoi(buf); | |
258 *pend = p; | |
259 return TRUE; | |
260 } | |
261 return FALSE; | |
262 } | |
263 | |
264 static | |
265 gboolean check_response_int_int(pop3_base *popb, gint *arg0, gint *arg1) | |
266 { | |
267 if(check_response(popb)){ | |
268 gchar *p = &(popb->buffer[3]); | |
269 gchar *pe; | |
270 | |
271 if(strtoi(p, &pe, arg0)){ | |
272 DEBUG(5) debugf("arg0 = %d\n", *arg0); | |
273 p = pe; | |
274 if(strtoi(p, &pe, arg1)) | |
275 DEBUG(5) debugf("arg1 = %d\n", *arg1); | |
276 return TRUE; | 222 return TRUE; |
277 } | 223 } |
278 popb->error = pop3_syntax; | 224 |
279 } | 225 static gboolean |
280 return FALSE; | 226 check_response(pop3_base * popb) |
281 } | 227 { |
282 | 228 char c = popb->buffer[0]; |
283 static | 229 |
284 gboolean get_drop_listing(pop3_base *popb) | 230 if (c == '+') { |
285 { | 231 popb->error = pop3_ok; |
286 gchar buf[64]; | 232 return TRUE; |
287 | 233 } else if (c == '-') |
288 DEBUG(5) debugf("get_drop_listing() entered\n"); | 234 popb->error = pop3_fail; |
289 | 235 else |
290 while(1){ | 236 popb->error = pop3_syntax; |
291 gint len = read_sockline(popb->in, buf, 64, POP3_CMD_TIMEOUT, READSOCKL_CHUG); | 237 return FALSE; |
292 if(len > 0){ | 238 } |
293 if(buf[0] == '.') | 239 |
240 static gboolean | |
241 strtoi(gchar * p, gchar ** pend, gint * val) | |
242 { | |
243 gchar buf[12]; | |
244 gint i = 0; | |
245 | |
246 while (*p && isspace(*p)) | |
247 p++; | |
248 if (*p) { | |
249 while ((i < 11) && isdigit(*p)) | |
250 buf[i++] = *(p++); | |
251 buf[i] = 0; | |
252 *val = atoi(buf); | |
253 *pend = p; | |
254 return TRUE; | |
255 } | |
256 return FALSE; | |
257 } | |
258 | |
259 static gboolean | |
260 check_response_int_int(pop3_base * popb, gint * arg0, gint * arg1) | |
261 { | |
262 if (check_response(popb)) { | |
263 gchar *p = &(popb->buffer[3]); | |
264 gchar *pe; | |
265 | |
266 if (strtoi(p, &pe, arg0)) { | |
267 DEBUG(5) debugf("arg0 = %d\n", *arg0); | |
268 p = pe; | |
269 if (strtoi(p, &pe, arg1)) | |
270 DEBUG(5) debugf("arg1 = %d\n", *arg1); | |
271 return TRUE; | |
272 } | |
273 popb->error = pop3_syntax; | |
274 } | |
275 return FALSE; | |
276 } | |
277 | |
278 static gboolean | |
279 get_drop_listing(pop3_base * popb) | |
280 { | |
281 gchar buf[64]; | |
282 | |
283 DEBUG(5) debugf("get_drop_listing() entered\n"); | |
284 | |
285 while (1) { | |
286 gint len = read_sockline(popb->in, buf, 64, POP3_CMD_TIMEOUT, READSOCKL_CHUG); | |
287 if (len > 0) { | |
288 if (buf[0] == '.') | |
289 return TRUE; | |
290 else { | |
291 gint number, msg_size; | |
292 gchar *p = buf, *pe; | |
293 if (strtoi(p, &pe, &number)) { | |
294 p = pe; | |
295 if (strtoi(p, &pe, &msg_size)) { | |
296 msg_info *info = g_malloc(sizeof(msg_info)); | |
297 info->number = number; | |
298 info->size = msg_size; | |
299 | |
300 DEBUG(5) debugf ("get_drop_listing(), number = %d, msg_size = %d\n", number, msg_size); | |
301 | |
302 info->uid = NULL; | |
303 info->is_fetched = FALSE; | |
304 info->is_in_uidl = FALSE; | |
305 popb->drop_list = g_list_append(popb->drop_list, info); | |
306 } else { | |
307 popb->error = pop3_syntax; | |
308 break; | |
309 } | |
310 } else { | |
311 popb->error = pop3_syntax; | |
312 break; | |
313 } | |
314 } | |
315 } else { | |
316 popb->error = (len == -1) ? pop3_eof : pop3_timeout; | |
317 return FALSE; | |
318 } | |
319 } | |
320 return FALSE; | |
321 } | |
322 | |
323 static gboolean | |
324 get_uid_listing(pop3_base * popb) | |
325 { | |
326 gchar buf[64]; | |
327 | |
328 while (1) { | |
329 gint len = read_sockline(popb->in, buf, 64, POP3_CMD_TIMEOUT, READSOCKL_CHUG); | |
330 if (len > 0) { | |
331 if (buf[0] == '.') | |
332 return TRUE; | |
333 else { | |
334 gint number; | |
335 gchar *p = buf, *pe; | |
336 if (strtoi(p, &pe, &number)) { | |
337 msg_info *info = NULL; | |
338 GList *drop_node; | |
339 | |
340 p = pe; | |
341 while (*p && isspace(*p)) | |
342 p++; | |
343 | |
344 foreach(popb->drop_list, drop_node) { | |
345 msg_info *curr_info = (msg_info *) (drop_node->data); | |
346 if (curr_info->number == number) { | |
347 info = curr_info; | |
348 break; | |
349 } | |
350 } | |
351 if (info) { | |
352 info->uid = g_strdup(p); | |
353 g_strchomp(info->uid); | |
354 } | |
355 | |
356 } else { | |
357 popb->error = pop3_syntax; | |
358 break; | |
359 } | |
360 } | |
361 } | |
362 } | |
363 return FALSE; | |
364 } | |
365 | |
366 static gboolean | |
367 check_init_response(pop3_base * popb) | |
368 { | |
369 if (check_response(popb)) { | |
370 gchar buf[256]; | |
371 gchar *p = popb->buffer; | |
372 gint i = 0; | |
373 if (*p) { | |
374 while (*p && (*p != '<')) | |
375 p++; | |
376 while (*p && (*p != '>') && (i < 254)) | |
377 buf[i++] = *(p++); | |
378 buf[i++] = '>'; | |
379 buf[i] = 0; | |
380 | |
381 popb->timestamp = g_strdup(buf); | |
382 | |
383 return TRUE; | |
384 } | |
385 } | |
386 return FALSE; | |
387 } | |
388 | |
389 void | |
390 pop3_in_close(pop3_base * popb) | |
391 { | |
392 GList *node; | |
393 | |
394 fclose(popb->in); | |
395 fclose(popb->out); | |
396 | |
397 close(popb->sock); | |
398 | |
399 foreach(popb->list_uid_old, node) { | |
400 gchar *uid = (gchar *) (node->data); | |
401 g_free(uid); | |
402 } | |
403 g_list_free(popb->list_uid_old); | |
404 | |
405 foreach(popb->drop_list, node) { | |
406 msg_info *info = (msg_info *) (node->data); | |
407 if (info->uid) | |
408 g_free(info->uid); | |
409 g_free(info); | |
410 } | |
411 g_list_free(popb->drop_list); | |
412 | |
413 if (popb->buffer) | |
414 g_free(popb->buffer); | |
415 if (popb->timestamp) | |
416 g_free(popb->timestamp); | |
417 } | |
418 | |
419 pop3_base* | |
420 pop3_in_open(gchar * host, gint port, GList * resolve_list, guint flags) | |
421 { | |
422 pop3_base *popb; | |
423 gint sock; | |
424 mxip_addr *addr; | |
425 | |
426 DEBUG(5) debugf("pop3_in_open entered, host = %s\n", host); | |
427 | |
428 if ((addr = connect_resolvelist(&sock, host, port, resolve_list))) { | |
429 /* create structure to hold status data: */ | |
430 popb = create_pop3base(sock, flags); | |
431 popb->remote_host = addr->name; | |
432 | |
433 DEBUG(5) { | |
434 struct sockaddr_in name; | |
435 int len; | |
436 getsockname(sock, (struct sockaddr *) (&name), &len); | |
437 debugf("socket: name.sin_addr = %s\n", inet_ntoa(name.sin_addr)); | |
438 } | |
439 return popb; | |
440 } | |
441 return NULL; | |
442 } | |
443 | |
444 pop3_base* | |
445 pop3_in_open_child(gchar * cmd, guint flags) | |
446 { | |
447 pop3_base *popb; | |
448 gint sock; | |
449 | |
450 DEBUG(5) debugf("pop3_in_open_child entered, cmd = %s\n", cmd); | |
451 | |
452 sock = child(cmd); | |
453 | |
454 if (sock > 0) { | |
455 | |
456 popb = create_pop3base(sock, flags); | |
457 popb->remote_host = NULL; | |
458 | |
459 return popb; | |
460 } | |
461 logwrite(LOG_ALERT, "child failed (sock = %d): %s\n", sock, strerror(errno)); | |
462 | |
463 return NULL; | |
464 } | |
465 | |
466 gboolean | |
467 pop3_in_init(pop3_base * popb) | |
468 { | |
469 gboolean ok; | |
470 | |
471 if ((ok = read_response(popb, POP3_INITIAL_TIMEOUT))) { | |
472 ok = check_init_response(popb); | |
473 } | |
474 if (!ok) | |
475 /* pop3_in_log_failure(popb, NULL); */ | |
476 logwrite(LOG_ALERT, "pop3 failed\n"); | |
477 return ok; | |
478 } | |
479 | |
480 gboolean | |
481 pop3_in_login(pop3_base * popb, gchar * user, gchar * pass) | |
482 { | |
483 if (popb->flags & POP3_FLAG_APOP) { | |
484 | |
485 gchar *string = g_strdup_printf("%s%s", popb->timestamp, pass); | |
486 gchar *digest = MD5String(string); | |
487 pop3_printf(popb->out, "APOP %s %s\r\n", user, digest); | |
488 g_free(string); | |
489 g_free(digest); | |
490 if (read_response(popb, POP3_CMD_TIMEOUT)) { | |
491 if (check_response(popb)) | |
492 return TRUE; | |
493 else | |
494 popb->error = pop3_login_failure; | |
495 } | |
496 | |
497 } else { | |
498 | |
499 pop3_printf(popb->out, "USER %s\r\n", user); | |
500 if (read_response(popb, POP3_CMD_TIMEOUT)) { | |
501 if (check_response(popb)) { | |
502 pop3_printf(popb->out, "PASS %s\r\n", pass); | |
503 if (read_response(popb, POP3_CMD_TIMEOUT)) { | |
504 if (check_response(popb)) | |
505 return TRUE; | |
506 else | |
507 popb->error = pop3_login_failure; | |
508 } | |
509 } else { | |
510 popb->error = pop3_login_failure; | |
511 } | |
512 } | |
513 } | |
514 return FALSE; | |
515 } | |
516 | |
517 gboolean | |
518 pop3_in_stat(pop3_base * popb) | |
519 { | |
520 pop3_printf(popb->out, "STAT\r\n"); | |
521 if (read_response(popb, POP3_CMD_TIMEOUT)) { | |
522 gint msg_cnt, mbox_size; | |
523 if (check_response_int_int(popb, &msg_cnt, &mbox_size)) { | |
524 popb->msg_cnt = msg_cnt; | |
525 popb->mbox_size = mbox_size; | |
526 | |
527 return TRUE; | |
528 } | |
529 } | |
530 return FALSE; | |
531 } | |
532 | |
533 gboolean | |
534 pop3_in_list(pop3_base * popb) | |
535 { | |
536 pop3_printf(popb->out, "LIST\r\n"); | |
537 if (read_response(popb, POP3_CMD_TIMEOUT)) { | |
538 if (get_drop_listing(popb)) { | |
539 return TRUE; | |
540 } | |
541 } | |
542 return FALSE; | |
543 } | |
544 | |
545 gboolean | |
546 pop3_in_dele(pop3_base * popb, gint number) | |
547 { | |
548 pop3_printf(popb->out, "DELE %d\r\n", number); | |
549 if (read_response(popb, POP3_CMD_TIMEOUT)) { | |
550 return TRUE; | |
551 } | |
552 return FALSE; | |
553 } | |
554 | |
555 message* | |
556 pop3_in_retr(pop3_base * popb, gint number, address * rcpt) | |
557 { | |
558 accept_error err; | |
559 | |
560 pop3_printf(popb->out, "RETR %d\r\n", number); | |
561 if (read_response(popb, POP3_CMD_TIMEOUT)) { | |
562 message *msg = create_message(); | |
563 msg->received_host = popb->remote_host; | |
564 msg->received_prot = (popb->flags & POP3_FLAG_APOP) ? PROT_APOP : PROT_POP3; | |
565 msg->transfer_id = (popb->next_id)++; | |
566 msg->rcpt_list = g_list_append(NULL, copy_address(rcpt)); | |
567 | |
568 if ((err = accept_message(popb->in, msg, ACC_MAIL_FROM_HEAD | |
569 | (conf.do_save_envelope_to ? ACC_SAVE_ENVELOPE_TO : 0))) | |
570 == AERR_OK) | |
571 return msg; | |
572 | |
573 destroy_message(msg); | |
574 } | |
575 return NULL; | |
576 } | |
577 | |
578 gboolean | |
579 pop3_in_uidl(pop3_base * popb) | |
580 { | |
581 pop3_printf(popb->out, "UIDL\r\n"); | |
582 if (read_response(popb, POP3_CMD_TIMEOUT)) { | |
583 if (get_uid_listing(popb)) { | |
584 return TRUE; | |
585 } | |
586 } | |
587 return FALSE; | |
588 } | |
589 | |
590 gboolean | |
591 pop3_in_quit(pop3_base * popb) | |
592 { | |
593 pop3_printf(popb->out, "QUIT\r\n"); | |
594 | |
595 DEBUG(4) debugf("QUIT\n"); | |
596 | |
597 signal(SIGALRM, SIG_DFL); | |
598 | |
294 return TRUE; | 599 return TRUE; |
295 else{ | |
296 gint number, msg_size; | |
297 gchar *p = buf, *pe; | |
298 if(strtoi(p, &pe, &number)){ | |
299 p = pe; | |
300 if(strtoi(p, &pe, &msg_size)){ | |
301 msg_info *info = g_malloc(sizeof(msg_info)); | |
302 info->number = number; | |
303 info->size = msg_size; | |
304 | |
305 DEBUG(5) debugf("get_drop_listing(), number = %d, msg_size = %d\n", number, msg_size); | |
306 | |
307 info->uid = NULL; | |
308 info->is_fetched = FALSE; | |
309 info->is_in_uidl = FALSE; | |
310 popb->drop_list = g_list_append(popb->drop_list, info); | |
311 }else{ | |
312 popb->error = pop3_syntax; | |
313 break; | |
314 } | |
315 }else{ | |
316 popb->error = pop3_syntax; | |
317 break; | |
318 } | |
319 } | |
320 }else{ | |
321 popb->error = (len == -1) ? pop3_eof : pop3_timeout; | |
322 return FALSE; | |
323 } | |
324 } | |
325 return FALSE; | |
326 } | |
327 | |
328 static | |
329 gboolean get_uid_listing(pop3_base *popb) | |
330 { | |
331 gchar buf[64]; | |
332 | |
333 while(1){ | |
334 gint len = read_sockline(popb->in, buf, 64, POP3_CMD_TIMEOUT, READSOCKL_CHUG); | |
335 if(len > 0){ | |
336 if(buf[0] == '.') | |
337 return TRUE; | |
338 else{ | |
339 gint number; | |
340 gchar *p = buf, *pe; | |
341 if(strtoi(p, &pe, &number)){ | |
342 msg_info *info = NULL; | |
343 GList *drop_node; | |
344 | |
345 p = pe; | |
346 while(*p && isspace(*p)) p++; | |
347 | |
348 foreach(popb->drop_list, drop_node){ | |
349 msg_info *curr_info = (msg_info *)(drop_node->data); | |
350 if(curr_info->number == number){ | |
351 info = curr_info; | |
352 break; | |
353 } | |
354 } | |
355 if(info){ | |
356 info->uid = g_strdup(p); | |
357 g_strchomp(info->uid); | |
358 } | |
359 | |
360 }else{ | |
361 popb->error = pop3_syntax; | |
362 break; | |
363 } | |
364 } | |
365 } | |
366 } | |
367 return FALSE; | |
368 } | |
369 | |
370 static | |
371 gboolean check_init_response(pop3_base *popb) | |
372 { | |
373 if(check_response(popb)){ | |
374 gchar buf[256]; | |
375 gchar *p = popb->buffer; | |
376 gint i = 0; | |
377 if(*p){ | |
378 while(*p && (*p != '<')) p++; | |
379 while(*p && (*p != '>') && (i < 254)) | |
380 buf[i++] = *(p++); | |
381 buf[i++] = '>'; | |
382 buf[i] = 0; | |
383 | |
384 popb->timestamp = g_strdup(buf); | |
385 | |
386 return TRUE; | |
387 } | |
388 } | |
389 return FALSE; | |
390 } | |
391 | |
392 void pop3_in_close(pop3_base *popb) | |
393 { | |
394 GList *node; | |
395 | |
396 fclose(popb->in); | |
397 fclose(popb->out); | |
398 | |
399 close(popb->sock); | |
400 | |
401 foreach(popb->list_uid_old, node){ | |
402 gchar *uid = (gchar *)(node->data); | |
403 g_free(uid); | |
404 } | |
405 g_list_free(popb->list_uid_old); | |
406 | |
407 foreach(popb->drop_list, node){ | |
408 msg_info *info = (msg_info *)(node->data); | |
409 if(info->uid) g_free(info->uid); | |
410 g_free(info); | |
411 } | |
412 g_list_free(popb->drop_list); | |
413 | |
414 if(popb->buffer) g_free(popb->buffer); | |
415 if(popb->timestamp) g_free(popb->timestamp); | |
416 } | |
417 | |
418 pop3_base *pop3_in_open(gchar *host, gint port, GList *resolve_list, guint flags) | |
419 { | |
420 pop3_base *popb; | |
421 gint sock; | |
422 mxip_addr *addr; | |
423 | |
424 DEBUG(5) debugf("pop3_in_open entered, host = %s\n", host); | |
425 | |
426 if((addr = connect_resolvelist(&sock, host, port, resolve_list))){ | |
427 /* create structure to hold status data: */ | |
428 popb = create_pop3base(sock, flags); | |
429 popb->remote_host = addr->name; | |
430 | |
431 DEBUG(5){ | |
432 struct sockaddr_in name; | |
433 int len; | |
434 getsockname(sock, (struct sockaddr *)(&name), &len); | |
435 debugf("socket: name.sin_addr = %s\n", inet_ntoa(name.sin_addr)); | |
436 } | |
437 return popb; | |
438 } | |
439 return NULL; | |
440 } | |
441 | |
442 pop3_base *pop3_in_open_child(gchar *cmd, guint flags) | |
443 { | |
444 pop3_base *popb; | |
445 gint sock; | |
446 | |
447 DEBUG(5) debugf("pop3_in_open_child entered, cmd = %s\n", cmd); | |
448 | |
449 sock = child(cmd); | |
450 | |
451 if(sock > 0){ | |
452 | |
453 popb = create_pop3base(sock, flags); | |
454 popb->remote_host = NULL; | |
455 | |
456 return popb; | |
457 } | |
458 logwrite(LOG_ALERT, "child failed (sock = %d): %s\n", sock, strerror(errno)); | |
459 | |
460 return NULL; | |
461 } | |
462 | |
463 gboolean pop3_in_init(pop3_base *popb) | |
464 { | |
465 gboolean ok; | |
466 | |
467 if((ok = read_response(popb, POP3_INITIAL_TIMEOUT))){ | |
468 ok = check_init_response(popb); | |
469 } | |
470 if(!ok) | |
471 /* pop3_in_log_failure(popb, NULL);*/ | |
472 logwrite(LOG_ALERT, "pop3 failed\n"); | |
473 return ok; | |
474 } | |
475 | |
476 gboolean pop3_in_login(pop3_base *popb, gchar *user, gchar *pass) | |
477 { | |
478 if(popb->flags & POP3_FLAG_APOP){ | |
479 | |
480 gchar *string = g_strdup_printf("%s%s", popb->timestamp, pass); | |
481 gchar *digest = MD5String(string); | |
482 pop3_printf(popb->out, "APOP %s %s\r\n", user, digest); | |
483 g_free(string); | |
484 g_free(digest); | |
485 if(read_response(popb, POP3_CMD_TIMEOUT)){ | |
486 if(check_response(popb)) | |
487 return TRUE; | |
488 else | |
489 popb->error = pop3_login_failure; | |
490 } | |
491 | |
492 }else{ | |
493 | |
494 pop3_printf(popb->out, "USER %s\r\n", user); | |
495 if(read_response(popb, POP3_CMD_TIMEOUT)){ | |
496 if(check_response(popb)){ | |
497 pop3_printf(popb->out, "PASS %s\r\n", pass); | |
498 if(read_response(popb, POP3_CMD_TIMEOUT)){ | |
499 if(check_response(popb)) | |
500 return TRUE; | |
501 else | |
502 popb->error = pop3_login_failure; | |
503 } | |
504 }else{ | |
505 popb->error = pop3_login_failure; | |
506 } | |
507 } | |
508 } | |
509 return FALSE; | |
510 } | |
511 | |
512 gboolean pop3_in_stat(pop3_base *popb) | |
513 { | |
514 pop3_printf(popb->out, "STAT\r\n"); | |
515 if(read_response(popb, POP3_CMD_TIMEOUT)){ | |
516 gint msg_cnt, mbox_size; | |
517 if(check_response_int_int(popb, &msg_cnt, &mbox_size)){ | |
518 popb->msg_cnt = msg_cnt; | |
519 popb->mbox_size = mbox_size; | |
520 | |
521 return TRUE; | |
522 } | |
523 } | |
524 return FALSE; | |
525 } | |
526 | |
527 gboolean pop3_in_list(pop3_base *popb) | |
528 { | |
529 pop3_printf(popb->out, "LIST\r\n"); | |
530 if(read_response(popb, POP3_CMD_TIMEOUT)){ | |
531 if(get_drop_listing(popb)){ | |
532 return TRUE; | |
533 } | |
534 } | |
535 return FALSE; | |
536 } | |
537 | |
538 gboolean pop3_in_dele(pop3_base *popb, gint number) | |
539 { | |
540 pop3_printf(popb->out, "DELE %d\r\n", number); | |
541 if(read_response(popb, POP3_CMD_TIMEOUT)){ | |
542 return TRUE; | |
543 } | |
544 return FALSE; | |
545 } | |
546 | |
547 message *pop3_in_retr(pop3_base *popb, gint number, address *rcpt) | |
548 { | |
549 accept_error err; | |
550 | |
551 pop3_printf(popb->out, "RETR %d\r\n", number); | |
552 if(read_response(popb, POP3_CMD_TIMEOUT)){ | |
553 message *msg = create_message(); | |
554 msg->received_host = popb->remote_host; | |
555 msg->received_prot = (popb->flags & POP3_FLAG_APOP) ? PROT_APOP : PROT_POP3; | |
556 msg->transfer_id = (popb->next_id)++; | |
557 msg->rcpt_list = g_list_append(NULL, copy_address(rcpt)); | |
558 | |
559 if((err = accept_message(popb->in, msg, | |
560 ACC_MAIL_FROM_HEAD|(conf.do_save_envelope_to ? ACC_SAVE_ENVELOPE_TO : 0))) | |
561 == AERR_OK) | |
562 return msg; | |
563 | |
564 destroy_message(msg); | |
565 } | |
566 return NULL; | |
567 } | |
568 | |
569 gboolean pop3_in_uidl(pop3_base *popb) | |
570 { | |
571 pop3_printf(popb->out, "UIDL\r\n"); | |
572 if(read_response(popb, POP3_CMD_TIMEOUT)){ | |
573 if(get_uid_listing(popb)){ | |
574 return TRUE; | |
575 } | |
576 } | |
577 return FALSE; | |
578 } | |
579 | |
580 gboolean pop3_in_quit(pop3_base *popb) | |
581 { | |
582 pop3_printf(popb->out, "QUIT\r\n"); | |
583 | |
584 DEBUG(4) debugf("QUIT\n"); | |
585 | |
586 signal(SIGALRM, SIG_DFL); | |
587 | |
588 return TRUE; | |
589 } | 600 } |
590 | 601 |
591 /* Send a DELE command for each message in (the old) uid listing. | 602 /* Send a DELE command for each message in (the old) uid listing. |
592 This is to prevent mail from to be kept on server, if a previous | 603 This is to prevent mail from to be kept on server, if a previous |
593 transaction was interupted. */ | 604 transaction was interupted. */ |
594 gboolean pop3_in_uidl_dele(pop3_base *popb) | 605 gboolean |
595 { | 606 pop3_in_uidl_dele(pop3_base * popb) |
596 GList *drop_node; | 607 { |
597 | 608 GList *drop_node; |
598 foreach(popb->drop_list, drop_node){ | 609 |
599 msg_info *info = (msg_info *)(drop_node->data); | 610 foreach(popb->drop_list, drop_node) { |
600 /* if(find_uid(popb, info->uid)){*/ | 611 msg_info *info = (msg_info *) (drop_node->data); |
601 if(info->is_in_uidl){ | 612 /* if(find_uid(popb, info->uid)){ */ |
602 if(!pop3_in_dele(popb, info->number)) | 613 if (info->is_in_uidl) { |
603 return FALSE; | 614 if (!pop3_in_dele(popb, info->number)) |
604 /* TODO: it probably makes sense to also | 615 return FALSE; |
605 delete this uid from the listing */ | 616 /* TODO: it probably makes sense to also delete this uid from the listing */ |
606 } | 617 } |
607 } | 618 } |
608 return TRUE; | 619 return TRUE; |
609 } | 620 } |
610 | 621 |
611 gboolean pop3_get(pop3_base *popb, | 622 gboolean |
612 gchar *user, gchar *pass, address *rcpt, address *return_path, | 623 pop3_get(pop3_base * popb, gchar * user, gchar * pass, address * rcpt, address * return_path, gint max_count, gint max_size, gboolean max_size_delete) |
613 gint max_count, gint max_size, gboolean max_size_delete) | 624 { |
614 { | 625 gboolean ok = FALSE; |
615 gboolean ok = FALSE; | 626 gint num_children = 0; |
616 gint num_children = 0; | 627 |
617 | 628 DEBUG(5) debugf("rcpt = %s@%s\n", rcpt->local_part, rcpt->domain); |
618 DEBUG(5) debugf("rcpt = %s@%s\n", rcpt->local_part, rcpt->domain); | 629 |
619 | 630 signal(SIGCHLD, SIG_DFL); |
620 signal(SIGCHLD, SIG_DFL); | 631 |
621 | 632 if (pop3_in_init(popb)) { |
622 if(pop3_in_init(popb)){ | 633 if (pop3_in_login(popb, user, pass)) { |
623 if(pop3_in_login(popb, user, pass)){ | 634 if (pop3_in_stat(popb)) { |
624 if(pop3_in_stat(popb)){ | 635 if (popb->msg_cnt > 0) { |
625 if(popb->msg_cnt > 0){ | 636 |
626 | 637 logwrite(LOG_NOTICE | LOG_VERBOSE, "%d message(s) for user %s at %s\n", popb->msg_cnt, user, popb->remote_host); |
627 logwrite(LOG_NOTICE|LOG_VERBOSE, "%d message(s) for user %s at %s\n", | 638 |
628 popb->msg_cnt, user, popb->remote_host); | 639 if (pop3_in_list(popb)) { |
629 | 640 gboolean do_get = !(popb->flags & POP3_FLAG_UIDL); |
630 if(pop3_in_list(popb)){ | 641 if (!do_get) |
631 gboolean do_get = !(popb->flags & POP3_FLAG_UIDL); | 642 do_get = pop3_in_uidl(popb); |
632 if(!do_get) do_get = pop3_in_uidl(popb); | 643 if (do_get) { |
633 if(do_get){ | 644 gint count = 0; |
634 gint count = 0; | 645 GList *drop_node; |
635 GList *drop_node; | 646 |
636 | 647 if (popb->flags & POP3_FLAG_UIDL) { |
637 if(popb->flags & POP3_FLAG_UIDL){ | 648 read_uidl(popb, user); |
638 read_uidl(popb, user); | 649 logwrite(LOG_VERBOSE | LOG_NOTICE, "%d message(s) already in uidl.\n", popb->uidl_known_cnt); |
639 logwrite(LOG_VERBOSE|LOG_NOTICE, "%d message(s) already in uidl.\n", | 650 } |
640 popb->uidl_known_cnt); | 651 if ((popb->flags & POP3_FLAG_UIDL) && (popb->flags & POP3_FLAG_UIDL_DELE)) |
641 } | 652 pop3_in_uidl_dele(popb); |
642 if((popb->flags & POP3_FLAG_UIDL) && (popb->flags & POP3_FLAG_UIDL_DELE)) | 653 |
643 pop3_in_uidl_dele(popb); | 654 foreach(popb->drop_list, drop_node) { |
644 | 655 |
645 foreach(popb->drop_list, drop_node){ | 656 msg_info *info = (msg_info *) (drop_node->data); |
646 | 657 gboolean do_get_this = !(popb->flags & POP3_FLAG_UIDL); |
647 msg_info *info = (msg_info *)(drop_node->data); | 658 /* if(!do_get_this) do_get_this = !find_uid(popb, info->uid); */ |
648 gboolean do_get_this = !(popb->flags & POP3_FLAG_UIDL); | 659 if (!do_get_this) |
649 /* if(!do_get_this) do_get_this = !find_uid(popb, info->uid);*/ | 660 do_get_this = !(info->is_in_uidl); |
650 if(!do_get_this) do_get_this = !(info->is_in_uidl); | 661 if (do_get_this) { |
651 if(do_get_this){ | 662 |
652 | 663 if ((info->size < max_size) || (max_size == 0)) { |
653 if((info->size < max_size) || (max_size == 0)){ | 664 message *msg; |
654 message *msg; | 665 |
655 | 666 logwrite(LOG_VERBOSE | LOG_NOTICE, "receiving message %d\n", info->number); |
656 logwrite(LOG_VERBOSE|LOG_NOTICE, "receiving message %d\n", info->number); | 667 msg = pop3_in_retr(popb, info->number, rcpt); |
657 msg = pop3_in_retr(popb, info->number, rcpt); | 668 |
658 | 669 if (msg) { |
659 if(msg){ | 670 if (return_path) |
660 if(return_path) | 671 msg->return_path = copy_address(return_path); |
661 msg->return_path = copy_address(return_path); | 672 if (spool_write(msg, TRUE)) { |
662 if(spool_write(msg, TRUE)){ | 673 pid_t pid; |
663 pid_t pid; | 674 logwrite(LOG_NOTICE, "%s <= %s host=%s with %s\n", msg->uid, |
664 logwrite(LOG_NOTICE, "%s <= %s host=%s with %s\n", | 675 addr_string(msg->return_path), popb->remote_host, |
665 msg->uid, | 676 (popb->flags & POP3_FLAG_APOP) ? prot_names [PROT_APOP] : prot_names [PROT_POP3]); |
666 addr_string(msg->return_path), | 677 info->is_fetched = TRUE; |
667 popb->remote_host, | 678 count++; |
668 (popb->flags & POP3_FLAG_APOP) ? | |
669 prot_names[PROT_APOP] : prot_names[PROT_POP3] | |
670 ); | |
671 info->is_fetched = TRUE; | |
672 count++; | |
673 #if DO_WRITE_UIDL_EARLY | 679 #if DO_WRITE_UIDL_EARLY |
674 if(popb->flags & POP3_FLAG_UIDL) write_uidl(popb, user); | 680 if (popb->flags & POP3_FLAG_UIDL) |
681 write_uidl(popb, user); | |
675 #endif | 682 #endif |
676 if(!conf.do_queue){ | 683 if (!conf.do_queue) { |
677 | 684 |
678 /* wait for child processes. If there are too many, | 685 /* wait for child processes. If there are too many, we wait blocking, before we fork another one */ |
679 we wait blocking, before we fork another one */ | 686 while (num_children > 0) { |
680 while(num_children > 0){ | 687 int status, options = WNOHANG; |
681 int status, options = WNOHANG; | 688 pid_t pid; |
682 pid_t pid; | 689 |
683 | 690 if (num_children >= POP3_MAX_CHILDREN) { |
684 if(num_children >= POP3_MAX_CHILDREN){ | 691 logwrite(LOG_NOTICE, "too many children - waiting\n"); |
685 logwrite(LOG_NOTICE, "too many children - waiting\n"); | 692 options = 0; |
686 options = 0; | 693 } |
687 } | 694 if ((pid = waitpid(0, &status, options)) > 0) { |
688 if((pid = waitpid(0, &status, options)) > 0){ | 695 num_children--; |
689 num_children--; | 696 if (WEXITSTATUS(status) != EXIT_SUCCESS) |
690 if(WEXITSTATUS(status) != EXIT_SUCCESS) | 697 logwrite(LOG_WARNING, "delivery process with pid %d returned %d\n", pid, WEXITSTATUS (status)); |
691 logwrite(LOG_WARNING, | 698 if (WIFSIGNALED(status)) |
692 "delivery process with pid %d returned %d\n", | 699 logwrite(LOG_WARNING, "delivery process with pid %d got signal: %d\n", pid, WTERMSIG (status)); |
693 pid, WEXITSTATUS(status)); | 700 } else if (pid < 0) { |
694 if(WIFSIGNALED(status)) | 701 logwrite(LOG_WARNING, "wait got error: %s\n", strerror(errno)); |
695 logwrite(LOG_WARNING, | 702 } |
696 "delivery process with pid %d got signal: %d\n", | 703 } |
697 pid, WTERMSIG(status)); | 704 |
698 }else if(pid < 0){ | 705 if ((pid = fork()) == 0) { |
699 logwrite(LOG_WARNING, "wait got error: %s\n", strerror(errno)); | 706 deliver(msg); |
700 } | 707 _exit(EXIT_SUCCESS); |
701 } | 708 } else if (pid < 0) { |
702 | 709 logwrite(LOG_ALERT | LOG_VERBOSE, "could not fork for delivery, id = %s: %s\n", msg->uid, strerror(errno)); |
703 if((pid = fork()) == 0){ | 710 } else |
704 deliver(msg); | 711 num_children++; |
705 _exit(EXIT_SUCCESS); | 712 } else { |
706 }else if(pid < 0){ | 713 DEBUG(1) debugf("queuing forced by configuration or option.\n"); |
707 logwrite(LOG_ALERT|LOG_VERBOSE, | 714 } |
708 "could not fork for delivery, id = %s: %s\n", | 715 if (popb->flags & POP3_FLAG_DELETE) |
709 msg->uid, strerror(errno)); | 716 pop3_in_dele(popb, info->number); |
710 }else | 717 |
711 num_children++; | 718 destroy_message(msg); |
712 }else{ | 719 } /* if(spool_write(msg, TRUE)) */ |
713 DEBUG(1) debugf("queuing forced by configuration or option.\n"); | 720 } else { |
714 } | 721 logwrite(LOG_ALERT, "retrieving of message %d failed: %d\n", info->number, popb->error); |
715 if(popb->flags & POP3_FLAG_DELETE) | 722 } |
716 pop3_in_dele(popb, info->number); | 723 } /* if((info->size > max_size) ... */ |
717 | 724 else { |
718 destroy_message(msg); | 725 logwrite(LOG_NOTICE | LOG_VERBOSE, "size of message #%d (%d) > max_size (%d)\n", info->number, info->size, max_size); |
719 }/* if(spool_write(msg, TRUE)) */ | 726 if (max_size_delete) |
720 }else{ | 727 if (popb->flags & POP3_FLAG_DELETE) |
721 logwrite(LOG_ALERT, | 728 pop3_in_dele(popb, info->number); |
722 "retrieving of message %d failed: %d\n", | 729 } |
723 info->number, popb->error); | 730 } /* if(do_get_this) ... */ |
724 } | 731 else { |
725 }/* if((info->size > max_size) ... */ | 732 if (popb->flags & POP3_FLAG_UIDL) { |
726 else{ | 733 info->is_fetched = TRUE; /* obsolete? */ |
727 logwrite(LOG_NOTICE|LOG_VERBOSE, "size of message #%d (%d) > max_size (%d)\n", | 734 logwrite(LOG_VERBOSE, "message %d already known\n", info->number); |
728 info->number, info->size, max_size); | 735 DEBUG(1) debugf("message %d (uid = %s) not fetched\n", info->number, info->uid); |
729 if(max_size_delete) | |
730 if(popb->flags & POP3_FLAG_DELETE) | |
731 pop3_in_dele(popb, info->number); | |
732 } | |
733 }/* if(do_get_this) ... */ | |
734 else{ | |
735 if(popb->flags & POP3_FLAG_UIDL){ | |
736 info->is_fetched = TRUE; /* obsolete? */ | |
737 logwrite(LOG_VERBOSE, "message %d already known\n", | |
738 info->number); | |
739 DEBUG(1) debugf("message %d (uid = %s) not fetched\n", | |
740 info->number, info->uid); | |
741 #if 0 | 736 #if 0 |
742 #if DO_WRITE_UIDL_EARLY | 737 #if DO_WRITE_UIDL_EARLY |
743 write_uidl(popb, user); /* obsolete? */ | 738 write_uidl(popb, user); /* obsolete? */ |
744 #endif | 739 #endif |
745 #endif | 740 #endif |
746 } | 741 } |
747 } | 742 } |
748 if((max_count != 0) && (count >= max_count)) | 743 if ((max_count != 0) && (count >= max_count)) |
749 break; | 744 break; |
750 }/* foreach() */ | 745 } /* foreach() */ |
751 #if DO_WRITE_UIDL_EARLY | 746 #if DO_WRITE_UIDL_EARLY |
752 #else | 747 #else |
753 if(popb->flags & POP3_FLAG_UIDL) write_uidl(popb, user); | 748 if (popb->flags & POP3_FLAG_UIDL) |
749 write_uidl(popb, user); | |
754 #endif | 750 #endif |
755 }/* if(pop3_in_uidl(popb) ... */ | 751 } /* if(pop3_in_uidl(popb) ... */ |
756 }/* if(pop3_in_list(popb)) */ | 752 } /* if(pop3_in_list(popb)) */ |
757 }/* if(popb->msg_cnt > 0) */ | 753 } /* if(popb->msg_cnt > 0) */ |
758 else{ | 754 else { |
759 logwrite(LOG_NOTICE|LOG_VERBOSE, | 755 logwrite(LOG_NOTICE | LOG_VERBOSE, "no messages for user %s at %s\n", user, popb->remote_host); |
760 "no messages for user %s at %s\n", user, popb->remote_host); | 756 } |
761 } | 757 ok = TRUE; |
762 ok = TRUE; | 758 } |
763 } | 759 pop3_in_quit(popb); |
764 pop3_in_quit(popb); | 760 } else { |
765 }else{ | 761 logwrite(LOG_ALERT | LOG_VERBOSE, "pop3 login failed for user %s, host = %s\n", user, popb->remote_host); |
766 logwrite(LOG_ALERT|LOG_VERBOSE, | 762 } |
767 "pop3 login failed for user %s, host = %s\n", user, popb->remote_host); | 763 } |
768 } | 764 if (!ok) { |
769 } | 765 logwrite(LOG_ALERT | LOG_VERBOSE, "pop3 failed, error = %d\n", popb->error); |
770 if(!ok){ | 766 } |
771 logwrite(LOG_ALERT|LOG_VERBOSE, "pop3 failed, error = %d\n", popb->error); | 767 |
772 } | 768 while (num_children > 0) { |
773 | 769 int status; |
774 while(num_children > 0){ | 770 pid_t pid; |
775 int status; | 771 if ((pid = wait(&status)) > 0) { |
776 pid_t pid; | 772 num_children--; |
777 if((pid = wait(&status)) > 0){ | 773 if (WEXITSTATUS(status) != EXIT_SUCCESS) |
778 num_children--; | 774 logwrite(LOG_WARNING, "delivery process with pid %d returned %d\n", pid, WEXITSTATUS(status)); |
779 if(WEXITSTATUS(status) != EXIT_SUCCESS) | 775 if (WIFSIGNALED(status)) |
780 logwrite(LOG_WARNING, | 776 logwrite(LOG_WARNING, "delivery process with pid %d got signal: %d\n", pid, WTERMSIG(status)); |
781 "delivery process with pid %d returned %d\n", | 777 } else { |
782 pid, WEXITSTATUS(status)); | 778 logwrite(LOG_WARNING, "wait got error: %s\n", strerror(errno)); |
783 if(WIFSIGNALED(status)) | 779 } |
784 logwrite(LOG_WARNING, | 780 } |
785 "delivery process with pid %d got signal: %d\n", | 781 |
786 pid, WTERMSIG(status)); | 782 return ok; |
787 }else{ | |
788 logwrite(LOG_WARNING, "wait got error: %s\n", strerror(errno)); | |
789 } | |
790 } | |
791 | |
792 return ok; | |
793 } | 783 } |
794 | 784 |
795 /* function just to log into a pop server, | 785 /* function just to log into a pop server, |
796 for pop_before_smtp (or is it smtp_after_pop?) | 786 for pop_before_smtp (or is it smtp_after_pop?) |
797 */ | 787 */ |
798 | 788 |
799 gboolean pop3_login(gchar *host, gint port, GList *resolve_list, | 789 gboolean |
800 gchar *user, gchar *pass, guint flags) | 790 pop3_login(gchar * host, gint port, GList * resolve_list, gchar * user, gchar * pass, guint flags) |
801 { | 791 { |
802 gboolean ok = FALSE; | 792 gboolean ok = FALSE; |
803 pop3_base *popb; | 793 pop3_base *popb; |
804 | 794 |
805 signal(SIGCHLD, SIG_IGN); | 795 signal(SIGCHLD, SIG_IGN); |
806 | 796 |
807 if((popb = pop3_in_open(host, port, resolve_list, flags))){ | 797 if ((popb = pop3_in_open(host, port, resolve_list, flags))) { |
808 if(pop3_in_init(popb)){ | 798 if (pop3_in_init(popb)) { |
809 if(pop3_in_login(popb, user, pass)) | 799 if (pop3_in_login(popb, user, pass)) |
810 ok = TRUE; | 800 ok = TRUE; |
811 else | 801 else |
812 logwrite(LOG_ALERT|LOG_VERBOSE, | 802 logwrite(LOG_ALERT | LOG_VERBOSE, "pop3 login failed for user %s, host = %s\n", user, host); |
813 "pop3 login failed for user %s, host = %s\n", user, host); | 803 } |
814 } | 804 pop3_in_close(popb); |
815 pop3_in_close(popb); | 805 } |
816 } | 806 return ok; |
817 return ok; | |
818 } | 807 } |
819 | 808 |
820 #endif | 809 #endif |