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