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