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