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