]> Pileus Git - ~andy/fetchmail/blob - driver.c
Attempt merging from 6.3.24.
[~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                           int *transient_errors)
357 /* fetch messages in lockstep mode */
358 {
359     flag force_retrieval;
360     int num, firstnum = 1, lastnum = 0, err, len;
361     int fetchsizelimit = ctl->fetchsizelimit;
362     int msgsize;
363     int initialfetches = *fetches;
364
365     if (ctl->server.base_protocol->getpartialsizes && NUM_NONZERO(fetchsizelimit))
366     {
367         /* for POP3, we can get the size of one mail only! Unfortunately, this
368          * protocol specific test cannot be done elsewhere as the protocol
369          * could be "auto". */
370         switch (ctl->server.protocol)
371         {
372             case P_POP3:
373             fetchsizelimit = 1;
374         }
375
376         /* Time to allocate memory to store the sizes */
377         xfree(*msgsizes);
378         *msgsizes = (int *)xmalloc(sizeof(int) * fetchsizelimit);
379     }
380
381     /*
382      * What forces this code is that in
383      * IMAP2bis you can't fetch a message without
384      * having it marked `seen'.  In POP3 and IMAP4, on the
385      * other hand, you can (peek_capable is set by 
386      * each driver module to convey this; it's not a
387      * method constant because of the difference between
388      * IMAP2bis and IMAP4, and because POP3 doesn't  peek
389      * if fetchall is on).
390      *
391      * The result of being unable to peek is that if there's
392      * any kind of transient error (DNS lookup failure, or
393      * sendmail refusing delivery due to process-table limits)
394      * the message will be marked "seen" on the server without
395      * having been delivered.  This is not a big problem if
396      * fetchmail is running in foreground, because the user
397      * will see a "skipped" message when it next runs and get
398      * clued in.
399      *
400      * But in daemon mode this leads to the message
401      * being silently ignored forever.  This is not
402      * acceptable.
403      *
404      * We compensate for this by checking the error
405      * count from the previous pass and forcing all
406      * messages to be considered new if it's nonzero.
407      */
408     force_retrieval = !peek_capable && (ctl->errcount > 0);
409
410     for (num = 1; num <= count; num++)
411     {
412         flag suppress_delete = FALSE;
413         flag suppress_forward = FALSE;
414         flag suppress_readbody = FALSE;
415         flag retained = FALSE;
416         int msgcode = MSGLEN_UNKNOWN;
417
418         /* check if the message is old
419          * Note: the size of the message may not be known here */
420         if (ctl->fetchall || force_retrieval) {
421             /* empty */
422         } else { 
423             if (ctl->server.base_protocol->is_old && (ctl->server.base_protocol->is_old)(mailserver_socket,ctl,num)) {
424                     msgcode = MSGLEN_OLD;
425             }
426         }
427         if (msgcode == MSGLEN_OLD)
428         {
429             /*
430              * To avoid flooding the logs when using --keep, report
431              * skipping for old messages only when --flush is on.
432              */
433             if (outlevel > O_SILENT && ctl->flush)
434             {
435                 report_build(stdout, 
436                              GT_("skipping message %s@%s:%d"),
437                              ctl->remotename, ctl->server.truename, num);
438             }
439
440             goto flagthemail;
441         }
442
443         if (ctl->server.base_protocol->getpartialsizes && NUM_NONZERO(fetchsizelimit) &&
444             lastnum < num)
445         {
446             /* Instead of getting the sizes of all mails at the start, we get
447              * the sizes in blocks of fetchsizelimit. This leads to better
448              * performance when there are too many mails (say, 10000) in
449              * the mailbox and either we are not getting all the mails at
450              * one go (--fetchlimit 100) or there is a frequent socket
451              * error while just getting the sizes of all mails! */
452
453             int i;
454             int oldstage = stage;
455             firstnum = num;
456             lastnum = num + fetchsizelimit - 1;
457             if (lastnum > count)
458                 lastnum = count;
459             for (i = 0; i < fetchsizelimit; i++)
460                 (*msgsizes)[i] = 0;
461
462             stage = STAGE_GETSIZES;
463             err = (ctl->server.base_protocol->getpartialsizes)(mailserver_socket, num, lastnum, *msgsizes);
464             if (err != 0) {
465                 return err;
466             }
467             stage = oldstage;
468         }
469
470         msgsize = *msgsizes ? (*msgsizes)[num-firstnum] : 0;
471
472         /* check if the message is oversized */
473         if (NUM_NONZERO(ctl->limit) && (msgsize > ctl->limit))
474             msgcode = MSGLEN_TOOLARGE;
475 /*      else if (msgsize == 512)
476             msgcode = MSGLEN_OLD;  (hmh) sample code to skip message */
477
478         if (msgcode < 0)
479         {
480             if (msgcode == MSGLEN_TOOLARGE)
481             {
482                 mark_oversized(ctl, msgsize);
483                 if (!ctl->limitflush)
484                     suppress_delete = TRUE;
485             }
486             if (outlevel > O_SILENT)
487             {
488                 /* old messages are already handled above */
489                 report_build(stdout, 
490                              GT_("skipping message %s@%s:%d (%d octets)"),
491                              ctl->remotename, ctl->server.truename, num,
492                              msgsize);
493                 switch (msgcode)
494                 {
495                 case MSGLEN_INVALID:
496                     /*
497                      * Invalid lengths are produced by Post Office/NT's
498                      * annoying habit of randomly prepending bogus
499                      * LIST items of length -1.  Patrick Audley
500                      * <paudley@pobox.com> tells us: LIST shows a
501                      * size of -1, RETR and TOP return "-ERR
502                      * System error - couldn't open message", and
503                      * DELE succeeds but doesn't actually delete
504                      * the message.
505                      */
506                     report_build(stdout, GT_(" (length -1)"));
507                     break;
508                 case MSGLEN_TOOLARGE:
509                     report_build(stdout, GT_(" (oversized)"));
510                     break;
511                 }
512             }
513         }
514         else
515         {
516           /* XXX FIXME: make this one variable, wholesize and
517              separatefetchbody query the same variable just with
518              inverted logic */
519             flag wholesize = !ctl->server.base_protocol->fetch_body;
520             flag separatefetchbody = (ctl->server.base_protocol->fetch_body) ? TRUE : FALSE;
521
522             /* request a message */
523             err = (ctl->server.base_protocol->fetch_headers)(mailserver_socket,ctl,num, &len);
524             if (err == PS_TRANSIENT)    /* server is probably Exchange */
525             {
526                 report(stdout,
527                              GT_("couldn't fetch headers, message %s@%s:%d (%d octets)\n"),
528                              ctl->remotename, ctl->server.truename, num,
529                              msgsize);
530                 (*transient_errors)++;
531                 continue;
532             }
533             else if (err != 0)
534                 return(err);
535
536             /* -1 means we didn't see a size in the response */
537             if (len == -1)
538             {
539                 len = msgsize;
540                 wholesize = TRUE;
541             }
542
543             if (outlevel > O_SILENT)
544             {
545                 report_build(stdout, GT_("reading message %s@%s:%d of %d"),
546                              ctl->remotename, ctl->server.truename,
547                              num, count);
548
549                 if (len > 0)
550                     report_build(stdout, wholesize ? GT_(" (%d octets)")
551                                  : GT_(" (%d header octets)"), len);
552                 if (want_progress()) {
553                     /* flush and add a blank to append ticker dots */
554                     report_flush(stdout);
555                     putchar(' ');
556                 }
557             }
558
559             /* 
560              * Read the message headers and ship them to the
561              * output sink.  
562              */
563             err = readheaders(mailserver_socket, len, msgsize,
564                              ctl, num,
565                              /* pass the suppress_readbody flag only if the underlying
566                               * protocol does not fetch the body separately */
567                              separatefetchbody ? 0 : &suppress_readbody);
568
569             if (err == PS_RETAINED)
570                 suppress_forward = suppress_delete = retained = TRUE;
571             else if (err == PS_TRANSIENT)
572             {
573                 suppress_delete = suppress_forward = TRUE;
574                 (*transient_errors)++;
575             }
576             else if (err == PS_REFUSED)
577                 suppress_forward = TRUE;
578             else if (err)
579                 return(err);
580
581             /* tell server we got it OK and resynchronize */
582             if (separatefetchbody && ctl->server.base_protocol->trail)
583             {
584                 err = eat_trailer(mailserver_socket, ctl);
585                 if (err) return(err);
586             }
587
588             /* do not read the body which is not being forwarded only if
589              * the underlying protocol allows the body to be fetched
590              * separately */
591             if (separatefetchbody && suppress_forward)
592                 suppress_readbody = TRUE;
593
594             /* 
595              * If we're using IMAP4 or something else that
596              * can fetch headers separately from bodies,
597              * it's time to request the body now.  This
598              * fetch may be skipped if we got an anti-spam
599              * or other PS_REFUSED error response during
600              * readheaders.
601              */
602             if (!suppress_readbody)
603             {
604                 if (separatefetchbody)
605                 {
606                     len = -1;
607                     if ((err=(ctl->server.base_protocol->fetch_body)(mailserver_socket,ctl,num,&len))) {
608                         if (err == PS_ERROR && ctl->server.retrieveerror) {
609                             /*
610                              * Mark a message with a protocol error as seen.
611                              * This can be used to see which messages we've attempted
612                              * to download, but failed.
613                              */
614                             if (ctl->server.retrieveerror == RE_MARKSEEN) {
615                                 if ((ctl->server.base_protocol->mark_seen)(mailserver_socket,ctl,num)) {
616                                     return(err);
617                                 }
618                             }
619
620                             if (ctl->server.retrieveerror != RE_ABORT) {
621                                 /*
622                                  * Do not abort download session.  Continue with the next message.
623                                  *
624                                  * Prevents a malformed message from blocking all other messages
625                                  * behind it in the mailbox from being downloaded.
626                                  *
627                                  * Reconnect to SMTP to force this incomplete message to be dropped.
628                                  * Required because we've already begun the DATA portion of the
629                                  * interaction with the SMTP server (commands are ignored/
630                                  * considered part of the message data).
631                                  */
632                                 abort_message_sink(ctl);
633
634                                 // Ensure we don't delete the failed message from the server.
635                                 suppress_delete = TRUE;
636
637                                 // Bookkeeping required before next message can be downloaded.
638                                 goto flagthemail;
639                             }
640                         }
641
642                         return(err);
643                     }
644
645                     /*
646                      * Work around a bug in Novell's
647                      * broken GroupWise IMAP server;
648                      * its body FETCH response is missing
649                      * the required length for the data
650                      * string.  This violates RFC2060.
651                      */
652                     if (len == -1)
653                         len = msgsize - msgblk.msglen;
654                     if (!wholesize) {
655                         if (outlevel > O_SILENT)
656                             report_build(stdout,
657                                     GT_(" (%d body octets)"), len);
658                         if (want_progress()) {
659                             report_flush(stdout);
660                             putchar(' ');
661                         }
662                     }
663                 }
664
665                 /* process the body now */
666                 err = readbody(mailserver_socket,
667                               ctl,
668                               !suppress_forward,
669                               len);
670
671                 if (err == PS_TRANSIENT)
672                 {
673                     suppress_delete = suppress_forward = TRUE;
674                     (*transient_errors)++;
675                 }
676                 else if (err)
677                     return(err);
678
679                 /* tell server we got it OK and resynchronize */
680                 if (ctl->server.base_protocol->trail) {
681                     err = eat_trailer(mailserver_socket, ctl);
682                     if (err) return(err);
683                 }
684             }
685
686             /* count # messages forwarded on this pass */
687             if (!suppress_forward)
688                 (*dispatches)++;
689
690             /*
691              * Check to see if the numbers matched?
692              *
693              * Yes, some servers foo this up horribly.
694              * All IMAP servers seem to get it right, and
695              * so does Eudora QPOP at least in 2.xx
696              * versions.
697              *
698              * Microsoft Exchange gets it completely
699              * wrong, reporting compressed rather than
700              * actual sizes (so the actual length of
701              * message is longer than the reported size).
702              * Another fine example of Microsoft brain death!
703              *
704              * Some older POP servers, like the old UCB
705              * POP server and the pre-QPOP QUALCOMM
706              * versions, report a longer size in the LIST
707              * response than actually gets shipped up.
708              * It's unclear what is going on here, as the
709              * QUALCOMM server (at least) seems to be
710              * reporting the on-disk size correctly.
711              *
712              * qmail-pop3d also goofs up message sizes and does not
713              * count the line end characters properly.
714              */
715             if (msgblk.msglen != msgsize)
716             {
717                 if (outlevel >= O_DEBUG)
718                     report(stdout,
719                            GT_("message %s@%s:%d was not the expected length (%d actual != %d expected)\n"),
720                            ctl->remotename, ctl->server.truename, num,
721                            msgblk.msglen, msgsize);
722             }
723
724             /* end-of-message processing starts here */
725             if (!close_sink(ctl, &msgblk, !suppress_forward))
726             {
727                 ctl->errcount++;
728                 suppress_delete = TRUE;
729             }
730             if (!retained)
731                 (*fetches)++;
732         }
733
734 flagthemail:
735         /*
736          * At this point in flow of control,
737          * either we've bombed on a protocol error
738          * or had delivery refused by the SMTP server
739          * or we've seen `accepted for delivery' and the message is shipped.
740          * It's safe to mark the message seen and delete it on the server now.
741          */
742
743         /* in softbounce mode, suppress deletion and marking as seen */
744         if (suppress_forward)
745             suppress_delete = suppress_delete || run.softbounce;
746
747         /* maybe we delete this message now? */
748         if (retained)
749         {
750             if (outlevel > O_SILENT) 
751                 report_complete(stdout, GT_(" retained\n"));
752         }
753         else if (ctl->server.base_protocol->delete_msg
754                  && !suppress_delete
755                  && ((msgcode >= 0 && !ctl->keep)
756                      || (msgcode == MSGLEN_OLD && ctl->flush)
757                      || (msgcode == MSGLEN_TOOLARGE && ctl->limitflush)))
758         {
759             (*deletions)++;
760             if (outlevel > O_SILENT) 
761                 report_complete(stdout, GT_(" flushed\n"));
762             err = (ctl->server.base_protocol->delete_msg)(mailserver_socket, ctl, num);
763             if (err != 0)
764                 return(err);
765         }
766         else
767         {
768             /*
769              * To avoid flooding the logs when using --keep, report
770              * skipping of new messages only.
771              */
772             if (outlevel > O_SILENT && msgcode != MSGLEN_OLD)
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, transient_errors, 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             set_timeout(0);
1059             report(stderr, GT_("SSL connection failed.\n"));
1060             err = PS_SOCKET;
1061             goto cleanUp;
1062         }
1063         
1064         /* Fetchmail didn't hang on SSLOpen, 
1065          * then no need to set mailserver_socket_temp 
1066          */
1067         mailserver_socket_temp = -1;
1068 #endif
1069         
1070         /* A timeout is still defined before SSLOpen, 
1071          * then Fetchmail hanging on SSLOpen is handled.
1072          */
1073         set_timeout(0);
1074         phase = oldphase;
1075
1076 #ifdef KERBEROS_V5
1077         if (ctl->server.authenticate == A_KERBEROS_V5)
1078         {
1079             set_timeout(mytimeout);
1080             err = kerberos5_auth(mailserver_socket, ctl->server.truename);
1081             set_timeout(0);
1082             if (err != 0)
1083                 goto cleanUp;
1084         }
1085 #endif /* KERBEROS_V5 */
1086
1087         /* accept greeting message from mail server */
1088         err = (ctl->server.base_protocol->parse_response)(mailserver_socket, buf);
1089         if (err != 0)
1090             goto cleanUp;
1091
1092         /* try to get authorized to fetch mail */
1093         stage = STAGE_GETAUTH;
1094         if (ctl->server.base_protocol->getauth)
1095         {
1096             set_timeout(mytimeout);
1097             err = (ctl->server.base_protocol->getauth)(mailserver_socket, ctl, buf);
1098             set_timeout(0);
1099
1100             if (err != 0)
1101             {
1102                 if (err == PS_LOCKBUSY)
1103                     report(stderr, GT_("Lock-busy error on %s@%s\n"),
1104                           ctl->remotename,
1105                           ctl->server.truename);
1106                 else if (err == PS_SERVBUSY)
1107                     report(stderr, GT_("Server busy error on %s@%s\n"),
1108                           ctl->remotename,
1109                           ctl->server.truename);
1110                 else if (err == PS_AUTHFAIL)
1111                 {
1112                     report(stderr, GT_("Authorization failure on %s@%s%s\n"), 
1113                            ctl->remotename,
1114                            ctl->server.truename,
1115                            (ctl->wehaveauthed ? GT_(" (previously authorized)") : "")
1116                         );
1117                     if (ctl->server.authenticate == A_ANY && !ctl->wehaveauthed) {
1118                         report(stderr, GT_("For help, see http://www.fetchmail.info/fetchmail-FAQ.html#R15\n"));
1119                     }
1120
1121                     /*
1122                      * If we're running in background, try to mail the
1123                      * calling user a heads-up about the authentication 
1124                      * failure once it looks like this isn't a fluke 
1125                      * due to the server being temporarily inaccessible.
1126                      * When we get third succesive failure, we notify the user
1127                      * but only if we haven't already managed to get
1128                      * authorization.  After that, once we get authorization
1129                      * we let the user know service is restored.
1130                      */
1131                     if (run.poll_interval
1132                         && !ctl->wehavesentauthnote
1133                         && ((ctl->wehaveauthed && ++ctl->authfailcount >= 10)
1134                             || (!ctl->wehaveauthed && ++ctl->authfailcount >= 3))
1135                         && !open_warning_by_mail(ctl))
1136                     {
1137                         ctl->wehavesentauthnote = 1;
1138                         stuff_warning(iana_charset, ctl,
1139                                       GT_("Subject: fetchmail authentication failed on %s@%s"),
1140                             ctl->remotename, ctl->server.truename);
1141                         stuff_warning(NULL, ctl, "%s", "");
1142                         stuff_warning(NULL, ctl,
1143                                       GT_("Fetchmail could not get mail from %s@%s.\n"), 
1144                                       ctl->remotename,
1145                                       ctl->server.truename);
1146                         if (ctl->wehaveauthed) {
1147                             stuff_warning(NULL, ctl, GT_("\
1148 The attempt to get authorization failed.\n\
1149 Since we have already succeeded in getting authorization for this\n\
1150 connection, this is probably another failure mode (such as busy server)\n\
1151 that fetchmail cannot distinguish because the server didn't send a useful\n\
1152 error message."));
1153                             stuff_warning(NULL, ctl, GT_("\
1154 \n\
1155 However, if you HAVE changed your account details since starting the\n\
1156 fetchmail daemon, you need to stop the daemon, change your configuration\n\
1157 of fetchmail, and then restart the daemon.\n\
1158 \n\
1159 The fetchmail daemon will continue running and attempt to connect\n\
1160 at each cycle.  No future notifications will be sent until service\n\
1161 is restored."));
1162                         } else {
1163                             stuff_warning(NULL, ctl, GT_("\
1164 The attempt to get authorization failed.\n\
1165 This probably means your password is invalid, but some servers have\n\
1166 other failure modes that fetchmail cannot distinguish from this\n\
1167 because they don't send useful error messages on login failure.\n\
1168 \n\
1169 The fetchmail daemon will continue running and attempt to connect\n\
1170 at each cycle.  No future notifications will be sent until service\n\
1171 is restored."));
1172                         }
1173                         close_warning_by_mail(ctl, (struct msgblk *)NULL);
1174                     }
1175                 }
1176                 else if (err == PS_REPOLL)
1177                 {
1178                   if (outlevel >= O_VERBOSE)
1179                     report(stderr, GT_("Repoll immediately on %s@%s\n"),
1180                            ctl->remotename,
1181                            ctl->server.truename);
1182                 }
1183                 else
1184                     report(stderr, GT_("Unknown login or authentication error on %s@%s\n"),
1185                            ctl->remotename,
1186                            ctl->server.truename);
1187                     
1188                 goto cleanUp;
1189             }
1190             else
1191             {
1192                 /*
1193                  * This connection has given us authorization at least once.
1194                  *
1195                  * There are dodgy server (clubinternet.fr for example) that
1196                  * give spurious authorization failures on patently good
1197                  * account/password details, then 5 minutes later let you in!
1198                  *
1199                  * This is meant to build in some tolerance of such nasty bits
1200                  * of work.
1201                  */
1202                 ctl->wehaveauthed = 1;
1203                 /*if (ctl->authfailcount >= 3)*/
1204                 if (ctl->wehavesentauthnote)
1205                 {
1206                     ctl->wehavesentauthnote = 0;
1207                     report(stderr,
1208                            GT_("Authorization OK on %s@%s\n"),
1209                            ctl->remotename,
1210                            ctl->server.truename);
1211                     if (!open_warning_by_mail(ctl))
1212                     {
1213                         stuff_warning(iana_charset, ctl,
1214                               GT_("Subject: fetchmail authentication OK on %s@%s"), 
1215                                       ctl->remotename, ctl->server.truename);
1216                         stuff_warning(NULL, ctl, "%s", "");
1217                         stuff_warning(NULL, ctl,
1218                               GT_("Fetchmail was able to log into %s@%s.\n"), 
1219                                       ctl->remotename,
1220                                       ctl->server.truename);
1221                         stuff_warning(NULL, ctl, 
1222                                       GT_("Service has been restored.\n"));
1223                         close_warning_by_mail(ctl, (struct msgblk *)NULL);
1224                     
1225                     }
1226                 }
1227                 /*
1228                  * Reporting only after the first three
1229                  * consecutive failures, or ten consecutive
1230                  * failures after we have managed to get
1231                  * authorization.
1232                  */
1233                 ctl->authfailcount = 0;
1234             }
1235         }
1236
1237         ctl->errcount = fetches = 0;
1238
1239         /* now iterate over each folder selected */
1240         for (idp = ctl->mailboxes; idp; idp = idp->next)
1241         {
1242             ctl->folder = idp->id;
1243             pass = 0;
1244             do {
1245                 dispatches = 0;
1246                 transient_errors = 0;
1247                 ++pass;
1248
1249                 /* reset timeout, in case we did an IDLE */
1250                 mytimeout = ctl->server.timeout;
1251
1252                 if (outlevel >= O_DEBUG)
1253                 {
1254                     if (idp->id)
1255                         report(stdout, GT_("selecting or re-polling folder %s\n"), idp->id);
1256                     else
1257                         report(stdout, GT_("selecting or re-polling default folder\n"));
1258                 }
1259
1260                 /* compute # of messages and number of new messages waiting */
1261                 stage = STAGE_GETRANGE;
1262                 err = (ctl->server.base_protocol->getrange)(mailserver_socket, ctl, idp->id, &count, &newm, &bytes);
1263                 if (err != 0)
1264                     goto cleanUp;
1265
1266                 /* show user how many messages we downloaded */
1267                 if (idp->id)
1268                     (void) snprintf(buf, sizeof(buf),
1269                                    GT_("%s at %s (folder %s)"),
1270                                    ctl->remotename, ctl->server.pollname, idp->id);
1271                 else
1272                     (void) snprintf(buf, sizeof(buf), GT_("%s at %s"),
1273                                    ctl->remotename, ctl->server.pollname);
1274                 if (outlevel > O_SILENT)
1275                 {
1276                     if (count == -1)            /* only used for ETRN */
1277                         report(stdout, GT_("Polling %s\n"), ctl->server.truename);
1278                     else if (count != 0)
1279                     {
1280                         if (newm != -1 && (count - newm) > 0)
1281                             report_build(stdout, ngettext("%d message (%d %s) for %s", "%d messages (%d %s) for %s", (unsigned long)count),
1282                                   count,
1283                                   count - newm, 
1284                                   ngettext("seen", "seen", (unsigned long)count-newm),
1285                                   buf);
1286                         else
1287                             report_build(stdout, ngettext("%d message for %s",
1288                                                           "%d messages for %s",
1289                                                           count), 
1290                                   count, buf);
1291                         if (bytes == -1)
1292                             report_complete(stdout, ".\n");
1293                         else
1294                             report_complete(stdout, GT_(" (%d octets).\n"), bytes);
1295                     }
1296                     else
1297                     {
1298                         /* these are pointless in normal daemon mode */
1299                         if (pass == 1 && (run.poll_interval == 0 || outlevel >= O_VERBOSE))
1300                             report(stdout, GT_("No mail for %s\n"), buf); 
1301                     }
1302                 }
1303
1304                 /* very important, this is where we leave the do loop */ 
1305                 if (count == 0)
1306                     break;
1307
1308                 if (check_only)
1309                 {
1310                     if (newm == -1 || ctl->fetchall)
1311                         newm = count;
1312                     fetches = newm;     /* set error status correctly */
1313                     /*
1314                      * There used to be a `goto noerror' here, but this
1315                      * prevented checking of multiple folders.  This
1316                      * comment is a reminder in case I introduced some
1317                      * subtle bug by removing it...
1318                      */
1319                 }
1320                 else if (count > 0)
1321                 {    
1322                     int         i;
1323
1324                     /*
1325                      * Don't trust the message count passed by the server.
1326                      * Without this check, it might be possible to do a
1327                      * DNS-spoofing attack that would pass back a ridiculous 
1328                      * count, and allocate a malloc area that would overlap
1329                      * a portion of the stack.
1330                      */
1331                     if ((unsigned)count > INT_MAX/sizeof(int))
1332                     {
1333                         report(stderr, GT_("bogus message count!"));
1334                         err = PS_PROTOCOL;
1335                         goto cleanUp;
1336                     }
1337
1338                     /* 
1339                      * We need the size of each message before it's
1340                      * loaded in order to pass it to the ESMTP SIZE
1341                      * option.  If the protocol has a getsizes method,
1342                      * we presume this means it doesn't get reliable
1343                      * sizes from message fetch responses.
1344                      *
1345                      * If the protocol supports getting sizes of subset of
1346                      * messages, we skip this step now.
1347                      */
1348                     if (proto->getsizes &&
1349                         !(proto->getpartialsizes && NUM_NONZERO(ctl->fetchsizelimit)))
1350                     {
1351                         xfree(msgsizes);
1352                         msgsizes = (int *)xmalloc(sizeof(int) * count);
1353                         for (i = 0; i < count; i++)
1354                             msgsizes[i] = 0;
1355
1356                         stage = STAGE_GETSIZES;
1357                         err = (proto->getsizes)(mailserver_socket, count, msgsizes);
1358                         if (err != 0)
1359                             goto cleanUp;
1360
1361                         if (bytes == -1)
1362                         {
1363                             bytes = 0;
1364                             for (i = 0; i < count; i++)
1365                                 bytes += msgsizes[i];
1366                         }
1367                     }
1368
1369                     /* read, forward, and delete messages */
1370                     stage = STAGE_FETCH;
1371
1372                     /* fetch in lockstep mode */
1373                     err = fetch_messages(mailserver_socket, ctl, 
1374                                          count, &msgsizes,
1375                                          maxfetch,
1376                                          &fetches, &dispatches, &deletions,
1377                                          &transient_errors);
1378                     if (err != PS_SUCCESS && err != PS_MAXFETCH)
1379                         goto cleanUp;
1380
1381                     if (transient_errors > MAX_TRANSIENT_ERRORS)
1382                     {
1383                         if (outlevel > O_SILENT)
1384                         {
1385                             report(stderr, GT_("Too many mails skipped (%d > %d) due to transient errors for %s\n"),
1386                                     transient_errors, MAX_TRANSIENT_ERRORS, buf);
1387                         }
1388                     }
1389
1390                     if (!check_only && ctl->skipped
1391                         && run.poll_interval > 0 && !nodetach)
1392                     {
1393                         clean_skipped_list(&ctl->skipped);
1394                         send_size_warnings(ctl);
1395                     }
1396                 }
1397
1398                 /* end-of-mailbox processing before we repoll or switch to another one */
1399                 if (ctl->server.base_protocol->end_mailbox_poll)
1400                 {
1401                     tmperr = (ctl->server.base_protocol->end_mailbox_poll)(mailserver_socket, ctl);
1402                     if (tmperr) {
1403                         err = tmperr;
1404                         goto cleanUp;
1405                     }
1406                 }
1407                 /* Return now if we have reached the fetchlimit */
1408                 if (maxfetch && maxfetch <= fetches)
1409                     goto no_error;
1410             } while
1411                   /*
1412                    * Only repoll if we either had some actual forwards
1413                    * or are idling for new mails and had no errors.
1414                    * Otherwise it is far too easy to get into infinite loops.
1415                    */
1416                   (ctl->server.base_protocol->retry && (dispatches || ctl->idle) && !ctl->errcount);
1417         }
1418
1419         /* XXX: From this point onwards, preserve err unless a new error has occurred */
1420
1421     no_error:
1422         /* PS_SUCCESS, PS_MAXFETCH: ordinary termination with no errors -- officially log out */
1423         stage = STAGE_LOGOUT;
1424         tmperr = (ctl->server.base_protocol->logout_cmd)(mailserver_socket, ctl);
1425         if (tmperr != PS_SUCCESS)
1426             err = tmperr;
1427         /*
1428          * Hmmmm...arguably this would be incorrect if we had fetches but
1429          * no dispatches (due to oversized messages, etc.)
1430          */
1431         else if (err == PS_SUCCESS && fetches == 0)
1432             err = PS_NOMAIL;
1433         /*
1434          * Close all SMTP delivery sockets.  For optimum performance
1435          * we'd like to hold them open til end of run, but (1) this
1436          * loses if our poll interval is longer than the MTA's
1437          * inactivity timeout, and (2) some MTAs (like smail) don't
1438          * deliver after each message, but rather queue up mail and
1439          * wait to actually deliver it until the input socket is
1440          * closed.
1441          *
1442          * don't send QUIT for ODMR case because we're acting as a
1443          * proxy between the SMTP server and client.
1444          */
1445         smtp_close(ctl, ctl->server.protocol != P_ODMR);
1446         cleanupSockClose(mailserver_socket);
1447         goto closeUp;
1448
1449     cleanUp:
1450         /* we only get here on error */
1451         if (err != 0 && err != PS_SOCKET && err != PS_REPOLL)
1452         {
1453             stage = STAGE_LOGOUT;
1454             (ctl->server.base_protocol->logout_cmd)(mailserver_socket, ctl);
1455         }
1456
1457         /* try to clean up all streams */
1458         release_sink(ctl);
1459         /*
1460          * Sending SMTP QUIT on signal is theoretically nice, but led
1461          * to a subtle bug.  If fetchmail was terminated by signal
1462          * while it was shipping message text, it would hang forever
1463          * waiting for a command acknowledge.  In theory we could
1464          * enable the QUIT only outside of the message send.  In
1465          * practice, we don't care.  All mailservers hang up on a
1466          * dropped TCP/IP connection anyway.
1467          */
1468         smtp_close(ctl, 0);
1469         if (mailserver_socket != -1) {
1470             cleanupSockClose(mailserver_socket);
1471         }
1472         /* If there was a connect timeout, the socket should be closed.
1473          * mailserver_socket_temp contains the socket to close.
1474          */
1475         if (mailserver_socket_temp != -1) {
1476             cleanupSockClose(mailserver_socket_temp);
1477             mailserver_socket_temp = -1;
1478         }
1479     }
1480
1481     /* no report on PS_AUTHFAIL */
1482     msg = NULL;
1483     switch (err)
1484     {
1485     case PS_SOCKET:
1486         msg = GT_("socket");
1487         break;
1488     case PS_SYNTAX:
1489         msg = GT_("missing or bad RFC822 header or command line option");
1490         break;
1491     case PS_IOERR:
1492         msg = GT_("MDA");
1493         break;
1494     case PS_ERROR:
1495         msg = GT_("client/server synchronization");
1496         break;
1497     case PS_PROTOCOL:
1498         msg = GT_("client/server protocol");
1499         break;
1500     case PS_LOCKBUSY:
1501         msg = GT_("lock busy on server");
1502         break;
1503     case PS_SMTP:
1504         msg = GT_("SMTP transaction");
1505         break;
1506     case PS_DNS:
1507         msg = GT_("DNS lookup");
1508         break;
1509     case PS_UNDEFINED:
1510         msg = GT_("undefined");
1511         break;
1512     }
1513     if (msg) {
1514         if (phase == FORWARDING_WAIT || phase == LISTENER_WAIT
1515                 || err == PS_SMTP)
1516             report(stderr, GT_("%s error while fetching from %s@%s and delivering to SMTP host %s\n"),
1517                     msg, ctl->remotename, ctl->server.pollname,
1518                     ctl->smtphost ? ctl->smtphost : GT_("unknown"));
1519         else
1520             report(stderr, GT_("%s error while fetching from %s@%s\n"),
1521                     msg, ctl->remotename, ctl->server.pollname);
1522     }
1523
1524 closeUp:
1525     xfree(msgsizes);
1526     ctl->folder = NULL;
1527
1528     /* execute wrapup command, if any */
1529     if (ctl->postconnect && (tmperr = system(ctl->postconnect)))
1530     {
1531         if (WIFSIGNALED(tmperr))
1532             report(stderr, GT_("post-connection command terminated with signal %d\n"), WTERMSIG(tmperr));
1533         else
1534             report(stderr, GT_("post-connection command failed with status %d\n"), WEXITSTATUS(tmperr));
1535         if (err == PS_SUCCESS)
1536             err = PS_SYNTAX;
1537     }
1538
1539     set_timeout(0); /* cancel any pending alarm */
1540     set_signal_handler(SIGALRM, alrmsave);
1541     return(err);
1542 }
1543
1544 /** retrieve messages from server using given protocol method table */
1545 int do_protocol(struct query *ctl /** parsed options with merged-in defaults */,
1546                 const struct method *proto /** protocol method table */)
1547 {
1548     int err;
1549
1550 #ifndef KERBEROS_V5
1551     if (ctl->server.authenticate == A_KERBEROS_V5)
1552     {
1553         report(stderr, GT_("Kerberos V5 support not linked.\n"));
1554         return(PS_ERROR);
1555     }
1556 #endif /* KERBEROS_V5 */
1557
1558     /* lacking methods, there are some options that may fail */
1559     if (!proto->is_old)
1560     {
1561         /* check for unsupported options */
1562         if (ctl->flush) {
1563             report(stderr,
1564                     GT_("Option --flush is not supported with %s\n"),
1565                     proto->name);
1566             return(PS_SYNTAX);
1567         }
1568         else if (ctl->fetchall) {
1569             report(stderr,
1570                     GT_("Option --all is not supported with %s\n"),
1571                     proto->name);
1572             return(PS_SYNTAX);
1573         }
1574     }
1575     if (!(proto->getsizes || proto->getpartialsizes)
1576             && NUM_SPECIFIED(ctl->limit))
1577     {
1578         report(stderr,
1579                 GT_("Option --limit is not supported with %s\n"),
1580                 proto->name);
1581         return(PS_SYNTAX);
1582     }
1583
1584     /*
1585      * If no expunge limit or we do expunges within the driver,
1586      * then just do one session, passing in any fetchlimit.
1587      */
1588     if ((ctl->keep && !ctl->flush) ||
1589         proto->retry || !NUM_SPECIFIED(ctl->expunge))
1590         return(do_session(ctl, proto, NUM_VALUE_OUT(ctl->fetchlimit)));
1591     /*
1592      * There's an expunge limit, and it isn't handled in the driver itself.
1593      * OK; do multiple sessions, each fetching a limited # of messages.
1594      * Stop if the total count of retrieved messages exceeds ctl->fetchlimit
1595      * (if it was nonzero).
1596      */
1597     else
1598     {
1599         int totalcount = 0; 
1600         int lockouts   = 0;
1601         int expunge    = NUM_VALUE_OUT(ctl->expunge);
1602         int fetchlimit = NUM_VALUE_OUT(ctl->fetchlimit);
1603
1604         do {
1605             if (fetchlimit > 0 && (expunge == 0 || expunge > fetchlimit - totalcount))
1606                 expunge = fetchlimit - totalcount;
1607             err = do_session(ctl, proto, expunge);
1608             totalcount += expunge;
1609             if (NUM_SPECIFIED(ctl->fetchlimit) && totalcount >= fetchlimit)
1610                 break;
1611             if (err != PS_LOCKBUSY)
1612                 lockouts = 0;
1613             else if (lockouts >= MAX_LOCKOUTS)
1614                 break;
1615             else /* err == PS_LOCKBUSY */
1616             {
1617                 /*
1618                  * Allow time for the server lock to release.  if we
1619                  * don't do this, we'll often hit a locked-mailbox
1620                  * condition and fail.
1621                  */
1622                 lockouts++;
1623                 sleep(3);
1624             }
1625         } while
1626             (err == PS_MAXFETCH || err == PS_LOCKBUSY);
1627
1628         return(err);
1629     }
1630 }
1631
1632
1633 /* driver.c ends here */