masqmail

view src/pop3_in.c @ 156:ee2afbf92428

require host_name to be set in config file exit otherwise there is no portable way to determine the hostname (actually the hostname that masqmail should use) thus it must be set by the administrator
author meillo@marmaro.de
date Thu, 08 Jul 2010 09:49:05 +0200
parents c93023f58cc7
children dc89737b27aa
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 <sys/wait.h>
21 #include <sys/stat.h>
23 #include "masqmail.h"
24 #include "pop3_in.h"
25 #include "readsock.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 /* FIXME: Paolo's code has the return stmt
273 inside the if block right above it. What
274 is correct? */
275 }
276 popb->error = pop3_syntax;
277 }
278 return FALSE;
279 }
281 static gboolean
282 get_drop_listing(pop3_base * popb)
283 {
284 gchar buf[64];
286 DEBUG(5) debugf("get_drop_listing() entered\n");
288 while (1) {
289 gint len = read_sockline(popb->in, buf, 64, POP3_CMD_TIMEOUT, READSOCKL_CHUG);
290 if (len > 0) {
291 if (buf[0] == '.')
292 return TRUE;
293 else {
294 gint number, msg_size;
295 gchar *p = buf, *pe;
296 if (strtoi(p, &pe, &number)) {
297 p = pe;
298 if (strtoi(p, &pe, &msg_size)) {
299 msg_info *info = g_malloc(sizeof(msg_info));
300 info->number = number;
301 info->size = msg_size;
303 DEBUG(5) debugf ("get_drop_listing(), number = %d, msg_size = %d\n", number, msg_size);
305 info->uid = NULL;
306 info->is_fetched = FALSE;
307 info->is_in_uidl = FALSE;
308 popb->drop_list = g_list_append(popb->drop_list, info);
309 } else {
310 popb->error = pop3_syntax;
311 break;
312 }
313 } else {
314 popb->error = pop3_syntax;
315 break;
316 }
317 }
318 } else {
319 popb->error = (len == -1) ? pop3_eof : pop3_timeout;
320 return FALSE;
321 }
322 }
323 return FALSE;
324 }
326 static gboolean
327 get_uid_listing(pop3_base * popb)
328 {
329 gchar buf[64];
331 while (1) {
332 gint len = read_sockline(popb->in, buf, 64, POP3_CMD_TIMEOUT, READSOCKL_CHUG);
333 if (len > 0) {
334 if (buf[0] == '.')
335 return TRUE;
336 else {
337 gint number;
338 gchar *p = buf, *pe;
339 if (strtoi(p, &pe, &number)) {
340 msg_info *info = NULL;
341 GList *drop_node;
343 p = pe;
344 while (*p && isspace(*p))
345 p++;
347 foreach(popb->drop_list, drop_node) {
348 msg_info *curr_info = (msg_info *) (drop_node->data);
349 if (curr_info->number == number) {
350 info = curr_info;
351 break;
352 }
353 }
354 if (info) {
355 info->uid = g_strdup(p);
356 g_strchomp(info->uid);
357 }
359 } else {
360 popb->error = pop3_syntax;
361 break;
362 }
363 }
364 }
365 }
366 return FALSE;
367 }
369 static gboolean
370 check_init_response(pop3_base * popb)
371 {
372 if (check_response(popb)) {
373 gchar buf[256];
374 gchar *p = popb->buffer;
375 gint i = 0;
376 if (*p) {
377 while (*p && (*p != '<'))
378 p++;
379 while (*p && (*p != '>') && (i < 254))
380 buf[i++] = *(p++);
381 buf[i++] = '>';
382 buf[i] = '\0';
384 popb->timestamp = g_strdup(buf);
386 return TRUE;
387 }
388 }
389 return FALSE;
390 }
392 void
393 pop3_in_close(pop3_base * popb)
394 {
395 GList *node;
397 fclose(popb->in);
398 fclose(popb->out);
400 close(popb->sock);
402 foreach(popb->list_uid_old, node) {
403 gchar *uid = (gchar *) (node->data);
404 g_free(uid);
405 }
406 g_list_free(popb->list_uid_old);
408 foreach(popb->drop_list, node) {
409 msg_info *info = (msg_info *) (node->data);
410 if (info->uid)
411 g_free(info->uid);
412 g_free(info);
413 }
414 g_list_free(popb->drop_list);
416 if (popb->buffer)
417 g_free(popb->buffer);
418 if (popb->timestamp)
419 g_free(popb->timestamp);
420 }
422 pop3_base*
423 pop3_in_open(gchar * host, gint port, GList * resolve_list, guint flags)
424 {
425 pop3_base *popb;
426 gint sock;
427 mxip_addr *addr;
429 DEBUG(5) debugf("pop3_in_open entered, host = %s\n", host);
431 if ((addr = connect_resolvelist(&sock, host, port, resolve_list))) {
432 /* create structure to hold status data: */
433 popb = create_pop3base(sock, flags);
434 popb->remote_host = addr->name;
436 DEBUG(5) {
437 struct sockaddr_in name;
438 int len;
439 getsockname(sock, (struct sockaddr *) (&name), &len);
440 debugf("socket: name.sin_addr = %s\n", inet_ntoa(name.sin_addr));
441 }
442 return popb;
443 }
444 return NULL;
445 }
447 pop3_base*
448 pop3_in_open_child(gchar * cmd, guint flags)
449 {
450 pop3_base *popb;
451 gint sock;
453 DEBUG(5) debugf("pop3_in_open_child entered, cmd = %s\n", cmd);
454 sock = child(cmd);
455 if (sock > 0) {
456 popb = create_pop3base(sock, flags);
457 popb->remote_host = NULL;
458 return popb;
459 }
460 logwrite(LOG_ALERT, "child failed (sock = %d): %s\n", sock, strerror(errno));
462 return NULL;
463 }
465 gboolean
466 pop3_in_init(pop3_base * popb)
467 {
468 gboolean ok;
470 if ((ok = read_response(popb, POP3_INITIAL_TIMEOUT))) {
471 ok = check_init_response(popb);
472 }
473 if (!ok)
474 /* pop3_in_log_failure(popb, NULL); */
475 logwrite(LOG_ALERT, "pop3 failed\n");
476 return ok;
477 }
479 gboolean
480 pop3_in_login(pop3_base * popb, gchar * user, gchar * pass)
481 {
482 if (popb->flags & POP3_FLAG_APOP) {
484 gchar *string = g_strdup_printf("%s%s", popb->timestamp, pass);
485 gchar *digest = MD5String(string);
486 pop3_printf(popb->out, "APOP %s %s\r\n", user, digest);
487 g_free(string);
488 g_free(digest);
489 if (read_response(popb, POP3_CMD_TIMEOUT)) {
490 if (check_response(popb))
491 return TRUE;
492 else
493 popb->error = pop3_login_failure;
494 }
496 } else {
498 pop3_printf(popb->out, "USER %s\r\n", user);
499 if (read_response(popb, POP3_CMD_TIMEOUT)) {
500 if (check_response(popb)) {
501 pop3_printf(popb->out, "PASS %s\r\n", pass);
502 if (read_response(popb, POP3_CMD_TIMEOUT)) {
503 if (check_response(popb))
504 return TRUE;
505 else
506 popb->error = pop3_login_failure;
507 }
508 } else {
509 popb->error = pop3_login_failure;
510 }
511 }
512 }
513 return FALSE;
514 }
516 gboolean
517 pop3_in_stat(pop3_base * popb)
518 {
519 pop3_printf(popb->out, "STAT\r\n");
520 if (read_response(popb, POP3_CMD_TIMEOUT)) {
521 gint msg_cnt, mbox_size;
522 if (check_response_int_int(popb, &msg_cnt, &mbox_size)) {
523 popb->msg_cnt = msg_cnt;
524 popb->mbox_size = mbox_size;
526 return TRUE;
527 }
528 }
529 return FALSE;
530 }
532 gboolean
533 pop3_in_list(pop3_base * popb)
534 {
535 pop3_printf(popb->out, "LIST\r\n");
536 if (read_response(popb, POP3_CMD_TIMEOUT)) {
537 if (get_drop_listing(popb)) {
538 return TRUE;
539 }
540 }
541 return FALSE;
542 }
544 gboolean
545 pop3_in_dele(pop3_base * popb, gint number)
546 {
547 pop3_printf(popb->out, "DELE %d\r\n", number);
548 if (read_response(popb, POP3_CMD_TIMEOUT)) {
549 return TRUE;
550 }
551 return FALSE;
552 }
554 message*
555 pop3_in_retr(pop3_base * popb, gint number, address * rcpt)
556 {
557 accept_error err;
559 pop3_printf(popb->out, "RETR %d\r\n", number);
560 if (read_response(popb, POP3_CMD_TIMEOUT)) {
561 message *msg = create_message();
562 msg->received_host = popb->remote_host;
563 msg->received_prot = (popb->flags & POP3_FLAG_APOP) ? PROT_APOP : PROT_POP3;
564 msg->transfer_id = (popb->next_id)++;
565 msg->rcpt_list = g_list_append(NULL, copy_address(rcpt));
567 if ((err = accept_message(popb->in, msg, ACC_MAIL_FROM_HEAD
568 | (conf.do_save_envelope_to ? ACC_SAVE_ENVELOPE_TO : 0)))
569 == AERR_OK)
570 return msg;
572 destroy_message(msg);
573 }
574 return NULL;
575 }
577 gboolean
578 pop3_in_uidl(pop3_base * popb)
579 {
580 pop3_printf(popb->out, "UIDL\r\n");
581 if (read_response(popb, POP3_CMD_TIMEOUT)) {
582 if (get_uid_listing(popb)) {
583 return TRUE;
584 }
585 }
586 return FALSE;
587 }
589 gboolean
590 pop3_in_quit(pop3_base * popb)
591 {
592 pop3_printf(popb->out, "QUIT\r\n");
593 DEBUG(4) debugf("QUIT\n");
594 signal(SIGALRM, SIG_DFL);
595 return TRUE;
596 }
598 /* Send a DELE command for each message in (the old) uid listing.
599 This is to prevent mail from to be kept on server, if a previous
600 transaction was interupted. */
601 gboolean
602 pop3_in_uidl_dele(pop3_base * popb)
603 {
604 GList *drop_node;
606 foreach(popb->drop_list, drop_node) {
607 msg_info *info = (msg_info *) (drop_node->data);
608 /* if(find_uid(popb, info->uid)){ */
609 if (info->is_in_uidl) {
610 if (!pop3_in_dele(popb, info->number))
611 return FALSE;
612 /* TODO: it probably makes sense to also delete this uid from the listing */
613 }
614 }
615 return TRUE;
616 }
618 gboolean
619 pop3_get(pop3_base * popb, gchar * user, gchar * pass, address * rcpt, address * return_path,
620 gint max_count, gint max_size, gboolean max_size_delete)
621 {
622 gboolean ok = FALSE;
623 gint num_children = 0;
625 DEBUG(5) debugf("rcpt = %s@%s\n", rcpt->local_part, rcpt->domain);
627 signal(SIGCHLD, SIG_DFL);
629 if (pop3_in_init(popb)) {
630 if (pop3_in_login(popb, user, pass)) {
631 if (pop3_in_stat(popb)) {
632 if (popb->msg_cnt > 0) {
634 logwrite(LOG_NOTICE | LOG_VERBOSE, "%d message(s) for user %s at %s\n",
635 popb->msg_cnt, user, popb->remote_host);
637 if (pop3_in_list(popb)) {
638 gboolean do_get = !(popb->flags & POP3_FLAG_UIDL);
639 if (!do_get)
640 do_get = pop3_in_uidl(popb);
641 if (do_get) {
642 gint count = 0;
643 GList *drop_node;
645 if (popb->flags & POP3_FLAG_UIDL) {
646 read_uidl(popb, user);
647 logwrite(LOG_VERBOSE | LOG_NOTICE, "%d message(s) already in uidl.\n", popb->uidl_known_cnt);
648 }
649 if ((popb->flags & POP3_FLAG_UIDL) && (popb->flags & POP3_FLAG_UIDL_DELE))
650 pop3_in_uidl_dele(popb);
652 foreach(popb->drop_list, drop_node) {
654 msg_info *info = (msg_info *) (drop_node->data);
655 gboolean do_get_this = !(popb->flags & POP3_FLAG_UIDL);
656 /* if(!do_get_this) do_get_this = !find_uid(popb, info->uid); */
657 if (!do_get_this)
658 do_get_this = !(info->is_in_uidl);
659 if (do_get_this) {
661 if ((info->size < max_size) || (max_size == 0)) {
662 message *msg;
664 logwrite(LOG_VERBOSE | LOG_NOTICE, "receiving message %d\n", info->number);
665 msg = pop3_in_retr(popb, info->number, rcpt);
667 if (msg) {
668 if (return_path)
669 msg->return_path = copy_address(return_path);
670 if (spool_write(msg, TRUE)) {
671 pid_t pid;
672 logwrite(LOG_NOTICE, "%s <= %s host=%s with %s\n", msg->uid,
673 addr_string(msg->return_path), popb->remote_host,
674 (popb->flags & POP3_FLAG_APOP) ? prot_names [PROT_APOP] : prot_names [PROT_POP3]);
675 info->is_fetched = TRUE;
676 count++;
677 #if DO_WRITE_UIDL_EARLY
678 if (popb->flags & POP3_FLAG_UIDL)
679 write_uidl(popb, user);
680 #endif
681 if (!conf.do_queue) {
683 /* wait for child processes. If there are too many, we wait blocking, before we fork another one */
684 while (num_children > 0) {
685 int status, options = WNOHANG;
686 pid_t pid;
688 if (num_children >= POP3_MAX_CHILDREN) {
689 logwrite(LOG_NOTICE, "too many children - waiting\n");
690 options = 0;
691 }
692 if ((pid = waitpid(0, &status, options)) > 0) {
693 num_children--;
694 if (WEXITSTATUS(status) != EXIT_SUCCESS)
695 logwrite(LOG_WARNING, "delivery process with pid %d returned %d\n", pid, WEXITSTATUS (status));
696 if (WIFSIGNALED(status))
697 logwrite(LOG_WARNING, "delivery process with pid %d got signal: %d\n", pid, WTERMSIG (status));
698 } else if (pid < 0) {
699 logwrite(LOG_WARNING, "wait got error: %s\n", strerror(errno));
700 }
701 }
703 if ((pid = fork()) == 0) {
704 deliver(msg);
705 _exit(EXIT_SUCCESS);
706 } else if (pid < 0) {
707 logwrite(LOG_ALERT | LOG_VERBOSE, "could not fork for delivery, id = %s: %s\n", msg->uid, strerror(errno));
708 } else
709 num_children++;
710 } else {
711 DEBUG(1) debugf("queuing forced by configuration or option.\n");
712 }
713 if (popb->flags & POP3_FLAG_DELETE)
714 pop3_in_dele(popb, info->number);
716 destroy_message(msg);
717 } /* if(spool_write(msg, TRUE)) */
718 } else {
719 logwrite(LOG_ALERT, "retrieving of message %d failed: %d\n", info->number, popb->error);
720 }
721 } else {
722 /* info->size > max_size */
723 logwrite(LOG_NOTICE | LOG_VERBOSE, "size of message #%d (%d) > max_size (%d)\n", info->number, info->size, max_size);
724 if (max_size_delete)
725 if (popb->flags & POP3_FLAG_DELETE)
726 pop3_in_dele(popb, info->number);
727 }
728 } /* if(do_get_this) ... */
729 else {
730 if (popb->flags & POP3_FLAG_UIDL) {
731 info->is_fetched = TRUE; /* obsolete? */
732 logwrite(LOG_VERBOSE, "message %d already known\n", info->number);
733 DEBUG(1) debugf("message %d (uid = %s) not fetched\n", info->number, info->uid);
734 #if 0
735 #if DO_WRITE_UIDL_EARLY
736 write_uidl(popb, user); /* obsolete? */
737 #endif
738 #endif
739 }
740 }
741 if ((max_count != 0) && (count >= max_count))
742 break;
743 } /* foreach() */
744 #if DO_WRITE_UIDL_EARLY
745 #else
746 if (popb->flags & POP3_FLAG_UIDL)
747 write_uidl(popb, user);
748 #endif
749 } /* if(pop3_in_uidl(popb) ... */
750 } /* if(pop3_in_list(popb)) */
751 } /* if(popb->msg_cnt > 0) */
752 else {
753 logwrite(LOG_NOTICE | LOG_VERBOSE, "no messages for user %s at %s\n", user, popb->remote_host);
754 }
755 ok = TRUE;
756 }
757 pop3_in_quit(popb);
758 } else {
759 logwrite(LOG_ALERT | LOG_VERBOSE, "pop3 login failed for user %s, host = %s\n", user, popb->remote_host);
760 }
761 }
762 if (!ok) {
763 logwrite(LOG_ALERT | LOG_VERBOSE, "pop3 failed, error = %d\n", popb->error);
764 }
766 while (num_children > 0) {
767 int status;
768 pid_t pid;
769 if ((pid = wait(&status)) > 0) {
770 num_children--;
771 if (WEXITSTATUS(status) != EXIT_SUCCESS)
772 logwrite(LOG_WARNING, "delivery process with pid %d returned %d\n", pid, WEXITSTATUS(status));
773 if (WIFSIGNALED(status))
774 logwrite(LOG_WARNING, "delivery process with pid %d got signal: %d\n", pid, WTERMSIG(status));
775 } else {
776 logwrite(LOG_WARNING, "wait got error: %s\n", strerror(errno));
777 }
778 }
780 return ok;
781 }
783 /* function just to log into a pop server,
784 for pop_before_smtp (or is it smtp_after_pop?)
785 */
787 gboolean
788 pop3_login(gchar * host, gint port, GList * resolve_list, gchar * user, gchar * pass, guint flags)
789 {
790 gboolean ok = FALSE;
791 pop3_base *popb;
793 signal(SIGCHLD, SIG_IGN);
795 if ((popb = pop3_in_open(host, port, resolve_list, flags))) {
796 if (pop3_in_init(popb)) {
797 if (pop3_in_login(popb, user, pass))
798 ok = TRUE;
799 else
800 logwrite(LOG_ALERT | LOG_VERBOSE, "pop3 login failed for user %s, host = %s\n", user, host);
801 }
802 pop3_in_close(popb);
803 }
804 return ok;
805 }
807 #endif