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