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