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