]> Pileus Git - ~andy/fetchmail/blob - driver.c
Merge 'next' branch up to tag 'before-cpp'
[~andy/fetchmail] / driver.c
1 /*
2  * driver.c -- generic driver for mail fetch method protocols
3  *
4  * Copyright 1997 by Eric S. Raymond
5  * For license terms, see the file COPYING in this directory.
6  */
7
8 #include  "config.h"
9 #include  <stdio.h>
10 #include  <setjmp.h>
11 #include  <errno.h>
12 #include  <string.h>
13 #include  <stdlib.h>
14 #include  <limits.h>
15 #include <unistd.h>
16 #include  <signal.h>
17 #include <sys/wait.h>
18 #include <sys/time.h>
19
20 #include <sys/socket.h>
21 #include <netdb.h>
22 #ifdef HAVE_PKG_hesiod
23 #ifdef __cplusplus
24 extern "C" {
25 #endif
26 #include <hesiod.h>
27 #ifdef __cplusplus
28 }
29 #endif
30 #endif
31
32 #include <langinfo.h>
33
34 #include "kerberos.h"
35
36 #include "gettext.h"
37 #include "socket.h"
38
39 #include "fetchmail.h"
40 #include "getaddrinfo.h"
41 #include "tunable.h"
42
43 #include "sdump.h"
44
45 /* throw types for runtime errors */
46 #define THROW_TIMEOUT   1               /* server timed out */
47
48 /* magic values for the message length array */
49 #define MSGLEN_UNKNOWN  0               /* length unknown (0 is impossible) */
50 #define MSGLEN_INVALID  -1              /* length passed back is invalid */
51 #define MSGLEN_TOOLARGE -2              /* message is too large */
52 #define MSGLEN_OLD      -3              /* message is old */
53
54 int pass;               /* how many times have we re-polled? */
55 int stage;              /* where are we? */
56 int phase;              /* where are we, for error-logging purposes? */
57 int batchcount;         /* count of messages sent in current batch */
58 flag peek_capable;      /* can we peek for better error recovery? */
59 int mailserver_socket_temp = -1;        /* socket to free if connect timeout */ 
60
61 struct addrinfo *ai0, *ai1;     /* clean these up after signal */
62
63 static volatile int timeoutcount = 0;   /* count consecutive timeouts */
64 static volatile int idletimeout = 0;    /* timeout occured in idle stage? */
65
66 static sigjmp_buf       restart;
67
68 int is_idletimeout(void)
69 /* last timeout occured in idle stage? */
70 {
71     return idletimeout;
72 }
73
74 void resetidletimeout(void)
75 {
76     idletimeout = 0;
77 }
78
79 void set_timeout(int timeleft)
80 /* reset the nonresponse-timeout */
81 {
82     struct itimerval ntimeout;
83
84     if (timeleft == 0)
85         timeoutcount = 0;
86
87     ntimeout.it_interval.tv_sec = ntimeout.it_interval.tv_usec = 0;
88     ntimeout.it_value.tv_sec  = timeleft;
89     ntimeout.it_value.tv_usec = 0;
90     setitimer(ITIMER_REAL, &ntimeout, (struct itimerval *)NULL);
91 }
92
93 static void timeout_handler (int signal)
94 /* handle SIGALRM signal indicating a server timeout */
95 {
96     (void)signal;
97     if(stage != STAGE_IDLE) {
98         timeoutcount++;
99         /* XXX FIXME: this siglongjmp must die - it's not safe to be
100          * called from a function handler and breaks, for instance,
101          * getaddrinfo() */
102         siglongjmp(restart, THROW_TIMEOUT);
103     } else
104         idletimeout = 1;
105 }
106
107 #define CLEANUP_TIMEOUT 60 /* maximum timeout during cleanup */
108
109 static int cleanupSockClose (int fd)
110 /* close sockets in maximum CLEANUP_TIMEOUT seconds during cleanup */
111 {
112     (void)SockTimeout(fd, CLEANUP_TIMEOUT); /* ignore errors */
113     return SockClose(fd);
114 }
115
116 #ifdef KERBEROS_V5
117 /** authenticate to the server host using Kerberos V5 */
118 static int kerberos5_auth(int socket /** socket to server host */, const char *canonical /** server name */)
119 {
120     krb5_error_code retval;
121     krb5_context context;
122     krb5_ccache ccdef;
123     krb5_principal client = NULL, server = NULL;
124     krb5_error *err_ret = NULL;
125
126     krb5_auth_context auth_context = NULL;
127
128     krb5_init_context(&context);
129     krb5_auth_con_init(context, &auth_context);
130
131     if ((retval = krb5_cc_default(context, &ccdef))) {
132         report(stderr, "krb5_cc_default: %s\n", error_message(retval));
133         return(PS_ERROR);
134     }
135
136     if ((retval = krb5_cc_get_principal(context, ccdef, &client))) {
137         report(stderr, "krb5_cc_get_principal: %s\n", error_message(retval));
138         return(PS_ERROR);
139     }
140
141     if ((retval = krb5_sname_to_principal(context, canonical, "pop",
142            KRB5_NT_UNKNOWN,
143            &server))) {
144         report(stderr, "krb5_sname_to_principal: %s\n", error_message(retval));
145         return(PS_ERROR);
146     }
147
148     retval = krb5_sendauth(context, &auth_context, (krb5_pointer) &socket,
149          "KPOPV1.0", client, server,
150          AP_OPTS_MUTUAL_REQUIRED,
151          NULL,  /* no data to checksum */
152          0,   /* no creds, use ccache instead */
153          ccdef,
154          &err_ret, 0,
155
156          NULL); /* don't need reply */
157
158     krb5_free_principal(context, server);
159     krb5_free_principal(context, client);
160     krb5_auth_con_free(context, auth_context);
161
162     if (retval) {
163 #ifdef HEIMDAL
164       if (err_ret && err_ret->e_text) {
165           char *t = err_ret->e_text;
166           char *tt = sdump(t, strlen(t));
167           report(stderr, GT_("krb5_sendauth: %s [server says '%s']\n"),
168                  error_message(retval), tt);
169           free(tt);
170 #else
171       if (err_ret && err_ret->text.length) {
172           char *tt = sdump(err_ret->text.data, err_ret->text.length);
173           report(stderr, GT_("krb5_sendauth: %s [server says '%s']\n"),
174                  error_message(retval), tt);
175           free(tt);
176 #endif
177           krb5_free_error(context, err_ret);
178       } else
179           report(stderr, "krb5_sendauth: %s\n", error_message(retval));
180       return(PS_ERROR);
181     }
182
183     return 0;
184 }
185 #endif /* KERBEROS_V5 */
186
187 static void clean_skipped_list(struct idlist **skipped_list)
188 /* struct "idlist" contains no "prev" ptr; we must remove unused items first */
189 {
190     struct idlist *current=NULL, *prev=NULL, *tmp=NULL, *head=NULL;
191     prev = current = head = *skipped_list;
192
193     if (!head)
194         return;
195     do
196     {
197         /* if item has no reference, remove it */
198         if (current && current->val.status.mark == 0)
199         {
200             if (current == head) /* remove first item (head) */
201             {
202                 head = current->next;
203                 if (current->id) free(current->id);
204                 free(current);
205                 prev = current = head;
206             }
207             else /* remove middle/last item */
208             {
209                 tmp = current->next;
210                 prev->next = tmp;
211                 if (current->id) free(current->id);
212                 free(current);
213                 current = tmp;
214             }
215         }
216         else /* skip this item */
217         {
218             prev = current;
219             current = current->next;
220         }
221     } while(current);
222
223     *skipped_list = head;
224 }
225
226 static void send_size_warnings(struct query *ctl)
227 /* send warning mail with skipped msg; reset msg count when user notified */
228 {
229     int size, nbr;
230     int msg_to_send = FALSE;
231     struct idlist *head=NULL, *current=NULL;
232     int max_warning_poll_count;
233
234     head = ctl->skipped;
235     if (!head)
236         return;
237
238     /* don't start a notification message unless we need to */
239     for (current = head; current; current = current->next)
240         if (current->val.status.num == 0 && current->val.status.mark)
241             msg_to_send = TRUE;
242     if (!msg_to_send)
243         return;
244
245     /*
246      * There's no good way to recover if we can't send notification mail, 
247      * but it's not a disaster, either, since the skipped mail will not
248      * be deleted.
249      */
250     if (open_warning_by_mail(ctl))
251         return;
252     stuff_warning(iana_charset, ctl,
253            GT_("Subject: Fetchmail oversized-messages warning"));
254     stuff_warning(NULL, ctl, "%s", "");
255     if (ctl->limitflush)
256         stuff_warning(NULL, ctl,
257                 GT_("The following oversized messages were deleted on server %s account %s:"),
258                 ctl->server.pollname, ctl->remotename);
259     else
260         stuff_warning(NULL, ctl,
261                 GT_("The following oversized messages remain on server %s account %s:"),
262                 ctl->server.pollname, ctl->remotename);
263
264     stuff_warning(NULL, ctl, "%s", "");
265
266     if (run.poll_interval == 0)
267         max_warning_poll_count = 0;
268     else
269         max_warning_poll_count = ctl->warnings/run.poll_interval;
270
271     /* parse list of skipped msg, adding items to the mail */
272     for (current = head; current; current = current->next)
273     {
274         if (current->val.status.num == 0 && current->val.status.mark)
275         {
276             nbr = current->val.status.mark;
277             size = atoi(current->id);
278             if (ctl->limitflush)
279                 stuff_warning(NULL, ctl,
280                         ngettext("  %d message  %d octets long deleted by fetchmail.",
281                                  "  %d messages %d octets long deleted by fetchmail.", nbr),
282                         nbr, size);
283             else
284                 stuff_warning(NULL, ctl,
285                         ngettext("  %d message  %d octets long skipped by fetchmail.",
286                                  "  %d messages %d octets long skipped by fetchmail.", nbr),
287                         nbr, size);
288         }
289         current->val.status.num++;
290         current->val.status.mark = 0;
291
292         if (current->val.status.num >= max_warning_poll_count)
293             current->val.status.num = 0;
294     }
295
296     stuff_warning(NULL, ctl, "%s", "");
297
298     close_warning_by_mail(ctl, (struct msgblk *)NULL);
299 }
300
301 static void mark_oversized(struct query *ctl, int size)
302 /* mark a message oversized */
303 {
304     struct idlist *current=NULL, *tmp=NULL;
305     char sizestr[32];
306     int cnt;
307
308     /* convert size to string */
309     snprintf(sizestr, sizeof(sizestr), "%d", size);
310
311     /* build a list of skipped messages
312      * val.id = size of msg (string cnvt)
313      * val.status.num = warning_poll_count
314      * val.status.mask = nbr of msg this size
315      */
316
317     current = ctl->skipped;
318
319     /* initialise warning_poll_count to the
320      * current value so that all new msg will
321      * be included in the next mail
322      */
323     cnt = current ? current->val.status.num : 0;
324
325     /* if entry exists, increment the count */
326     if (current && (tmp = str_in_list(&current, sizestr, FALSE)))
327     {
328         tmp->val.status.mark++;
329     }
330     /* otherwise, create a new entry */
331     /* initialise with current poll count */
332     else
333     {
334         tmp = save_str(&ctl->skipped, sizestr, 1);
335         tmp->val.status.num = cnt;
336     }
337 }
338
339 static int eat_trailer(int sock, struct query *ctl)
340 {
341     /* we only need this LF if we're printing ticker dots
342      * AND we are dumping protocol traces. */
343     if (outlevel >= O_VERBOSE && want_progress()) fputc('\n', stdout);
344     return (ctl->server.base_protocol->trail)(sock, ctl, tag);
345 }
346
347 static int fetch_messages(int mailserver_socket, struct query *ctl, 
348                           int count, int **msgsizes, int maxfetch,
349                           int *fetches, int *dispatches, int *deletions)
350 /* fetch messages in lockstep mode */
351 {
352     flag force_retrieval;
353     int num, firstnum = 1, lastnum = 0, err, len;
354     int fetchsizelimit = ctl->fetchsizelimit;
355     int msgsize;
356     int initialfetches = *fetches;
357
358     if (ctl->server.base_protocol->getpartialsizes && NUM_NONZERO(fetchsizelimit))
359     {
360         /* for POP3, we can get the size of one mail only! Unfortunately, this
361          * protocol specific test cannot be done elsewhere as the protocol
362          * could be "auto". */
363         switch (ctl->server.protocol)
364         {
365             case P_POP3: case P_APOP:
366             fetchsizelimit = 1;
367         }
368
369         /* Time to allocate memory to store the sizes */
370         xfree(*msgsizes);
371         *msgsizes = (int *)xmalloc(sizeof(int) * fetchsizelimit);
372     }
373
374     /*
375      * What forces this code is that in
376      * IMAP2bis you can't fetch a message without
377      * having it marked `seen'.  In POP3 and IMAP4, on the
378      * other hand, you can (peek_capable is set by 
379      * each driver module to convey this; it's not a
380      * method constant because of the difference between
381      * IMAP2bis and IMAP4, and because POP3 doesn't  peek
382      * if fetchall is on).
383      *
384      * The result of being unable to peek is that if there's
385      * any kind of transient error (DNS lookup failure, or
386      * sendmail refusing delivery due to process-table limits)
387      * the message will be marked "seen" on the server without
388      * having been delivered.  This is not a big problem if
389      * fetchmail is running in foreground, because the user
390      * will see a "skipped" message when it next runs and get
391      * clued in.
392      *
393      * But in daemon mode this leads to the message
394      * being silently ignored forever.  This is not
395      * acceptable.
396      *
397      * We compensate for this by checking the error
398      * count from the previous pass and forcing all
399      * messages to be considered new if it's nonzero.
400      */
401     force_retrieval = !peek_capable && (ctl->errcount > 0);
402
403     for (num = 1; num <= count; num++)
404     {
405         flag suppress_delete = FALSE;
406         flag suppress_forward = FALSE;
407         flag suppress_readbody = FALSE;
408         flag retained = FALSE;
409         int msgcode = MSGLEN_UNKNOWN;
410
411         /* check if the message is old
412          * Note: the size of the message may not be known here */
413         if (ctl->fetchall || force_retrieval) {
414             /* empty */
415         } else { 
416             if (ctl->server.base_protocol->is_old && (ctl->server.base_protocol->is_old)(mailserver_socket,ctl,num)) {
417                     msgcode = MSGLEN_OLD;
418             }
419         }
420         if (msgcode == MSGLEN_OLD)
421         {
422             /*
423              * To avoid flooding the logs when using --keep, report
424              * skipping for old messages only when --flush is on.
425              */
426             if (outlevel > O_SILENT && ctl->flush)
427             {
428                 report_build(stdout, 
429                              GT_("skipping message %s@%s:%d"),
430                              ctl->remotename, ctl->server.truename, num);
431             }
432
433             goto flagthemail;
434         }
435
436         if (ctl->server.base_protocol->getpartialsizes && NUM_NONZERO(fetchsizelimit) &&
437             lastnum < num)
438         {
439             /* Instead of getting the sizes of all mails at the start, we get
440              * the sizes in blocks of fetchsizelimit. This leads to better
441              * performance when there are too many mails (say, 10000) in
442              * the mailbox and either we are not getting all the mails at
443              * one go (--fetchlimit 100) or there is a frequent socket
444              * error while just getting the sizes of all mails! */
445
446             int i;
447             int oldstage = stage;
448             firstnum = num;
449             lastnum = num + fetchsizelimit - 1;
450             if (lastnum > count)
451                 lastnum = count;
452             for (i = 0; i < fetchsizelimit; i++)
453                 (*msgsizes)[i] = 0;
454
455             stage = STAGE_GETSIZES;
456             err = (ctl->server.base_protocol->getpartialsizes)(mailserver_socket, num, lastnum, *msgsizes);
457             if (err != 0) {
458                 return err;
459             }
460             stage = oldstage;
461         }
462
463         msgsize = *msgsizes ? (*msgsizes)[num-firstnum] : 0;
464
465         /* check if the message is oversized */
466         if (NUM_NONZERO(ctl->limit) && (msgsize > ctl->limit))
467             msgcode = MSGLEN_TOOLARGE;
468 /*      else if (msgsize == 512)
469             msgcode = MSGLEN_OLD;  (hmh) sample code to skip message */
470
471         if (msgcode < 0)
472         {
473             if (msgcode == MSGLEN_TOOLARGE)
474             {
475                 mark_oversized(ctl, msgsize);
476                 if (!ctl->limitflush)
477                     suppress_delete = TRUE;
478             }
479             if (outlevel > O_SILENT)
480             {
481                 /* old messages are already handled above */
482                 report_build(stdout, 
483                              GT_("skipping message %s@%s:%d (%d octets)"),
484                              ctl->remotename, ctl->server.truename, num,
485                              msgsize);
486                 switch (msgcode)
487                 {
488                 case MSGLEN_INVALID:
489                     /*
490                      * Invalid lengths are produced by Post Office/NT's
491                      * annoying habit of randomly prepending bogus
492                      * LIST items of length -1.  Patrick Audley
493                      * <paudley@pobox.com> tells us: LIST shows a
494                      * size of -1, RETR and TOP return "-ERR
495                      * System error - couldn't open message", and
496                      * DELE succeeds but doesn't actually delete
497                      * the message.
498                      */
499                     report_build(stdout, GT_(" (length -1)"));
500                     break;
501                 case MSGLEN_TOOLARGE:
502                     report_build(stdout, GT_(" (oversized)"));
503                     break;
504                 }
505             }
506         }
507         else
508         {
509           /* XXX FIXME: make this one variable, wholesize and
510              separatefetchbody query the same variable just with
511              inverted logic */
512             flag wholesize = !ctl->server.base_protocol->fetch_body;
513             flag separatefetchbody = (ctl->server.base_protocol->fetch_body) ? TRUE : FALSE;
514
515             /* request a message */
516             err = (ctl->server.base_protocol->fetch_headers)(mailserver_socket,ctl,num, &len);
517             if (err == PS_TRANSIENT)    /* server is probably Exchange */
518             {
519                 report(stdout,
520                              GT_("couldn't fetch headers, message %s@%s:%d (%d octets)\n"),
521                              ctl->remotename, ctl->server.truename, num,
522                              msgsize);
523                 continue;
524             }
525             else if (err != 0)
526                 return(err);
527
528             /* -1 means we didn't see a size in the response */
529             if (len == -1)
530             {
531                 len = msgsize;
532                 wholesize = TRUE;
533             }
534
535             if (outlevel > O_SILENT)
536             {
537                 report_build(stdout, GT_("reading message %s@%s:%d of %d"),
538                              ctl->remotename, ctl->server.truename,
539                              num, count);
540
541                 if (len > 0)
542                     report_build(stdout, wholesize ? GT_(" (%d octets)")
543                                  : GT_(" (%d header octets)"), len);
544                 if (want_progress()) {
545                     /* flush and add a blank to append ticker dots */
546                     report_flush(stdout);
547                     putchar(' ');
548                 }
549             }
550
551             /* 
552              * Read the message headers and ship them to the
553              * output sink.  
554              */
555             err = readheaders(mailserver_socket, len, msgsize,
556                              ctl, num,
557                              /* pass the suppress_readbody flag only if the underlying
558                               * protocol does not fetch the body separately */
559                              separatefetchbody ? 0 : &suppress_readbody);
560
561             if (err == PS_RETAINED)
562                 suppress_forward = suppress_delete = retained = TRUE;
563             else if (err == PS_TRANSIENT)
564                 suppress_delete = suppress_forward = TRUE;
565             else if (err == PS_REFUSED)
566                 suppress_forward = TRUE;
567             else if (err)
568                 return(err);
569
570             /* tell server we got it OK and resynchronize */
571             if (separatefetchbody && ctl->server.base_protocol->trail)
572             {
573                 err = eat_trailer(mailserver_socket, ctl);
574                 if (err) return(err);
575             }
576
577             /* do not read the body which is not being forwarded only if
578              * the underlying protocol allows the body to be fetched
579              * separately */
580             if (separatefetchbody && suppress_forward)
581                 suppress_readbody = TRUE;
582
583             /* 
584              * If we're using IMAP4 or something else that
585              * can fetch headers separately from bodies,
586              * it's time to request the body now.  This
587              * fetch may be skipped if we got an anti-spam
588              * or other PS_REFUSED error response during
589              * readheaders.
590              */
591             if (!suppress_readbody)
592             {
593                 if (separatefetchbody)
594                 {
595                     len = -1;
596                     if ((err=(ctl->server.base_protocol->fetch_body)(mailserver_socket,ctl,num,&len))) {
597                         if (err == PS_ERROR && ctl->server.retrieveerror) {
598                             /*
599                              * Mark a message with a protocol error as seen.
600                              * This can be used to see which messages we've attempted
601                              * to download, but failed.
602                              */
603                             if (ctl->server.retrieveerror == RE_MARKSEEN) {
604                                 if ((ctl->server.base_protocol->mark_seen)(mailserver_socket,ctl,num)) {
605                                     return(err);
606                                 }
607                             }
608
609                             if (ctl->server.retrieveerror != RE_ABORT) {
610                                 /*
611                                  * Do not abort download session.  Continue with the next message.
612                                  *
613                                  * Prevents a malformed message from blocking all other messages
614                                  * behind it in the mailbox from being downloaded.
615                                  *
616                                  * Reconnect to SMTP to force this incomplete message to be dropped.
617                                  * Required because we've already begun the DATA portion of the
618                                  * interaction with the SMTP server (commands are ignored/
619                                  * considered part of the message data).
620                                  */
621                                 abort_message_sink(ctl);
622
623                                 // Ensure we don't delete the failed message from the server.
624                                 suppress_delete = TRUE;
625
626                                 // Bookkeeping required before next message can be downloaded.
627                                 goto flagthemail;
628                             }
629                         }
630
631                         return(err);
632                     }
633
634                     /*
635                      * Work around a bug in Novell's
636                      * broken GroupWise IMAP server;
637                      * its body FETCH response is missing
638                      * the required length for the data
639                      * string.  This violates RFC2060.
640                      */
641                     if (len == -1)
642                         len = msgsize - msgblk.msglen;
643                     if (!wholesize) {
644                         if (outlevel > O_SILENT)
645                             report_build(stdout,
646                                     GT_(" (%d body octets)"), len);
647                         if (want_progress()) {
648                             report_flush(stdout);
649                             putchar(' ');
650                         }
651                     }
652                 }
653
654                 /* process the body now */
655                 err = readbody(mailserver_socket,
656                               ctl,
657                               !suppress_forward,
658                               len);
659
660                 if (err == PS_TRANSIENT)
661                     suppress_delete = suppress_forward = TRUE;
662                 else if (err)
663                     return(err);
664
665                 /* tell server we got it OK and resynchronize */
666                 if (ctl->server.base_protocol->trail) {
667                     err = eat_trailer(mailserver_socket, ctl);
668                     if (err) return(err);
669                 }
670             }
671
672             /* count # messages forwarded on this pass */
673             if (!suppress_forward)
674                 (*dispatches)++;
675
676             /*
677              * Check to see if the numbers matched?
678              *
679              * Yes, some servers foo this up horribly.
680              * All IMAP servers seem to get it right, and
681              * so does Eudora QPOP at least in 2.xx
682              * versions.
683              *
684              * Microsoft Exchange gets it completely
685              * wrong, reporting compressed rather than
686              * actual sizes (so the actual length of
687              * message is longer than the reported size).
688              * Another fine example of Microsoft brain death!
689              *
690              * Some older POP servers, like the old UCB
691              * POP server and the pre-QPOP QUALCOMM
692              * versions, report a longer size in the LIST
693              * response than actually gets shipped up.
694              * It's unclear what is going on here, as the
695              * QUALCOMM server (at least) seems to be
696              * reporting the on-disk size correctly.
697              *
698              * qmail-pop3d also goofs up message sizes and does not
699              * count the line end characters properly.
700              */
701             if (msgblk.msglen != msgsize)
702             {
703                 if (outlevel >= O_DEBUG)
704                     report(stdout,
705                            GT_("message %s@%s:%d was not the expected length (%d actual != %d expected)\n"),
706                            ctl->remotename, ctl->server.truename, num,
707                            msgblk.msglen, msgsize);
708             }
709
710             /* end-of-message processing starts here */
711             if (!close_sink(ctl, &msgblk, !suppress_forward))
712             {
713                 ctl->errcount++;
714                 suppress_delete = TRUE;
715             }
716             if (!retained)
717                 (*fetches)++;
718         }
719
720 flagthemail:
721         /*
722          * At this point in flow of control,
723          * either we've bombed on a protocol error
724          * or had delivery refused by the SMTP server
725          * or we've seen `accepted for delivery' and the message is shipped.
726          * It's safe to mark the message seen and delete it on the server now.
727          */
728
729         /* in softbounce mode, suppress deletion and marking as seen */
730         if (suppress_forward)
731             suppress_delete = suppress_delete || run.softbounce;
732
733         /* maybe we delete this message now? */
734         if (retained)
735         {
736             if (outlevel > O_SILENT) 
737                 report_complete(stdout, GT_(" retained\n"));
738         }
739         else if (ctl->server.base_protocol->delete_msg
740                  && !suppress_delete
741                  && ((msgcode >= 0 && !ctl->keep)
742                      || (msgcode == MSGLEN_OLD && ctl->flush)
743                      || (msgcode == MSGLEN_TOOLARGE && ctl->limitflush)))
744         {
745             (*deletions)++;
746             if (outlevel > O_SILENT) 
747                 report_complete(stdout, GT_(" flushed\n"));
748             err = (ctl->server.base_protocol->delete_msg)(mailserver_socket, ctl, num);
749             if (err != 0)
750                 return(err);
751         }
752         else
753         {
754             /*
755              * To avoid flooding the logs when using --keep, report
756              * skipping of new messages only.
757              */
758             if (outlevel > O_SILENT && msgcode != MSGLEN_OLD)
759             report_complete(stdout, GT_(" not flushed\n"));
760
761             /* maybe we mark this message as seen now? */
762             if (ctl->server.base_protocol->mark_seen
763                 && !suppress_delete
764                 && (msgcode >= 0 && ctl->keep))
765             {
766                 err = (ctl->server.base_protocol->mark_seen)(mailserver_socket, ctl, num);
767                 if (err != 0)
768                     return(err);
769             }
770         }
771
772         /* perhaps this as many as we're ready to handle */
773         if (maxfetch && maxfetch <= *fetches && num < count)
774         {
775             int remcount = count - (*fetches - initialfetches);
776             report(stdout,
777                    ngettext("fetchlimit %d reached; %d message left on server %s account %s\n",
778                             "fetchlimit %d reached; %d messages left on server %s account %s\n", remcount),
779                    maxfetch, remcount, ctl->server.truename, ctl->remotename);
780             return(PS_MAXFETCH);
781         }
782     } /* for (num = 1; num <= count; num++) */
783
784     return(PS_SUCCESS);
785 }
786
787 /* retrieve messages from server using given protocol method table */
788 static int do_session(
789         /* parsed options with merged-in defaults */
790         struct query *ctl,
791         /* protocol method table */
792         const struct method *proto,
793         /* maximum number of messages to fetch */
794         const int maxfetch)
795 {
796     static int *msgsizes;
797     volatile int err, mailserver_socket = -1;   /* pacifies -Wall */
798     int tmperr;
799     int deletions = 0, js;
800     const char *msg;
801     SIGHANDLERTYPE alrmsave;
802
803     ctl->server.base_protocol = proto;
804
805     msgsizes = NULL;
806     pass = 0;
807     err = 0;
808     init_transact(proto);
809
810     /* set up the server-nonresponse timeout */
811     alrmsave = set_signal_handler(SIGALRM, timeout_handler);
812     mytimeout = ctl->server.timeout;
813
814     if ((js = sigsetjmp(restart,1)))
815     {
816         /* exception caught */
817         sigset_t        allsigs;
818
819         sigfillset(&allsigs);
820         sigprocmask(SIG_UNBLOCK, &allsigs, NULL);
821
822         if (ai0) {
823             fm_freeaddrinfo(ai0); ai0 = NULL;
824         }
825
826         if (ai1) {
827             fm_freeaddrinfo(ai1); ai1 = NULL;
828         }
829         
830         if (js == THROW_TIMEOUT)
831         {
832             if (phase == OPEN_WAIT)
833                 report(stdout,
834                        GT_("timeout after %d seconds waiting to connect to server %s.\n"),
835                        ctl->server.timeout, ctl->server.pollname);
836             else if (phase == SERVER_WAIT)
837                 report(stdout,
838                        GT_("timeout after %d seconds waiting for server %s.\n"),
839                        ctl->server.timeout, ctl->server.pollname);
840             else if (phase == FORWARDING_WAIT)
841                 report(stdout,
842                        GT_("timeout after %d seconds waiting for %s.\n"),
843                        ctl->server.timeout,
844                        ctl->mda ? "MDA" : "SMTP");
845             else if (phase == LISTENER_WAIT)
846                 report(stdout,
847                        GT_("timeout after %d seconds waiting for listener to respond.\n"), ctl->server.timeout);
848             else
849                 report(stdout, 
850                        GT_("timeout after %d seconds.\n"), ctl->server.timeout);
851
852             /*
853              * If we've exceeded our threshold for consecutive timeouts, 
854              * try to notify the user, then mark the connection wedged.
855              * Don't do this if the connection can idle, though; idle
856              * timeouts just mean the frequency of mail is low.
857              */
858             if (timeoutcount > MAX_TIMEOUTS 
859                 && !open_warning_by_mail(ctl))
860             {
861                 stuff_warning(iana_charset, ctl,
862                               GT_("Subject: fetchmail sees repeated timeouts"));
863                 stuff_warning(NULL, ctl, "%s", "");
864                 stuff_warning(NULL, ctl,
865                               GT_("Fetchmail saw more than %d timeouts while attempting to get mail from %s@%s.\n"), 
866                               MAX_TIMEOUTS,
867                               ctl->remotename, ctl->server.truename);
868                 stuff_warning(NULL, ctl, 
869     GT_("This could mean that your mailserver is stuck, or that your SMTP\n" \
870     "server is wedged, or that your mailbox file on the server has been\n" \
871     "corrupted by a server error.  You can run `fetchmail -v -v' to\n" \
872     "diagnose the problem.\n\n" \
873     "Fetchmail won't poll this mailbox again until you restart it.\n"));
874                 close_warning_by_mail(ctl, (struct msgblk *)NULL);
875                 ctl->wedged = TRUE;
876             }
877         }
878
879         err = PS_SOCKET;
880         goto cleanUp;
881     }
882     else
883     {
884         /* sigsetjmp returned zero -> normal operation */
885         char buf[MSGBUFSIZE+1], *realhost;
886         int count, newm, bytes;
887         int fetches, dispatches, oldphase;
888         struct idlist *idp;
889
890         /* execute pre-initialization command, if any */
891         if (ctl->preconnect && (err = system(ctl->preconnect)))
892         {
893             if (WIFSIGNALED(err))
894                 report(stderr,
895                         GT_("pre-connection command terminated with signal %d\n"), WTERMSIG(err));
896             else
897                 report(stderr,
898                         GT_("pre-connection command failed with status %d\n"), WEXITSTATUS(err));
899             err = PS_SYNTAX;
900             goto closeUp;
901         }
902
903         /* open a socket to the mail server */
904         oldphase = phase;
905         phase = OPEN_WAIT;
906         set_timeout(mytimeout);
907
908 #ifdef HAVE_PKG_hesiod
909         /* If either the pollname or vianame are "hesiod" we want to
910            lookup the user's hesiod pobox host */
911         if (!strcasecmp(ctl->server.queryname, "hesiod")) {
912             struct hes_postoffice *hes_p;
913             hes_p = hes_getmailhost(ctl->remotename);
914             if (hes_p != NULL && strcmp(hes_p->po_type, "POP") == 0) {
915                  free(ctl->server.queryname);
916                  ctl->server.queryname = xstrdup(hes_p->po_host);
917                  if (ctl->server.via)
918                      free(ctl->server.via);
919                  ctl->server.via = xstrdup(hes_p->po_host);
920             } else {
921                  report(stderr,
922                         GT_("couldn't find HESIOD pobox for %s\n"),
923                         ctl->remotename);
924             }
925         }
926 #endif /* HESIOD */
927
928         /*
929          * Canonicalize the server truename for later use.  This also
930          * functions as a probe for whether the mailserver is accessible.
931          * We try it on each poll cycle until we get a result.  This way,
932          * fetchmail won't fail if started up when the network is inaccessible.
933          */
934         if (ctl->server.dns && !ctl->server.trueaddr)
935         {
936             if (ctl->server.lead_server)
937             {
938                 char    *leadname = ctl->server.lead_server->truename;
939
940                 /* prevent core dump from ill-formed or duplicate entry */
941                 if (!leadname)
942                 {
943                     report(stderr, GT_("Lead server has no name.\n"));
944                     err = PS_DNS;
945                     set_timeout(0);
946                     phase = oldphase;
947                     goto closeUp;
948                 }
949
950                 xfree(ctl->server.truename);
951                 ctl->server.truename = xstrdup(leadname);
952             }
953             else
954             {
955                 struct addrinfo hints, *res;
956                 int error;
957
958                 memset(&hints, 0, sizeof(hints));
959                 hints.ai_socktype = SOCK_STREAM;
960                 hints.ai_family = AF_UNSPEC;
961                 hints.ai_flags = AI_CANONNAME;
962 #ifdef AI_ADDRCONFIG
963                 hints.ai_flags |= AI_ADDRCONFIG;
964 #endif
965
966                 error = fm_getaddrinfo(ctl->server.queryname, NULL, &hints, &res);
967                 if (error)
968                 {
969                     report(stderr,
970                            GT_("couldn't find canonical DNS name of %s (%s): %s\n"),
971                            ctl->server.pollname, ctl->server.queryname,
972                            gai_strerror(error));
973                     err = PS_DNS;
974                     set_timeout(0);
975                     phase = oldphase;
976                     goto closeUp;
977                 }
978                 else
979                 {
980                     xfree(ctl->server.truename);
981                     /* Older FreeBSD versions return NULL in ai_canonname
982                      * if they cannot canonicalize, rather than copying
983                      * the queryname here, as IEEE Std 1003.1-2001
984                      * requires. Work around NULL. */
985                     if (res->ai_canonname != NULL) {
986                         ctl->server.truename = xstrdup(res->ai_canonname);
987                     } else {
988                         ctl->server.truename = xstrdup(ctl->server.queryname);
989                     }
990                     ctl->server.trueaddr = (struct sockaddr *)xmalloc(res->ai_addrlen);
991                     ctl->server.trueaddr_len = res->ai_addrlen;
992                     memcpy(ctl->server.trueaddr, res->ai_addr, res->ai_addrlen);
993                     fm_freeaddrinfo(res);
994                 }
995             }
996         }
997
998         realhost = ctl->server.via ? ctl->server.via : ctl->server.pollname;
999
1000         /* allow time for the port to be set up if we have a plugin */
1001         if (ctl->server.plugin)
1002             (void)sleep(1);
1003         if ((mailserver_socket = SockOpen(realhost, 
1004                              ctl->server.service ? ctl->server.service : ( ctl->use_ssl ? ctl->server.base_protocol->sslservice : ctl->server.base_protocol->service ),
1005                              ctl->server.plugin, &ai0)) == -1)
1006         {
1007             char        errbuf[BUFSIZ];
1008             int err_no = errno;
1009             /*
1010              * Avoid generating a bogus error every poll cycle when we're
1011              * in daemon mode but the connection to the outside world
1012              * is down.
1013              */
1014             if (!((err_no == EHOSTUNREACH || err_no == ENETUNREACH) 
1015                   && run.poll_interval))
1016             {
1017                 report_build(stderr, GT_("%s connection to %s failed"), 
1018                              ctl->server.base_protocol->name, ctl->server.pollname);
1019                     strlcpy(errbuf, strerror(err_no), sizeof(errbuf));
1020                 report_complete(stderr, ": %s\n", errbuf);
1021             }
1022             err = PS_SOCKET;
1023             set_timeout(0);
1024             phase = oldphase;
1025             goto closeUp;
1026         }
1027
1028 #ifdef SSL_ENABLE
1029         /* Save the socket opened. Useful if Fetchmail hangs on SSLOpen 
1030          * because the socket can be closed.
1031          */
1032         mailserver_socket_temp = mailserver_socket;
1033         set_timeout(mytimeout);
1034
1035         /* perform initial SSL handshake on open connection */
1036         if (ctl->use_ssl &&
1037                 SSLOpen(mailserver_socket, ctl->sslcert, ctl->sslkey,
1038                     ctl->sslproto, ctl->sslcertck,
1039                     ctl->sslcertfile, ctl->sslcertpath,
1040                     ctl->sslfingerprint, ctl->sslcommonname ?
1041                     ctl->sslcommonname : realhost, ctl->server.pollname,
1042                     &ctl->remotename) == -1)
1043         {
1044             report(stderr, GT_("SSL connection failed.\n"));
1045             err = PS_SOCKET;
1046             goto cleanUp;
1047         }
1048         
1049         /* Fetchmail didn't hang on SSLOpen, 
1050          * then no need to set mailserver_socket_temp 
1051          */
1052         mailserver_socket_temp = -1;
1053 #endif
1054         
1055         /* A timeout is still defined before SSLOpen, 
1056          * then Fetchmail hanging on SSLOpen is handled.
1057          */
1058         set_timeout(0);
1059         phase = oldphase;
1060
1061 #ifdef KERBEROS_V5
1062         if (ctl->server.authenticate == A_KERBEROS_V5)
1063         {
1064             set_timeout(mytimeout);
1065             err = kerberos5_auth(mailserver_socket, ctl->server.truename);
1066             set_timeout(0);
1067             if (err != 0)
1068                 goto cleanUp;
1069         }
1070 #endif /* KERBEROS_V5 */
1071
1072         /* accept greeting message from mail server */
1073         err = (ctl->server.base_protocol->parse_response)(mailserver_socket, buf);
1074         if (err != 0)
1075             goto cleanUp;
1076
1077         /* try to get authorized to fetch mail */
1078         stage = STAGE_GETAUTH;
1079         if (ctl->server.base_protocol->getauth)
1080         {
1081             set_timeout(mytimeout);
1082             err = (ctl->server.base_protocol->getauth)(mailserver_socket, ctl, buf);
1083             set_timeout(0);
1084
1085             if (err != 0)
1086             {
1087                 if (err == PS_LOCKBUSY)
1088                     report(stderr, GT_("Lock-busy error on %s@%s\n"),
1089                           ctl->remotename,
1090                           ctl->server.truename);
1091                 else if (err == PS_SERVBUSY)
1092                     report(stderr, GT_("Server busy error on %s@%s\n"),
1093                           ctl->remotename,
1094                           ctl->server.truename);
1095                 else if (err == PS_AUTHFAIL)
1096                 {
1097                     report(stderr, GT_("Authorization failure on %s@%s%s\n"), 
1098                            ctl->remotename,
1099                            ctl->server.truename,
1100                            (ctl->wehaveauthed ? GT_(" (previously authorized)") : "")
1101                         );
1102                     if (ctl->server.authenticate == A_ANY && !ctl->wehaveauthed) {
1103                         report(stderr, GT_("For help, see http://www.fetchmail.info/fetchmail-FAQ.html#R15\n"));
1104                     }
1105
1106                     /*
1107                      * If we're running in background, try to mail the
1108                      * calling user a heads-up about the authentication 
1109                      * failure once it looks like this isn't a fluke 
1110                      * due to the server being temporarily inaccessible.
1111                      * When we get third succesive failure, we notify the user
1112                      * but only if we haven't already managed to get
1113                      * authorization.  After that, once we get authorization
1114                      * we let the user know service is restored.
1115                      */
1116                     if (run.poll_interval
1117                         && !ctl->wehavesentauthnote
1118                         && ((ctl->wehaveauthed && ++ctl->authfailcount >= 10)
1119                             || (!ctl->wehaveauthed && ++ctl->authfailcount >= 3))
1120                         && !open_warning_by_mail(ctl))
1121                     {
1122                         ctl->wehavesentauthnote = 1;
1123                         stuff_warning(iana_charset, ctl,
1124                                       GT_("Subject: fetchmail authentication failed on %s@%s"),
1125                             ctl->remotename, ctl->server.truename);
1126                         stuff_warning(NULL, ctl, "%s", "");
1127                         stuff_warning(NULL, ctl,
1128                                       GT_("Fetchmail could not get mail from %s@%s.\n"), 
1129                                       ctl->remotename,
1130                                       ctl->server.truename);
1131                         if (ctl->wehaveauthed) {
1132                             stuff_warning(NULL, ctl, GT_("\
1133 The attempt to get authorization failed.\n\
1134 Since we have already succeeded in getting authorization for this\n\
1135 connection, this is probably another failure mode (such as busy server)\n\
1136 that fetchmail cannot distinguish because the server didn't send a useful\n\
1137 error message."));
1138                             stuff_warning(NULL, ctl, GT_("\
1139 \n\
1140 However, if you HAVE changed your account details since starting the\n\
1141 fetchmail daemon, you need to stop the daemon, change your configuration\n\
1142 of fetchmail, and then restart the daemon.\n\
1143 \n\
1144 The fetchmail daemon will continue running and attempt to connect\n\
1145 at each cycle.  No future notifications will be sent until service\n\
1146 is restored."));
1147                         } else {
1148                             stuff_warning(NULL, ctl, GT_("\
1149 The attempt to get authorization failed.\n\
1150 This probably means your password is invalid, but some servers have\n\
1151 other failure modes that fetchmail cannot distinguish from this\n\
1152 because they don't send useful error messages on login failure.\n\
1153 \n\
1154 The fetchmail daemon will continue running and attempt to connect\n\
1155 at each cycle.  No future notifications will be sent until service\n\
1156 is restored."));
1157                         }
1158                         close_warning_by_mail(ctl, (struct msgblk *)NULL);
1159                     }
1160                 }
1161                 else if (err == PS_REPOLL)
1162                 {
1163                   if (outlevel >= O_VERBOSE)
1164                     report(stderr, GT_("Repoll immediately on %s@%s\n"),
1165                            ctl->remotename,
1166                            ctl->server.truename);
1167                 }
1168                 else
1169                     report(stderr, GT_("Unknown login or authentication error on %s@%s\n"),
1170                            ctl->remotename,
1171                            ctl->server.truename);
1172                     
1173                 goto cleanUp;
1174             }
1175             else
1176             {
1177                 /*
1178                  * This connection has given us authorization at least once.
1179                  *
1180                  * There are dodgy server (clubinternet.fr for example) that
1181                  * give spurious authorization failures on patently good
1182                  * account/password details, then 5 minutes later let you in!
1183                  *
1184                  * This is meant to build in some tolerance of such nasty bits
1185                  * of work.
1186                  */
1187                 ctl->wehaveauthed = 1;
1188                 /*if (ctl->authfailcount >= 3)*/
1189                 if (ctl->wehavesentauthnote)
1190                 {
1191                     ctl->wehavesentauthnote = 0;
1192                     report(stderr,
1193                            GT_("Authorization OK on %s@%s\n"),
1194                            ctl->remotename,
1195                            ctl->server.truename);
1196                     if (!open_warning_by_mail(ctl))
1197                     {
1198                         stuff_warning(iana_charset, ctl,
1199                               GT_("Subject: fetchmail authentication OK on %s@%s"), 
1200                                       ctl->remotename, ctl->server.truename);
1201                         stuff_warning(NULL, ctl, "%s", "");
1202                         stuff_warning(NULL, ctl,
1203                               GT_("Fetchmail was able to log into %s@%s.\n"), 
1204                                       ctl->remotename,
1205                                       ctl->server.truename);
1206                         stuff_warning(NULL, ctl, 
1207                                       GT_("Service has been restored.\n"));
1208                         close_warning_by_mail(ctl, (struct msgblk *)NULL);
1209                     
1210                     }
1211                 }
1212                 /*
1213                  * Reporting only after the first three
1214                  * consecutive failures, or ten consecutive
1215                  * failures after we have managed to get
1216                  * authorization.
1217                  */
1218                 ctl->authfailcount = 0;
1219             }
1220         }
1221
1222         ctl->errcount = fetches = 0;
1223
1224         /* now iterate over each folder selected */
1225         for (idp = ctl->mailboxes; idp; idp = idp->next)
1226         {
1227             ctl->folder = idp->id;
1228             pass = 0;
1229             do {
1230                 dispatches = 0;
1231                 ++pass;
1232
1233                 /* reset timeout, in case we did an IDLE */
1234                 mytimeout = ctl->server.timeout;
1235
1236                 if (outlevel >= O_DEBUG)
1237                 {
1238                     if (idp->id)
1239                         report(stdout, GT_("selecting or re-polling folder %s\n"), idp->id);
1240                     else
1241                         report(stdout, GT_("selecting or re-polling default folder\n"));
1242                 }
1243
1244                 /* compute # of messages and number of new messages waiting */
1245                 stage = STAGE_GETRANGE;
1246                 err = (ctl->server.base_protocol->getrange)(mailserver_socket, ctl, idp->id, &count, &newm, &bytes);
1247                 if (err != 0)
1248                     goto cleanUp;
1249
1250                 /* show user how many messages we downloaded */
1251                 if (idp->id)
1252                     (void) snprintf(buf, sizeof(buf),
1253                                    GT_("%s at %s (folder %s)"),
1254                                    ctl->remotename, ctl->server.pollname, idp->id);
1255                 else
1256                     (void) snprintf(buf, sizeof(buf), GT_("%s at %s"),
1257                                    ctl->remotename, ctl->server.pollname);
1258                 if (outlevel > O_SILENT)
1259                 {
1260                     if (count == -1)            /* only used for ETRN */
1261                         report(stdout, GT_("Polling %s\n"), ctl->server.truename);
1262                     else if (count != 0)
1263                     {
1264                         if (newm != -1 && (count - newm) > 0)
1265                             report_build(stdout, ngettext("%d message (%d %s) for %s", "%d messages (%d %s) for %s", (unsigned long)count),
1266                                   count,
1267                                   count - newm, 
1268                                   ngettext("seen", "seen", (unsigned long)count-newm),
1269                                   buf);
1270                         else
1271                             report_build(stdout, ngettext("%d message for %s",
1272                                                           "%d messages for %s",
1273                                                           count), 
1274                                   count, buf);
1275                         if (bytes == -1)
1276                             report_complete(stdout, ".\n");
1277                         else
1278                             report_complete(stdout, GT_(" (%d octets).\n"), bytes);
1279                     }
1280                     else
1281                     {
1282                         /* these are pointless in normal daemon mode */
1283                         if (pass == 1 && (run.poll_interval == 0 || outlevel >= O_VERBOSE))
1284                             report(stdout, GT_("No mail for %s\n"), buf); 
1285                     }
1286                 }
1287
1288                 /* very important, this is where we leave the do loop */ 
1289                 if (count == 0)
1290                     break;
1291
1292                 if (check_only)
1293                 {
1294                     if (newm == -1 || ctl->fetchall)
1295                         newm = count;
1296                     fetches = newm;     /* set error status correctly */
1297                     /*
1298                      * There used to be a `goto noerror' here, but this
1299                      * prevented checking of multiple folders.  This
1300                      * comment is a reminder in case I introduced some
1301                      * subtle bug by removing it...
1302                      */
1303                 }
1304                 else if (count > 0)
1305                 {    
1306                     int         i;
1307
1308                     /*
1309                      * Don't trust the message count passed by the server.
1310                      * Without this check, it might be possible to do a
1311                      * DNS-spoofing attack that would pass back a ridiculous 
1312                      * count, and allocate a malloc area that would overlap
1313                      * a portion of the stack.
1314                      */
1315                     if ((unsigned)count > INT_MAX/sizeof(int))
1316                     {
1317                         report(stderr, GT_("bogus message count!"));
1318                         err = PS_PROTOCOL;
1319                         goto cleanUp;
1320                     }
1321
1322                     /* 
1323                      * We need the size of each message before it's
1324                      * loaded in order to pass it to the ESMTP SIZE
1325                      * option.  If the protocol has a getsizes method,
1326                      * we presume this means it doesn't get reliable
1327                      * sizes from message fetch responses.
1328                      *
1329                      * If the protocol supports getting sizes of subset of
1330                      * messages, we skip this step now.
1331                      */
1332                     if (proto->getsizes &&
1333                         !(proto->getpartialsizes && NUM_NONZERO(ctl->fetchsizelimit)))
1334                     {
1335                         xfree(msgsizes);
1336                         msgsizes = (int *)xmalloc(sizeof(int) * count);
1337                         for (i = 0; i < count; i++)
1338                             msgsizes[i] = 0;
1339
1340                         stage = STAGE_GETSIZES;
1341                         err = (proto->getsizes)(mailserver_socket, count, msgsizes);
1342                         if (err != 0)
1343                             goto cleanUp;
1344
1345                         if (bytes == -1)
1346                         {
1347                             bytes = 0;
1348                             for (i = 0; i < count; i++)
1349                                 bytes += msgsizes[i];
1350                         }
1351                     }
1352
1353                     /* read, forward, and delete messages */
1354                     stage = STAGE_FETCH;
1355
1356                     /* fetch in lockstep mode */
1357                     err = fetch_messages(mailserver_socket, ctl, 
1358                                          count, &msgsizes,
1359                                          maxfetch,
1360                                          &fetches, &dispatches, &deletions);
1361                     if (err != PS_SUCCESS && err != PS_MAXFETCH)
1362                         goto cleanUp;
1363
1364                     if (!check_only && ctl->skipped
1365                         && run.poll_interval > 0 && !nodetach)
1366                     {
1367                         clean_skipped_list(&ctl->skipped);
1368                         send_size_warnings(ctl);
1369                     }
1370                 }
1371
1372                 /* end-of-mailbox processing before we repoll or switch to another one */
1373                 if (ctl->server.base_protocol->end_mailbox_poll)
1374                 {
1375                     tmperr = (ctl->server.base_protocol->end_mailbox_poll)(mailserver_socket, ctl);
1376                     if (tmperr) {
1377                         err = tmperr;
1378                         goto cleanUp;
1379                     }
1380                 }
1381                 /* Return now if we have reached the fetchlimit */
1382                 if (maxfetch && maxfetch <= fetches)
1383                     goto no_error;
1384             } while
1385                   /*
1386                    * Only repoll if we either had some actual forwards
1387                    * or are idling for new mails and had no errors.
1388                    * Otherwise it is far too easy to get into infinite loops.
1389                    */
1390                   (ctl->server.base_protocol->retry && (dispatches || ctl->idle) && !ctl->errcount);
1391         }
1392
1393         /* XXX: From this point onwards, preserve err unless a new error has occurred */
1394
1395     no_error:
1396         /* PS_SUCCESS, PS_MAXFETCH: ordinary termination with no errors -- officially log out */
1397         stage = STAGE_LOGOUT;
1398         tmperr = (ctl->server.base_protocol->logout_cmd)(mailserver_socket, ctl);
1399         if (tmperr != PS_SUCCESS)
1400             err = tmperr;
1401         /*
1402          * Hmmmm...arguably this would be incorrect if we had fetches but
1403          * no dispatches (due to oversized messages, etc.)
1404          */
1405         else if (err == PS_SUCCESS && fetches == 0)
1406             err = PS_NOMAIL;
1407         /*
1408          * Close all SMTP delivery sockets.  For optimum performance
1409          * we'd like to hold them open til end of run, but (1) this
1410          * loses if our poll interval is longer than the MTA's
1411          * inactivity timeout, and (2) some MTAs (like smail) don't
1412          * deliver after each message, but rather queue up mail and
1413          * wait to actually deliver it until the input socket is
1414          * closed.
1415          *
1416          * don't send QUIT for ODMR case because we're acting as a
1417          * proxy between the SMTP server and client.
1418          */
1419         smtp_close(ctl, ctl->server.protocol != P_ODMR);
1420         cleanupSockClose(mailserver_socket);
1421         goto closeUp;
1422
1423     cleanUp:
1424         /* we only get here on error */
1425         if (err != 0 && err != PS_SOCKET && err != PS_REPOLL)
1426         {
1427             stage = STAGE_LOGOUT;
1428             (ctl->server.base_protocol->logout_cmd)(mailserver_socket, ctl);
1429         }
1430
1431         /* try to clean up all streams */
1432         release_sink(ctl);
1433         /*
1434          * Sending SMTP QUIT on signal is theoretically nice, but led
1435          * to a subtle bug.  If fetchmail was terminated by signal
1436          * while it was shipping message text, it would hang forever
1437          * waiting for a command acknowledge.  In theory we could
1438          * enable the QUIT only outside of the message send.  In
1439          * practice, we don't care.  All mailservers hang up on a
1440          * dropped TCP/IP connection anyway.
1441          */
1442         smtp_close(ctl, 0);
1443         if (mailserver_socket != -1) {
1444             cleanupSockClose(mailserver_socket);
1445         }
1446         /* If there was a connect timeout, the socket should be closed.
1447          * mailserver_socket_temp contains the socket to close.
1448          */
1449         if (mailserver_socket_temp != -1) {
1450             cleanupSockClose(mailserver_socket_temp);
1451             mailserver_socket_temp = -1;
1452         }
1453     }
1454
1455     /* no report on PS_AUTHFAIL */
1456     msg = NULL;
1457     switch (err)
1458     {
1459     case PS_SOCKET:
1460         msg = GT_("socket");
1461         break;
1462     case PS_SYNTAX:
1463         msg = GT_("missing or bad RFC822 header");
1464         break;
1465     case PS_IOERR:
1466         msg = GT_("MDA");
1467         break;
1468     case PS_ERROR:
1469         msg = GT_("client/server synchronization");
1470         break;
1471     case PS_PROTOCOL:
1472         msg = GT_("client/server protocol");
1473         break;
1474     case PS_LOCKBUSY:
1475         msg = GT_("lock busy on server");
1476         break;
1477     case PS_SMTP:
1478         msg = GT_("SMTP transaction");
1479         break;
1480     case PS_DNS:
1481         msg = GT_("DNS lookup");
1482         break;
1483     case PS_UNDEFINED:
1484         msg = GT_("undefined");
1485         break;
1486     }
1487     if (msg) {
1488         if (phase == FORWARDING_WAIT || phase == LISTENER_WAIT
1489                 || err == PS_SMTP)
1490             report(stderr, GT_("%s error while fetching from %s@%s and delivering to SMTP host %s\n"),
1491                     msg, ctl->remotename, ctl->server.pollname,
1492                     ctl->smtphost ? ctl->smtphost : GT_("unknown"));
1493         else
1494             report(stderr, GT_("%s error while fetching from %s@%s\n"),
1495                     msg, ctl->remotename, ctl->server.pollname);
1496     }
1497
1498 closeUp:
1499     xfree(msgsizes);
1500     ctl->folder = NULL;
1501
1502     /* execute wrapup command, if any */
1503     if (ctl->postconnect && (tmperr = system(ctl->postconnect)))
1504     {
1505         if (WIFSIGNALED(tmperr))
1506             report(stderr, GT_("post-connection command terminated with signal %d\n"), WTERMSIG(tmperr));
1507         else
1508             report(stderr, GT_("post-connection command failed with status %d\n"), WEXITSTATUS(tmperr));
1509         if (err == PS_SUCCESS)
1510             err = PS_SYNTAX;
1511     }
1512
1513     set_timeout(0); /* cancel any pending alarm */
1514     set_signal_handler(SIGALRM, alrmsave);
1515     return(err);
1516 }
1517
1518 /** retrieve messages from server using given protocol method table */
1519 int do_protocol(struct query *ctl /** parsed options with merged-in defaults */,
1520                 const struct method *proto /** protocol method table */)
1521 {
1522     int err;
1523
1524 #ifndef KERBEROS_V5
1525     if (ctl->server.authenticate == A_KERBEROS_V5)
1526     {
1527         report(stderr, GT_("Kerberos V5 support not linked.\n"));
1528         return(PS_ERROR);
1529     }
1530 #endif /* KERBEROS_V5 */
1531
1532     /* lacking methods, there are some options that may fail */
1533     if (!proto->is_old)
1534     {
1535         /* check for unsupported options */
1536         if (ctl->flush) {
1537             report(stderr,
1538                     GT_("Option --flush is not supported with %s\n"),
1539                     proto->name);
1540             return(PS_SYNTAX);
1541         }
1542         else if (ctl->fetchall) {
1543             report(stderr,
1544                     GT_("Option --all is not supported with %s\n"),
1545                     proto->name);
1546             return(PS_SYNTAX);
1547         }
1548     }
1549     if (!(proto->getsizes || proto->getpartialsizes)
1550             && NUM_SPECIFIED(ctl->limit))
1551     {
1552         report(stderr,
1553                 GT_("Option --limit is not supported with %s\n"),
1554                 proto->name);
1555         return(PS_SYNTAX);
1556     }
1557
1558     /*
1559      * If no expunge limit or we do expunges within the driver,
1560      * then just do one session, passing in any fetchlimit.
1561      */
1562     if ((ctl->keep && !ctl->flush) ||
1563         proto->retry || !NUM_SPECIFIED(ctl->expunge))
1564         return(do_session(ctl, proto, NUM_VALUE_OUT(ctl->fetchlimit)));
1565     /*
1566      * There's an expunge limit, and it isn't handled in the driver itself.
1567      * OK; do multiple sessions, each fetching a limited # of messages.
1568      * Stop if the total count of retrieved messages exceeds ctl->fetchlimit
1569      * (if it was nonzero).
1570      */
1571     else
1572     {
1573         int totalcount = 0; 
1574         int lockouts   = 0;
1575         int expunge    = NUM_VALUE_OUT(ctl->expunge);
1576         int fetchlimit = NUM_VALUE_OUT(ctl->fetchlimit);
1577
1578         do {
1579             if (fetchlimit > 0 && (expunge == 0 || expunge > fetchlimit - totalcount))
1580                 expunge = fetchlimit - totalcount;
1581             err = do_session(ctl, proto, expunge);
1582             totalcount += expunge;
1583             if (NUM_SPECIFIED(ctl->fetchlimit) && totalcount >= fetchlimit)
1584                 break;
1585             if (err != PS_LOCKBUSY)
1586                 lockouts = 0;
1587             else if (lockouts >= MAX_LOCKOUTS)
1588                 break;
1589             else /* err == PS_LOCKBUSY */
1590             {
1591                 /*
1592                  * Allow time for the server lock to release.  if we
1593                  * don't do this, we'll often hit a locked-mailbox
1594                  * condition and fail.
1595                  */
1596                 lockouts++;
1597                 sleep(3);
1598             }
1599         } while
1600             (err == PS_MAXFETCH || err == PS_LOCKBUSY);
1601
1602         return(err);
1603     }
1604 }
1605
1606
1607 /* driver.c ends here */