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