]> Pileus Git - ~andy/fetchmail/blob - driver.c
Merge branch 'master' into next
[~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                         return(err);
607                     /*
608                      * Work around a bug in Novell's
609                      * broken GroupWise IMAP server;
610                      * its body FETCH response is missing
611                      * the required length for the data
612                      * string.  This violates RFC2060.
613                      */
614                     if (len == -1)
615                         len = msgsize - msgblk.msglen;
616                     if (!wholesize) {
617                         if (outlevel > O_SILENT)
618                             report_build(stdout,
619                                     GT_(" (%d body octets)"), len);
620                         if (want_progress()) {
621                             report_flush(stdout);
622                             putchar(' ');
623                         }
624                     }
625                 }
626
627                 /* process the body now */
628                 err = readbody(mailserver_socket,
629                               ctl,
630                               !suppress_forward,
631                               len);
632
633                 if (err == PS_TRANSIENT)
634                     suppress_delete = suppress_forward = TRUE;
635                 else if (err)
636                     return(err);
637
638                 /* tell server we got it OK and resynchronize */
639                 if (ctl->server.base_protocol->trail) {
640                     err = eat_trailer(mailserver_socket, ctl);
641                     if (err) return(err);
642                 }
643             }
644
645             /* count # messages forwarded on this pass */
646             if (!suppress_forward)
647                 (*dispatches)++;
648
649             /*
650              * Check to see if the numbers matched?
651              *
652              * Yes, some servers foo this up horribly.
653              * All IMAP servers seem to get it right, and
654              * so does Eudora QPOP at least in 2.xx
655              * versions.
656              *
657              * Microsoft Exchange gets it completely
658              * wrong, reporting compressed rather than
659              * actual sizes (so the actual length of
660              * message is longer than the reported size).
661              * Another fine example of Microsoft brain death!
662              *
663              * Some older POP servers, like the old UCB
664              * POP server and the pre-QPOP QUALCOMM
665              * versions, report a longer size in the LIST
666              * response than actually gets shipped up.
667              * It's unclear what is going on here, as the
668              * QUALCOMM server (at least) seems to be
669              * reporting the on-disk size correctly.
670              *
671              * qmail-pop3d also goofs up message sizes and does not
672              * count the line end characters properly.
673              */
674             if (msgblk.msglen != msgsize)
675             {
676                 if (outlevel >= O_DEBUG)
677                     report(stdout,
678                            GT_("message %s@%s:%d was not the expected length (%d actual != %d expected)\n"),
679                            ctl->remotename, ctl->server.truename, num,
680                            msgblk.msglen, msgsize);
681             }
682
683             /* end-of-message processing starts here */
684             if (!close_sink(ctl, &msgblk, !suppress_forward))
685             {
686                 ctl->errcount++;
687                 suppress_delete = TRUE;
688             }
689             if (!retained)
690                 (*fetches)++;
691         }
692
693 flagthemail:
694         /*
695          * At this point in flow of control,
696          * either we've bombed on a protocol error
697          * or had delivery refused by the SMTP server
698          * or we've seen `accepted for delivery' and the message is shipped.
699          * It's safe to mark the message seen and delete it on the server now.
700          */
701
702         /* in softbounce mode, suppress deletion and marking as seen */
703         if (suppress_forward)
704             suppress_delete = suppress_delete || run.softbounce;
705
706         /* maybe we delete this message now? */
707         if (retained)
708         {
709             if (outlevel > O_SILENT) 
710                 report_complete(stdout, GT_(" retained\n"));
711         }
712         else if (ctl->server.base_protocol->delete_msg
713                  && !suppress_delete
714                  && ((msgcode >= 0 && !ctl->keep)
715                      || (msgcode == MSGLEN_OLD && ctl->flush)
716                      || (msgcode == MSGLEN_TOOLARGE && ctl->limitflush)))
717         {
718             (*deletions)++;
719             if (outlevel > O_SILENT) 
720                 report_complete(stdout, GT_(" flushed\n"));
721             err = (ctl->server.base_protocol->delete_msg)(mailserver_socket, ctl, num);
722             if (err != 0)
723                 return(err);
724         }
725         else
726         {
727             if (   (outlevel >= O_VERBOSE) ||
728                         /* To avoid flooding the syslog when using --keep,
729                          * report "Skipped message" only when:
730                          *  1) --verbose is on, or
731                          *  2) fetchmail does not use syslog, or
732                          *  3) the message was skipped for some other
733                          *     reason than just being old.
734                          */
735                    (outlevel > O_SILENT && (!run.use_syslog || msgcode != MSGLEN_OLD))
736                )
737             report_complete(stdout, GT_(" not flushed\n"));
738
739             /* maybe we mark this message as seen now? */
740             if (ctl->server.base_protocol->mark_seen
741                 && !suppress_delete
742                 && (msgcode >= 0 && ctl->keep))
743             {
744                 err = (ctl->server.base_protocol->mark_seen)(mailserver_socket, ctl, num);
745                 if (err != 0)
746                     return(err);
747             }
748         }
749
750         /* perhaps this as many as we're ready to handle */
751         if (maxfetch && maxfetch <= *fetches && num < count)
752         {
753             int remcount = count - (*fetches - initialfetches);
754             report(stdout,
755                    ngettext("fetchlimit %d reached; %d message left on server %s account %s\n",
756                             "fetchlimit %d reached; %d messages left on server %s account %s\n", remcount),
757                    maxfetch, remcount, ctl->server.truename, ctl->remotename);
758             return(PS_MAXFETCH);
759         }
760     } /* for (num = 1; num <= count; num++) */
761
762     return(PS_SUCCESS);
763 }
764
765 /* retrieve messages from server using given protocol method table */
766 static int do_session(
767         /* parsed options with merged-in defaults */
768         struct query *ctl,
769         /* protocol method table */
770         const struct method *proto,
771         /* maximum number of messages to fetch */
772         const int maxfetch)
773 {
774     static int *msgsizes;
775     volatile int err, mailserver_socket = -1;   /* pacifies -Wall */
776     int tmperr;
777     int deletions = 0, js;
778     const char *msg;
779     SIGHANDLERTYPE alrmsave;
780
781     ctl->server.base_protocol = proto;
782
783     msgsizes = NULL;
784     pass = 0;
785     err = 0;
786     init_transact(proto);
787
788     /* set up the server-nonresponse timeout */
789     alrmsave = set_signal_handler(SIGALRM, timeout_handler);
790     mytimeout = ctl->server.timeout;
791
792     if ((js = sigsetjmp(restart,1)))
793     {
794         /* exception caught */
795         sigset_t        allsigs;
796
797         sigfillset(&allsigs);
798         sigprocmask(SIG_UNBLOCK, &allsigs, NULL);
799
800         if (ai0) {
801             fm_freeaddrinfo(ai0); ai0 = NULL;
802         }
803
804         if (ai1) {
805             fm_freeaddrinfo(ai1); ai1 = NULL;
806         }
807         
808         if (js == THROW_TIMEOUT)
809         {
810             if (phase == OPEN_WAIT)
811                 report(stdout,
812                        GT_("timeout after %d seconds waiting to connect to server %s.\n"),
813                        ctl->server.timeout, ctl->server.pollname);
814             else if (phase == SERVER_WAIT)
815                 report(stdout,
816                        GT_("timeout after %d seconds waiting for server %s.\n"),
817                        ctl->server.timeout, ctl->server.pollname);
818             else if (phase == FORWARDING_WAIT)
819                 report(stdout,
820                        GT_("timeout after %d seconds waiting for %s.\n"),
821                        ctl->server.timeout,
822                        ctl->mda ? "MDA" : "SMTP");
823             else if (phase == LISTENER_WAIT)
824                 report(stdout,
825                        GT_("timeout after %d seconds waiting for listener to respond.\n"), ctl->server.timeout);
826             else
827                 report(stdout, 
828                        GT_("timeout after %d seconds.\n"), ctl->server.timeout);
829
830             /*
831              * If we've exceeded our threshold for consecutive timeouts, 
832              * try to notify the user, then mark the connection wedged.
833              * Don't do this if the connection can idle, though; idle
834              * timeouts just mean the frequency of mail is low.
835              */
836             if (timeoutcount > MAX_TIMEOUTS 
837                 && !open_warning_by_mail(ctl))
838             {
839                 stuff_warning(iana_charset, ctl,
840                               GT_("Subject: fetchmail sees repeated timeouts"));
841                 stuff_warning(NULL, ctl, "%s", "");
842                 stuff_warning(NULL, ctl,
843                               GT_("Fetchmail saw more than %d timeouts while attempting to get mail from %s@%s.\n"), 
844                               MAX_TIMEOUTS,
845                               ctl->remotename, ctl->server.truename);
846                 stuff_warning(NULL, ctl, 
847     GT_("This could mean that your mailserver is stuck, or that your SMTP\n" \
848     "server is wedged, or that your mailbox file on the server has been\n" \
849     "corrupted by a server error.  You can run `fetchmail -v -v' to\n" \
850     "diagnose the problem.\n\n" \
851     "Fetchmail won't poll this mailbox again until you restart it.\n"));
852                 close_warning_by_mail(ctl, (struct msgblk *)NULL);
853                 ctl->wedged = TRUE;
854             }
855         }
856
857         err = PS_SOCKET;
858         goto cleanUp;
859     }
860     else
861     {
862         /* sigsetjmp returned zero -> normal operation */
863         char buf[MSGBUFSIZE+1], *realhost;
864         int count, newm, bytes;
865         int fetches, dispatches, oldphase;
866         struct idlist *idp;
867
868         /* execute pre-initialization command, if any */
869         if (ctl->preconnect && (err = system(ctl->preconnect)))
870         {
871             if (WIFSIGNALED(err))
872                 report(stderr,
873                         GT_("pre-connection command terminated with signal %d\n"), WTERMSIG(err));
874             else
875                 report(stderr,
876                         GT_("pre-connection command failed with status %d\n"), WEXITSTATUS(err));
877             err = PS_SYNTAX;
878             goto closeUp;
879         }
880
881         /* open a socket to the mail server */
882         oldphase = phase;
883         phase = OPEN_WAIT;
884         set_timeout(mytimeout);
885
886 #ifdef HAVE_PKG_hesiod
887         /* If either the pollname or vianame are "hesiod" we want to
888            lookup the user's hesiod pobox host */
889         if (!strcasecmp(ctl->server.queryname, "hesiod")) {
890             struct hes_postoffice *hes_p;
891             hes_p = hes_getmailhost(ctl->remotename);
892             if (hes_p != NULL && strcmp(hes_p->po_type, "POP") == 0) {
893                  free(ctl->server.queryname);
894                  ctl->server.queryname = xstrdup(hes_p->po_host);
895                  if (ctl->server.via)
896                      free(ctl->server.via);
897                  ctl->server.via = xstrdup(hes_p->po_host);
898             } else {
899                  report(stderr,
900                         GT_("couldn't find HESIOD pobox for %s\n"),
901                         ctl->remotename);
902             }
903         }
904 #endif /* HESIOD */
905
906         /*
907          * Canonicalize the server truename for later use.  This also
908          * functions as a probe for whether the mailserver is accessible.
909          * We try it on each poll cycle until we get a result.  This way,
910          * fetchmail won't fail if started up when the network is inaccessible.
911          */
912         if (ctl->server.dns && !ctl->server.trueaddr)
913         {
914             if (ctl->server.lead_server)
915             {
916                 char    *leadname = ctl->server.lead_server->truename;
917
918                 /* prevent core dump from ill-formed or duplicate entry */
919                 if (!leadname)
920                 {
921                     report(stderr, GT_("Lead server has no name.\n"));
922                     err = PS_DNS;
923                     set_timeout(0);
924                     phase = oldphase;
925                     goto closeUp;
926                 }
927
928                 xfree(ctl->server.truename);
929                 ctl->server.truename = xstrdup(leadname);
930             }
931             else
932             {
933                 struct addrinfo hints, *res;
934                 int error;
935
936                 memset(&hints, 0, sizeof(hints));
937                 hints.ai_socktype = SOCK_STREAM;
938                 hints.ai_family = AF_UNSPEC;
939                 hints.ai_flags = AI_CANONNAME;
940 #ifdef AI_ADDRCONFIG
941                 hints.ai_flags |= AI_ADDRCONFIG;
942 #endif
943
944                 error = fm_getaddrinfo(ctl->server.queryname, NULL, &hints, &res);
945                 if (error)
946                 {
947                     report(stderr,
948                            GT_("couldn't find canonical DNS name of %s (%s): %s\n"),
949                            ctl->server.pollname, ctl->server.queryname,
950                            gai_strerror(error));
951                     err = PS_DNS;
952                     set_timeout(0);
953                     phase = oldphase;
954                     goto closeUp;
955                 }
956                 else
957                 {
958                     xfree(ctl->server.truename);
959                     /* Older FreeBSD versions return NULL in ai_canonname
960                      * if they cannot canonicalize, rather than copying
961                      * the queryname here, as IEEE Std 1003.1-2001
962                      * requires. Work around NULL. */
963                     if (res->ai_canonname != NULL) {
964                         ctl->server.truename = xstrdup(res->ai_canonname);
965                     } else {
966                         ctl->server.truename = xstrdup(ctl->server.queryname);
967                     }
968                     ctl->server.trueaddr = (struct sockaddr *)xmalloc(res->ai_addrlen);
969                     ctl->server.trueaddr_len = res->ai_addrlen;
970                     memcpy(ctl->server.trueaddr, res->ai_addr, res->ai_addrlen);
971                     fm_freeaddrinfo(res);
972                 }
973             }
974         }
975
976         realhost = ctl->server.via ? ctl->server.via : ctl->server.pollname;
977
978         /* allow time for the port to be set up if we have a plugin */
979         if (ctl->server.plugin)
980             (void)sleep(1);
981         if ((mailserver_socket = SockOpen(realhost, 
982                              ctl->server.service ? ctl->server.service : ( ctl->use_ssl ? ctl->server.base_protocol->sslservice : ctl->server.base_protocol->service ),
983                              ctl->server.plugin, &ai0)) == -1)
984         {
985             char        errbuf[BUFSIZ];
986             int err_no = errno;
987             /*
988              * Avoid generating a bogus error every poll cycle when we're
989              * in daemon mode but the connection to the outside world
990              * is down.
991              */
992             if (!((err_no == EHOSTUNREACH || err_no == ENETUNREACH) 
993                   && run.poll_interval))
994             {
995                 report_build(stderr, GT_("%s connection to %s failed"), 
996                              ctl->server.base_protocol->name, ctl->server.pollname);
997                     strlcpy(errbuf, strerror(err_no), sizeof(errbuf));
998                 report_complete(stderr, ": %s\n", errbuf);
999             }
1000             err = PS_SOCKET;
1001             set_timeout(0);
1002             phase = oldphase;
1003             goto closeUp;
1004         }
1005
1006 #ifdef SSL_ENABLE
1007         /* Save the socket opened. Useful if Fetchmail hangs on SSLOpen 
1008          * because the socket can be closed.
1009          */
1010         mailserver_socket_temp = mailserver_socket;
1011         set_timeout(mytimeout);
1012
1013         /* perform initial SSL handshake on open connection */
1014         if (ctl->use_ssl &&
1015                 SSLOpen(mailserver_socket, ctl->sslcert, ctl->sslkey,
1016                     ctl->sslproto, ctl->sslcertck,
1017                     ctl->sslcertfile, ctl->sslcertpath,
1018                     ctl->sslfingerprint, ctl->sslcommonname ?
1019                     ctl->sslcommonname : realhost, ctl->server.pollname,
1020                     &ctl->remotename) == -1)
1021         {
1022             report(stderr, GT_("SSL connection failed.\n"));
1023             err = PS_SOCKET;
1024             goto cleanUp;
1025         }
1026         
1027         /* Fetchmail didn't hang on SSLOpen, 
1028          * then no need to set mailserver_socket_temp 
1029          */
1030         mailserver_socket_temp = -1;
1031 #endif
1032         
1033         /* A timeout is still defined before SSLOpen, 
1034          * then Fetchmail hanging on SSLOpen is handled.
1035          */
1036         set_timeout(0);
1037         phase = oldphase;
1038
1039 #ifdef KERBEROS_V5
1040         if (ctl->server.authenticate == A_KERBEROS_V5)
1041         {
1042             set_timeout(mytimeout);
1043             err = kerberos5_auth(mailserver_socket, ctl->server.truename);
1044             set_timeout(0);
1045             if (err != 0)
1046                 goto cleanUp;
1047         }
1048 #endif /* KERBEROS_V5 */
1049
1050         /* accept greeting message from mail server */
1051         err = (ctl->server.base_protocol->parse_response)(mailserver_socket, buf);
1052         if (err != 0)
1053             goto cleanUp;
1054
1055         /* try to get authorized to fetch mail */
1056         stage = STAGE_GETAUTH;
1057         if (ctl->server.base_protocol->getauth)
1058         {
1059             set_timeout(mytimeout);
1060             err = (ctl->server.base_protocol->getauth)(mailserver_socket, ctl, buf);
1061             set_timeout(0);
1062
1063             if (err != 0)
1064             {
1065                 if (err == PS_LOCKBUSY)
1066                     report(stderr, GT_("Lock-busy error on %s@%s\n"),
1067                           ctl->remotename,
1068                           ctl->server.truename);
1069                 else if (err == PS_SERVBUSY)
1070                     report(stderr, GT_("Server busy error on %s@%s\n"),
1071                           ctl->remotename,
1072                           ctl->server.truename);
1073                 else if (err == PS_AUTHFAIL)
1074                 {
1075                     report(stderr, GT_("Authorization failure on %s@%s%s\n"), 
1076                            ctl->remotename,
1077                            ctl->server.truename,
1078                            (ctl->wehaveauthed ? GT_(" (previously authorized)") : "")
1079                         );
1080                     if (ctl->server.authenticate == A_ANY && !ctl->wehaveauthed) {
1081                         report(stderr, GT_("For help, see http://www.fetchmail.info/fetchmail-FAQ.html#R15\n"));
1082                     }
1083
1084                     /*
1085                      * If we're running in background, try to mail the
1086                      * calling user a heads-up about the authentication 
1087                      * failure once it looks like this isn't a fluke 
1088                      * due to the server being temporarily inaccessible.
1089                      * When we get third succesive failure, we notify the user
1090                      * but only if we haven't already managed to get
1091                      * authorization.  After that, once we get authorization
1092                      * we let the user know service is restored.
1093                      */
1094                     if (run.poll_interval
1095                         && !ctl->wehavesentauthnote
1096                         && ((ctl->wehaveauthed && ++ctl->authfailcount >= 10)
1097                             || (!ctl->wehaveauthed && ++ctl->authfailcount >= 3))
1098                         && !open_warning_by_mail(ctl))
1099                     {
1100                         ctl->wehavesentauthnote = 1;
1101                         stuff_warning(iana_charset, ctl,
1102                                       GT_("Subject: fetchmail authentication failed on %s@%s"),
1103                             ctl->remotename, ctl->server.truename);
1104                         stuff_warning(NULL, ctl, "%s", "");
1105                         stuff_warning(NULL, ctl,
1106                                       GT_("Fetchmail could not get mail from %s@%s.\n"), 
1107                                       ctl->remotename,
1108                                       ctl->server.truename);
1109                         if (ctl->wehaveauthed) {
1110                             stuff_warning(NULL, ctl, GT_("\
1111 The attempt to get authorization failed.\n\
1112 Since we have already succeeded in getting authorization for this\n\
1113 connection, this is probably another failure mode (such as busy server)\n\
1114 that fetchmail cannot distinguish because the server didn't send a useful\n\
1115 error message."));
1116                             stuff_warning(NULL, ctl, GT_("\
1117 \n\
1118 However, if you HAVE changed your account details since starting the\n\
1119 fetchmail daemon, you need to stop the daemon, change your configuration\n\
1120 of fetchmail, and then restart the daemon.\n\
1121 \n\
1122 The fetchmail daemon will continue running and attempt to connect\n\
1123 at each cycle.  No future notifications will be sent until service\n\
1124 is restored."));
1125                         } else {
1126                             stuff_warning(NULL, ctl, GT_("\
1127 The attempt to get authorization failed.\n\
1128 This probably means your password is invalid, but some servers have\n\
1129 other failure modes that fetchmail cannot distinguish from this\n\
1130 because they don't send useful error messages on login failure.\n\
1131 \n\
1132 The fetchmail daemon will continue running and attempt to connect\n\
1133 at each cycle.  No future notifications will be sent until service\n\
1134 is restored."));
1135                         }
1136                         close_warning_by_mail(ctl, (struct msgblk *)NULL);
1137                     }
1138                 }
1139                 else if (err == PS_REPOLL)
1140                 {
1141                   if (outlevel >= O_VERBOSE)
1142                     report(stderr, GT_("Repoll immediately on %s@%s\n"),
1143                            ctl->remotename,
1144                            ctl->server.truename);
1145                 }
1146                 else
1147                     report(stderr, GT_("Unknown login or authentication error on %s@%s\n"),
1148                            ctl->remotename,
1149                            ctl->server.truename);
1150                     
1151                 goto cleanUp;
1152             }
1153             else
1154             {
1155                 /*
1156                  * This connection has given us authorization at least once.
1157                  *
1158                  * There are dodgy server (clubinternet.fr for example) that
1159                  * give spurious authorization failures on patently good
1160                  * account/password details, then 5 minutes later let you in!
1161                  *
1162                  * This is meant to build in some tolerance of such nasty bits
1163                  * of work.
1164                  */
1165                 ctl->wehaveauthed = 1;
1166                 /*if (ctl->authfailcount >= 3)*/
1167                 if (ctl->wehavesentauthnote)
1168                 {
1169                     ctl->wehavesentauthnote = 0;
1170                     report(stderr,
1171                            GT_("Authorization OK on %s@%s\n"),
1172                            ctl->remotename,
1173                            ctl->server.truename);
1174                     if (!open_warning_by_mail(ctl))
1175                     {
1176                         stuff_warning(iana_charset, ctl,
1177                               GT_("Subject: fetchmail authentication OK on %s@%s"), 
1178                                       ctl->remotename, ctl->server.truename);
1179                         stuff_warning(NULL, ctl, "%s", "");
1180                         stuff_warning(NULL, ctl,
1181                               GT_("Fetchmail was able to log into %s@%s.\n"), 
1182                                       ctl->remotename,
1183                                       ctl->server.truename);
1184                         stuff_warning(NULL, ctl, 
1185                                       GT_("Service has been restored.\n"));
1186                         close_warning_by_mail(ctl, (struct msgblk *)NULL);
1187                     
1188                     }
1189                 }
1190                 /*
1191                  * Reporting only after the first three
1192                  * consecutive failures, or ten consecutive
1193                  * failures after we have managed to get
1194                  * authorization.
1195                  */
1196                 ctl->authfailcount = 0;
1197             }
1198         }
1199
1200         ctl->errcount = fetches = 0;
1201
1202         /* now iterate over each folder selected */
1203         for (idp = ctl->mailboxes; idp; idp = idp->next)
1204         {
1205             ctl->folder = idp->id;
1206             pass = 0;
1207             do {
1208                 dispatches = 0;
1209                 ++pass;
1210
1211                 /* reset timeout, in case we did an IDLE */
1212                 mytimeout = ctl->server.timeout;
1213
1214                 if (outlevel >= O_DEBUG)
1215                 {
1216                     if (idp->id)
1217                         report(stdout, GT_("selecting or re-polling folder %s\n"), idp->id);
1218                     else
1219                         report(stdout, GT_("selecting or re-polling default folder\n"));
1220                 }
1221
1222                 /* compute # of messages and number of new messages waiting */
1223                 stage = STAGE_GETRANGE;
1224                 err = (ctl->server.base_protocol->getrange)(mailserver_socket, ctl, idp->id, &count, &newm, &bytes);
1225                 if (err != 0)
1226                     goto cleanUp;
1227
1228                 /* show user how many messages we downloaded */
1229                 if (idp->id)
1230                     (void) snprintf(buf, sizeof(buf),
1231                                    GT_("%s at %s (folder %s)"),
1232                                    ctl->remotename, ctl->server.pollname, idp->id);
1233                 else
1234                     (void) snprintf(buf, sizeof(buf), GT_("%s at %s"),
1235                                    ctl->remotename, ctl->server.pollname);
1236                 if (outlevel > O_SILENT)
1237                 {
1238                     if (count == -1)            /* only used for ETRN */
1239                         report(stdout, GT_("Polling %s\n"), ctl->server.truename);
1240                     else if (count != 0)
1241                     {
1242                         if (newm != -1 && (count - newm) > 0)
1243                             report_build(stdout, ngettext("%d message (%d %s) for %s", "%d messages (%d %s) for %s", (unsigned long)count),
1244                                   count,
1245                                   count - newm, 
1246                                   ngettext("seen", "seen", (unsigned long)count-newm),
1247                                   buf);
1248                         else
1249                             report_build(stdout, ngettext("%d message for %s",
1250                                                           "%d messages for %s",
1251                                                           count), 
1252                                   count, buf);
1253                         if (bytes == -1)
1254                             report_complete(stdout, ".\n");
1255                         else
1256                             report_complete(stdout, GT_(" (%d octets).\n"), bytes);
1257                     }
1258                     else
1259                     {
1260                         /* these are pointless in normal daemon mode */
1261                         if (pass == 1 && (run.poll_interval == 0 || outlevel >= O_VERBOSE))
1262                             report(stdout, GT_("No mail for %s\n"), buf); 
1263                     }
1264                 }
1265
1266                 /* very important, this is where we leave the do loop */ 
1267                 if (count == 0)
1268                     break;
1269
1270                 if (check_only)
1271                 {
1272                     if (newm == -1 || ctl->fetchall)
1273                         newm = count;
1274                     fetches = newm;     /* set error status correctly */
1275                     /*
1276                      * There used to be a `goto noerror' here, but this
1277                      * prevented checking of multiple folders.  This
1278                      * comment is a reminder in case I introduced some
1279                      * subtle bug by removing it...
1280                      */
1281                 }
1282                 else if (count > 0)
1283                 {    
1284                     int         i;
1285
1286                     /*
1287                      * Don't trust the message count passed by the server.
1288                      * Without this check, it might be possible to do a
1289                      * DNS-spoofing attack that would pass back a ridiculous 
1290                      * count, and allocate a malloc area that would overlap
1291                      * a portion of the stack.
1292                      */
1293                     if ((unsigned)count > INT_MAX/sizeof(int))
1294                     {
1295                         report(stderr, GT_("bogus message count!"));
1296                         err = PS_PROTOCOL;
1297                         goto cleanUp;
1298                     }
1299
1300                     /* 
1301                      * We need the size of each message before it's
1302                      * loaded in order to pass it to the ESMTP SIZE
1303                      * option.  If the protocol has a getsizes method,
1304                      * we presume this means it doesn't get reliable
1305                      * sizes from message fetch responses.
1306                      *
1307                      * If the protocol supports getting sizes of subset of
1308                      * messages, we skip this step now.
1309                      */
1310                     if (proto->getsizes &&
1311                         !(proto->getpartialsizes && NUM_NONZERO(ctl->fetchsizelimit)))
1312                     {
1313                         xfree(msgsizes);
1314                         msgsizes = (int *)xmalloc(sizeof(int) * count);
1315                         for (i = 0; i < count; i++)
1316                             msgsizes[i] = 0;
1317
1318                         stage = STAGE_GETSIZES;
1319                         err = (proto->getsizes)(mailserver_socket, count, msgsizes);
1320                         if (err != 0)
1321                             goto cleanUp;
1322
1323                         if (bytes == -1)
1324                         {
1325                             bytes = 0;
1326                             for (i = 0; i < count; i++)
1327                                 bytes += msgsizes[i];
1328                         }
1329                     }
1330
1331                     /* read, forward, and delete messages */
1332                     stage = STAGE_FETCH;
1333
1334                     /* fetch in lockstep mode */
1335                     err = fetch_messages(mailserver_socket, ctl, 
1336                                          count, &msgsizes,
1337                                          maxfetch,
1338                                          &fetches, &dispatches, &deletions);
1339                     if (err != PS_SUCCESS && err != PS_MAXFETCH)
1340                         goto cleanUp;
1341
1342                     if (!check_only && ctl->skipped
1343                         && run.poll_interval > 0 && !nodetach)
1344                     {
1345                         clean_skipped_list(&ctl->skipped);
1346                         send_size_warnings(ctl);
1347                     }
1348                 }
1349
1350                 /* end-of-mailbox processing before we repoll or switch to another one */
1351                 if (ctl->server.base_protocol->end_mailbox_poll)
1352                 {
1353                     tmperr = (ctl->server.base_protocol->end_mailbox_poll)(mailserver_socket, ctl);
1354                     if (tmperr) {
1355                         err = tmperr;
1356                         goto cleanUp;
1357                     }
1358                 }
1359                 /* Return now if we have reached the fetchlimit */
1360                 if (maxfetch && maxfetch <= fetches)
1361                     goto no_error;
1362             } while
1363                   /*
1364                    * Only repoll if we either had some actual forwards
1365                    * or are idling for new mails and had no errors.
1366                    * Otherwise it is far too easy to get into infinite loops.
1367                    */
1368                   (ctl->server.base_protocol->retry && (dispatches || ctl->idle) && !ctl->errcount);
1369         }
1370
1371         /* XXX: From this point onwards, preserve err unless a new error has occurred */
1372
1373     no_error:
1374         /* PS_SUCCESS, PS_MAXFETCH: ordinary termination with no errors -- officially log out */
1375         stage = STAGE_LOGOUT;
1376         tmperr = (ctl->server.base_protocol->logout_cmd)(mailserver_socket, ctl);
1377         if (tmperr != PS_SUCCESS)
1378             err = tmperr;
1379         /*
1380          * Hmmmm...arguably this would be incorrect if we had fetches but
1381          * no dispatches (due to oversized messages, etc.)
1382          */
1383         else if (err == PS_SUCCESS && fetches == 0)
1384             err = PS_NOMAIL;
1385         /*
1386          * Close all SMTP delivery sockets.  For optimum performance
1387          * we'd like to hold them open til end of run, but (1) this
1388          * loses if our poll interval is longer than the MTA's
1389          * inactivity timeout, and (2) some MTAs (like smail) don't
1390          * deliver after each message, but rather queue up mail and
1391          * wait to actually deliver it until the input socket is
1392          * closed.
1393          *
1394          * don't send QUIT for ODMR case because we're acting as a
1395          * proxy between the SMTP server and client.
1396          */
1397         smtp_close(ctl, ctl->server.protocol != P_ODMR);
1398         cleanupSockClose(mailserver_socket);
1399         goto closeUp;
1400
1401     cleanUp:
1402         /* we only get here on error */
1403         if (err != 0 && err != PS_SOCKET && err != PS_REPOLL)
1404         {
1405             stage = STAGE_LOGOUT;
1406             (ctl->server.base_protocol->logout_cmd)(mailserver_socket, ctl);
1407         }
1408
1409         /* try to clean up all streams */
1410         release_sink(ctl);
1411         /*
1412          * Sending SMTP QUIT on signal is theoretically nice, but led
1413          * to a subtle bug.  If fetchmail was terminated by signal
1414          * while it was shipping message text, it would hang forever
1415          * waiting for a command acknowledge.  In theory we could
1416          * enable the QUIT only outside of the message send.  In
1417          * practice, we don't care.  All mailservers hang up on a
1418          * dropped TCP/IP connection anyway.
1419          */
1420         smtp_close(ctl, 0);
1421         if (mailserver_socket != -1) {
1422             cleanupSockClose(mailserver_socket);
1423         }
1424         /* If there was a connect timeout, the socket should be closed.
1425          * mailserver_socket_temp contains the socket to close.
1426          */
1427         if (mailserver_socket_temp != -1) {
1428             cleanupSockClose(mailserver_socket_temp);
1429             mailserver_socket_temp = -1;
1430         }
1431     }
1432
1433     /* no report on PS_AUTHFAIL */
1434     msg = NULL;
1435     switch (err)
1436     {
1437     case PS_SOCKET:
1438         msg = GT_("socket");
1439         break;
1440     case PS_SYNTAX:
1441         msg = GT_("missing or bad RFC822 header");
1442         break;
1443     case PS_IOERR:
1444         msg = GT_("MDA");
1445         break;
1446     case PS_ERROR:
1447         msg = GT_("client/server synchronization");
1448         break;
1449     case PS_PROTOCOL:
1450         msg = GT_("client/server protocol");
1451         break;
1452     case PS_LOCKBUSY:
1453         msg = GT_("lock busy on server");
1454         break;
1455     case PS_SMTP:
1456         msg = GT_("SMTP transaction");
1457         break;
1458     case PS_DNS:
1459         msg = GT_("DNS lookup");
1460         break;
1461     case PS_UNDEFINED:
1462         msg = GT_("undefined");
1463         break;
1464     }
1465     if (msg) {
1466         if (phase == FORWARDING_WAIT || phase == LISTENER_WAIT
1467                 || err == PS_SMTP)
1468             report(stderr, GT_("%s error while fetching from %s@%s and delivering to SMTP host %s\n"),
1469                     msg, ctl->remotename, ctl->server.pollname,
1470                     ctl->smtphost ? ctl->smtphost : GT_("unknown"));
1471         else
1472             report(stderr, GT_("%s error while fetching from %s@%s\n"),
1473                     msg, ctl->remotename, ctl->server.pollname);
1474     }
1475
1476 closeUp:
1477     xfree(msgsizes);
1478     ctl->folder = NULL;
1479
1480     /* execute wrapup command, if any */
1481     if (ctl->postconnect && (tmperr = system(ctl->postconnect)))
1482     {
1483         if (WIFSIGNALED(tmperr))
1484             report(stderr, GT_("post-connection command terminated with signal %d\n"), WTERMSIG(tmperr));
1485         else
1486             report(stderr, GT_("post-connection command failed with status %d\n"), WEXITSTATUS(tmperr));
1487         if (err == PS_SUCCESS)
1488             err = PS_SYNTAX;
1489     }
1490
1491     set_timeout(0); /* cancel any pending alarm */
1492     set_signal_handler(SIGALRM, alrmsave);
1493     return(err);
1494 }
1495
1496 /** retrieve messages from server using given protocol method table */
1497 int do_protocol(struct query *ctl /** parsed options with merged-in defaults */,
1498                 const struct method *proto /** protocol method table */)
1499 {
1500     int err;
1501
1502 #ifndef KERBEROS_V5
1503     if (ctl->server.authenticate == A_KERBEROS_V5)
1504     {
1505         report(stderr, GT_("Kerberos V5 support not linked.\n"));
1506         return(PS_ERROR);
1507     }
1508 #endif /* KERBEROS_V5 */
1509
1510     /* lacking methods, there are some options that may fail */
1511     if (!proto->is_old)
1512     {
1513         /* check for unsupported options */
1514         if (ctl->flush) {
1515             report(stderr,
1516                     GT_("Option --flush is not supported with %s\n"),
1517                     proto->name);
1518             return(PS_SYNTAX);
1519         }
1520         else if (ctl->fetchall) {
1521             report(stderr,
1522                     GT_("Option --all is not supported with %s\n"),
1523                     proto->name);
1524             return(PS_SYNTAX);
1525         }
1526     }
1527     if (!(proto->getsizes || proto->getpartialsizes)
1528             && NUM_SPECIFIED(ctl->limit))
1529     {
1530         report(stderr,
1531                 GT_("Option --limit is not supported with %s\n"),
1532                 proto->name);
1533         return(PS_SYNTAX);
1534     }
1535
1536     /*
1537      * If no expunge limit or we do expunges within the driver,
1538      * then just do one session, passing in any fetchlimit.
1539      */
1540     if ((ctl->keep && !ctl->flush) ||
1541         proto->retry || !NUM_SPECIFIED(ctl->expunge))
1542         return(do_session(ctl, proto, NUM_VALUE_OUT(ctl->fetchlimit)));
1543     /*
1544      * There's an expunge limit, and it isn't handled in the driver itself.
1545      * OK; do multiple sessions, each fetching a limited # of messages.
1546      * Stop if the total count of retrieved messages exceeds ctl->fetchlimit
1547      * (if it was nonzero).
1548      */
1549     else
1550     {
1551         int totalcount = 0; 
1552         int lockouts   = 0;
1553         int expunge    = NUM_VALUE_OUT(ctl->expunge);
1554         int fetchlimit = NUM_VALUE_OUT(ctl->fetchlimit);
1555
1556         do {
1557             if (fetchlimit > 0 && (expunge == 0 || expunge > fetchlimit - totalcount))
1558                 expunge = fetchlimit - totalcount;
1559             err = do_session(ctl, proto, expunge);
1560             totalcount += expunge;
1561             if (NUM_SPECIFIED(ctl->fetchlimit) && totalcount >= fetchlimit)
1562                 break;
1563             if (err != PS_LOCKBUSY)
1564                 lockouts = 0;
1565             else if (lockouts >= MAX_LOCKOUTS)
1566                 break;
1567             else /* err == PS_LOCKBUSY */
1568             {
1569                 /*
1570                  * Allow time for the server lock to release.  if we
1571                  * don't do this, we'll often hit a locked-mailbox
1572                  * condition and fail.
1573                  */
1574                 lockouts++;
1575                 sleep(3);
1576             }
1577         } while
1578             (err == PS_MAXFETCH || err == PS_LOCKBUSY);
1579
1580         return(err);
1581     }
1582 }
1583
1584
1585 /* driver.c ends here */