masqmail-0.2

view src/pop3_in.c @ 14:a8f3424347dc

replaced number 0 with character \0 where appropriate
author meillo@marmaro.de
date Wed, 29 Oct 2008 21:21:26 +0100
parents 08114f7dcc23
children f671821d8222
line source
1 /* pop3_in.c, Copyright (C) 2000 by Oliver Kurth,
2 *
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
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16 */
18 /* see RFC 1725 */
20 #include "masqmail.h"
21 #include "pop3_in.h"
22 #include "readsock.h"
24 #include <sys/wait.h>
25 #include <sys/stat.h>
27 #ifdef USE_LIB_CRYPTO
28 #include <openssl/md5.h>
29 #else
30 #include "md5/global.h"
31 #include "md5/md5.h"
32 #endif
34 #ifdef ENABLE_POP3
36 /* experimental feature */
37 #define DO_WRITE_UIDL_EARLY 1
39 static gchar*
40 MD5String(char *string)
41 {
42 MD5_CTX context;
43 unsigned char digest[16];
44 char str_digest[33];
45 int i;
47 #ifdef USE_LIB_CRYPTO
48 MD5(string, strlen(string), digest);
49 #else
50 MD5Init(&context);
51 MD5Update(&context, string, strlen(string));
52 MD5Final(digest, &context);
53 #endif
54 for (i = 0; i < 16; i++)
55 sprintf(str_digest + 2 * i, "%02x", digest[i]);
57 return g_strdup(str_digest);
58 }
60 static pop3_base*
61 create_pop3base(gint sock, guint flags)
62 {
63 gint dup_sock;
65 pop3_base *popb = (pop3_base *) g_malloc(sizeof(pop3_base));
66 if (popb) {
67 memset(popb, 0, sizeof(pop3_base));
69 popb->error = pop3_ok;
71 popb->buffer = (gchar *) g_malloc(POP3_BUF_LEN);
73 dup_sock = dup(sock);
74 popb->out = fdopen(sock, "w");
75 popb->in = fdopen(dup_sock, "r");
77 popb->flags = flags;
78 }
79 return popb;
80 }
82 static void
83 pop3_printf(FILE * out, gchar * fmt, ...)
84 {
85 va_list args;
86 va_start(args, fmt);
88 DEBUG(4) {
89 gchar buf[256];
90 va_list args_copy;
92 va_copy(args_copy, args);
93 vsnprintf(buf, 255, fmt, args_copy);
94 va_end(args_copy);
96 debugf(">>>%s", buf);
97 }
99 vfprintf(out, fmt, args);
100 fflush(out);
102 va_end(args);
103 }
105 static gboolean
106 find_uid(pop3_base * popb, gchar * str)
107 {
108 GList *node, *node_next;
110 for (node = popb->list_uid_old; node; node = node_next) {
111 gchar *uid = (gchar *) (node->data);
112 node_next = node->next;
113 if (strcmp(uid, str) == 0) {
114 #if 1
115 popb->list_uid_old = g_list_remove_link(popb->list_uid_old, node);
116 g_list_free_1(node);
117 g_free(uid);
118 #endif
119 return TRUE;
120 }
121 }
122 return FALSE;
123 }
125 static gboolean
126 write_uidl(pop3_base * popb, gchar * user)
127 {
128 gboolean ok = FALSE;
129 GList *node;
130 gchar *filename = g_strdup_printf("%s/popuidl/%s@%s", conf.spool_dir, user, popb->remote_host);
131 gchar *tmpname = g_strdup_printf("%s.tmp", filename);
132 FILE *fptr = fopen(tmpname, "wt");
134 if (fptr) {
135 foreach(popb->drop_list, node) {
136 msg_info *info = (msg_info *) (node->data);
137 if (info->is_fetched || info->is_in_uidl)
138 fprintf(fptr, "%s\n", info->uid);
139 }
140 fclose(fptr);
141 ok = (rename(tmpname, filename) != -1);
142 }
144 g_free(tmpname);
145 g_free(filename);
146 return ok;
147 }
149 static gboolean
150 read_uidl_fname(pop3_base * popb, gchar * filename)
151 {
152 gboolean ok = FALSE;
153 FILE *fptr = fopen(filename, "rt");
154 gchar buf[256];
156 if (fptr) {
157 popb->list_uid_old = NULL;
158 while (fgets(buf, 255, fptr)) {
159 if (buf[strlen(buf) - 1] == '\n') {
160 g_strchomp(buf);
161 popb->list_uid_old = g_list_append(popb->list_uid_old, g_strdup(buf));
162 } else {
163 logwrite(LOG_ALERT, "broken uid: %s\n", buf);
164 break;
165 }
166 }
167 fclose(fptr);
168 ok = TRUE;
169 } else
170 logwrite(LOG_ALERT, "opening of %s failed: %s", filename, strerror(errno));
171 return ok;
172 }
174 static gboolean
175 read_uidl(pop3_base * popb, gchar * user)
176 {
177 gboolean ok = FALSE;
178 struct stat statbuf;
179 gchar *filename = g_strdup_printf("%s/popuidl/%s@%s", conf.spool_dir, user, popb->remote_host);
181 if (stat(filename, &statbuf) == 0) {
182 ok = read_uidl_fname(popb, filename);
183 if (ok) {
184 GList *drop_node;
185 foreach(popb->drop_list, drop_node) {
186 msg_info *info = (msg_info *) (drop_node->data);
187 if (find_uid(popb, info->uid)) {
188 DEBUG(5) debugf("msg with uid '%s' already known\n", info->uid);
189 info->is_in_uidl = TRUE;
190 popb->uidl_known_cnt++;
191 } else
192 DEBUG(5) debugf("msg with uid '%s' not known\n", info->uid);
193 }
194 }
195 } else {
196 logwrite(LOG_DEBUG, "no uidl file '%s' found\n", filename);
197 ok = TRUE;
198 }
200 g_free(filename);
201 return ok; /* return code is irrelevant, do not check... */
202 }
204 static gboolean
205 read_response(pop3_base * popb, int timeout)
206 {
207 gint len;
209 len = read_sockline(popb->in, popb->buffer, POP3_BUF_LEN, timeout, READSOCKL_CHUG);
211 if (len == -3) {
212 popb->error = pop3_timeout;
213 return FALSE;
214 } else if (len == -2) {
215 popb->error = pop3_syntax;
216 return FALSE;
217 } else if (len == -1) {
218 popb->error = pop3_eof;
219 return FALSE;
220 }
222 return TRUE;
223 }
225 static gboolean
226 check_response(pop3_base * popb)
227 {
228 char c = popb->buffer[0];
230 if (c == '+') {
231 popb->error = pop3_ok;
232 return TRUE;
233 } else if (c == '-')
234 popb->error = pop3_fail;
235 else
236 popb->error = pop3_syntax;
237 return FALSE;
238 }
240 static gboolean
241 strtoi(gchar * p, gchar ** pend, gint * val)
242 {
243 gchar buf[12];
244 gint i = 0;
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 }
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;
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 }
278 static gboolean
279 get_drop_listing(pop3_base * popb)
280 {
281 gchar buf[64];
283 DEBUG(5) debugf("get_drop_listing() entered\n");
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;
300 DEBUG(5) debugf ("get_drop_listing(), number = %d, msg_size = %d\n", number, msg_size);
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 }
323 static gboolean
324 get_uid_listing(pop3_base * popb)
325 {
326 gchar buf[64];
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;
340 p = pe;
341 while (*p && isspace(*p))
342 p++;
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 }
356 } else {
357 popb->error = pop3_syntax;
358 break;
359 }
360 }
361 }
362 }
363 return FALSE;
364 }
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;
381 popb->timestamp = g_strdup(buf);
383 return TRUE;
384 }
385 }
386 return FALSE;
387 }
389 void
390 pop3_in_close(pop3_base * popb)
391 {
392 GList *node;
394 fclose(popb->in);
395 fclose(popb->out);
397 close(popb->sock);
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);
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);
413 if (popb->buffer)
414 g_free(popb->buffer);
415 if (popb->timestamp)
416 g_free(popb->timestamp);
417 }
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;
426 DEBUG(5) debugf("pop3_in_open entered, host = %s\n", host);
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;
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 }
444 pop3_base*
445 pop3_in_open_child(gchar * cmd, guint flags)
446 {
447 pop3_base *popb;
448 gint sock;
450 DEBUG(5) debugf("pop3_in_open_child entered, cmd = %s\n", cmd);
452 sock = child(cmd);
454 if (sock > 0) {
456 popb = create_pop3base(sock, flags);
457 popb->remote_host = NULL;
459 return popb;
460 }
461 logwrite(LOG_ALERT, "child failed (sock = %d): %s\n", sock, strerror(errno));
463 return NULL;
464 }
466 gboolean
467 pop3_in_init(pop3_base * popb)
468 {
469 gboolean ok;
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 }
480 gboolean
481 pop3_in_login(pop3_base * popb, gchar * user, gchar * pass)
482 {
483 if (popb->flags & POP3_FLAG_APOP) {
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 }
497 } else {
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 }
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;
527 return TRUE;
528 }
529 }
530 return FALSE;
531 }
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 }
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 }
555 message*
556 pop3_in_retr(pop3_base * popb, gint number, address * rcpt)
557 {
558 accept_error err;
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));
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;
573 destroy_message(msg);
574 }
575 return NULL;
576 }
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 }
590 gboolean
591 pop3_in_quit(pop3_base * popb)
592 {
593 pop3_printf(popb->out, "QUIT\r\n");
595 DEBUG(4) debugf("QUIT\n");
597 signal(SIGALRM, SIG_DFL);
599 return TRUE;
600 }
602 /* Send a DELE command for each message in (the old) uid listing.
603 This is to prevent mail from to be kept on server, if a previous
604 transaction was interupted. */
605 gboolean
606 pop3_in_uidl_dele(pop3_base * popb)
607 {
608 GList *drop_node;
610 foreach(popb->drop_list, drop_node) {
611 msg_info *info = (msg_info *) (drop_node->data);
612 /* if(find_uid(popb, info->uid)){ */
613 if (info->is_in_uidl) {
614 if (!pop3_in_dele(popb, info->number))
615 return FALSE;
616 /* TODO: it probably makes sense to also delete this uid from the listing */
617 }
618 }
619 return TRUE;
620 }
622 gboolean
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)
624 {
625 gboolean ok = FALSE;
626 gint num_children = 0;
628 DEBUG(5) debugf("rcpt = %s@%s\n", rcpt->local_part, rcpt->domain);
630 signal(SIGCHLD, SIG_DFL);
632 if (pop3_in_init(popb)) {
633 if (pop3_in_login(popb, user, pass)) {
634 if (pop3_in_stat(popb)) {
635 if (popb->msg_cnt > 0) {
637 logwrite(LOG_NOTICE | LOG_VERBOSE, "%d message(s) for user %s at %s\n", popb->msg_cnt, user, popb->remote_host);
639 if (pop3_in_list(popb)) {
640 gboolean do_get = !(popb->flags & POP3_FLAG_UIDL);
641 if (!do_get)
642 do_get = pop3_in_uidl(popb);
643 if (do_get) {
644 gint count = 0;
645 GList *drop_node;
647 if (popb->flags & POP3_FLAG_UIDL) {
648 read_uidl(popb, user);
649 logwrite(LOG_VERBOSE | LOG_NOTICE, "%d message(s) already in uidl.\n", popb->uidl_known_cnt);
650 }
651 if ((popb->flags & POP3_FLAG_UIDL) && (popb->flags & POP3_FLAG_UIDL_DELE))
652 pop3_in_uidl_dele(popb);
654 foreach(popb->drop_list, drop_node) {
656 msg_info *info = (msg_info *) (drop_node->data);
657 gboolean do_get_this = !(popb->flags & POP3_FLAG_UIDL);
658 /* if(!do_get_this) do_get_this = !find_uid(popb, info->uid); */
659 if (!do_get_this)
660 do_get_this = !(info->is_in_uidl);
661 if (do_get_this) {
663 if ((info->size < max_size) || (max_size == 0)) {
664 message *msg;
666 logwrite(LOG_VERBOSE | LOG_NOTICE, "receiving message %d\n", info->number);
667 msg = pop3_in_retr(popb, info->number, rcpt);
669 if (msg) {
670 if (return_path)
671 msg->return_path = copy_address(return_path);
672 if (spool_write(msg, TRUE)) {
673 pid_t pid;
674 logwrite(LOG_NOTICE, "%s <= %s host=%s with %s\n", msg->uid,
675 addr_string(msg->return_path), popb->remote_host,
676 (popb->flags & POP3_FLAG_APOP) ? prot_names [PROT_APOP] : prot_names [PROT_POP3]);
677 info->is_fetched = TRUE;
678 count++;
679 #if DO_WRITE_UIDL_EARLY
680 if (popb->flags & POP3_FLAG_UIDL)
681 write_uidl(popb, user);
682 #endif
683 if (!conf.do_queue) {
685 /* wait for child processes. If there are too many, we wait blocking, before we fork another one */
686 while (num_children > 0) {
687 int status, options = WNOHANG;
688 pid_t pid;
690 if (num_children >= POP3_MAX_CHILDREN) {
691 logwrite(LOG_NOTICE, "too many children - waiting\n");
692 options = 0;
693 }
694 if ((pid = waitpid(0, &status, options)) > 0) {
695 num_children--;
696 if (WEXITSTATUS(status) != EXIT_SUCCESS)
697 logwrite(LOG_WARNING, "delivery process with pid %d returned %d\n", pid, WEXITSTATUS (status));
698 if (WIFSIGNALED(status))
699 logwrite(LOG_WARNING, "delivery process with pid %d got signal: %d\n", pid, WTERMSIG (status));
700 } else if (pid < 0) {
701 logwrite(LOG_WARNING, "wait got error: %s\n", strerror(errno));
702 }
703 }
705 if ((pid = fork()) == 0) {
706 deliver(msg);
707 _exit(EXIT_SUCCESS);
708 } else if (pid < 0) {
709 logwrite(LOG_ALERT | LOG_VERBOSE, "could not fork for delivery, id = %s: %s\n", msg->uid, strerror(errno));
710 } else
711 num_children++;
712 } else {
713 DEBUG(1) debugf("queuing forced by configuration or option.\n");
714 }
715 if (popb->flags & POP3_FLAG_DELETE)
716 pop3_in_dele(popb, info->number);
718 destroy_message(msg);
719 } /* if(spool_write(msg, TRUE)) */
720 } else {
721 logwrite(LOG_ALERT, "retrieving of message %d failed: %d\n", info->number, popb->error);
722 }
723 } /* if((info->size > max_size) ... */
724 else {
725 logwrite(LOG_NOTICE | LOG_VERBOSE, "size of message #%d (%d) > max_size (%d)\n", info->number, info->size, max_size);
726 if (max_size_delete)
727 if (popb->flags & POP3_FLAG_DELETE)
728 pop3_in_dele(popb, info->number);
729 }
730 } /* if(do_get_this) ... */
731 else {
732 if (popb->flags & POP3_FLAG_UIDL) {
733 info->is_fetched = TRUE; /* obsolete? */
734 logwrite(LOG_VERBOSE, "message %d already known\n", info->number);
735 DEBUG(1) debugf("message %d (uid = %s) not fetched\n", info->number, info->uid);
736 #if 0
737 #if DO_WRITE_UIDL_EARLY
738 write_uidl(popb, user); /* obsolete? */
739 #endif
740 #endif
741 }
742 }
743 if ((max_count != 0) && (count >= max_count))
744 break;
745 } /* foreach() */
746 #if DO_WRITE_UIDL_EARLY
747 #else
748 if (popb->flags & POP3_FLAG_UIDL)
749 write_uidl(popb, user);
750 #endif
751 } /* if(pop3_in_uidl(popb) ... */
752 } /* if(pop3_in_list(popb)) */
753 } /* if(popb->msg_cnt > 0) */
754 else {
755 logwrite(LOG_NOTICE | LOG_VERBOSE, "no messages for user %s at %s\n", user, popb->remote_host);
756 }
757 ok = TRUE;
758 }
759 pop3_in_quit(popb);
760 } else {
761 logwrite(LOG_ALERT | LOG_VERBOSE, "pop3 login failed for user %s, host = %s\n", user, popb->remote_host);
762 }
763 }
764 if (!ok) {
765 logwrite(LOG_ALERT | LOG_VERBOSE, "pop3 failed, error = %d\n", popb->error);
766 }
768 while (num_children > 0) {
769 int status;
770 pid_t pid;
771 if ((pid = wait(&status)) > 0) {
772 num_children--;
773 if (WEXITSTATUS(status) != EXIT_SUCCESS)
774 logwrite(LOG_WARNING, "delivery process with pid %d returned %d\n", pid, WEXITSTATUS(status));
775 if (WIFSIGNALED(status))
776 logwrite(LOG_WARNING, "delivery process with pid %d got signal: %d\n", pid, WTERMSIG(status));
777 } else {
778 logwrite(LOG_WARNING, "wait got error: %s\n", strerror(errno));
779 }
780 }
782 return ok;
783 }
785 /* function just to log into a pop server,
786 for pop_before_smtp (or is it smtp_after_pop?)
787 */
789 gboolean
790 pop3_login(gchar * host, gint port, GList * resolve_list, gchar * user, gchar * pass, guint flags)
791 {
792 gboolean ok = FALSE;
793 pop3_base *popb;
795 signal(SIGCHLD, SIG_IGN);
797 if ((popb = pop3_in_open(host, port, resolve_list, flags))) {
798 if (pop3_in_init(popb)) {
799 if (pop3_in_login(popb, user, pass))
800 ok = TRUE;
801 else
802 logwrite(LOG_ALERT | LOG_VERBOSE, "pop3 login failed for user %s, host = %s\n", user, host);
803 }
804 pop3_in_close(popb);
805 }
806 return ok;
807 }
809 #endif