]> Pileus Git - ~andy/fetchmail/blob - driver.c
ddae6fc064c3bd9388f3a529aedcc8b3707a1866
[~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                 suppress_delete = TRUE;
547             }
548             if (outlevel > O_SILENT)
549             {
550                 /* old messages are already handled above */
551                 report_build(stdout, 
552                              GT_("skipping message %s@%s:%d (%d octets)"),
553                              ctl->remotename, ctl->server.truename, num,
554                              msgsize);
555                 switch (msgcode)
556                 {
557                 case MSGLEN_INVALID:
558                     /*
559                      * Invalid lengths are produced by Post Office/NT's
560                      * annoying habit of randomly prepending bogus
561                      * LIST items of length -1.  Patrick Audley
562                      * <paudley@pobox.com> tells us: LIST shows a
563                      * size of -1, RETR and TOP return "-ERR
564                      * System error - couldn't open message", and
565                      * DELE succeeds but doesn't actually delete
566                      * the message.
567                      */
568                     report_build(stdout, GT_(" (length -1)"));
569                     break;
570                 case MSGLEN_TOOLARGE:
571                     report_build(stdout, GT_(" (oversized)"));
572                     break;
573                 }
574             }
575         }
576         else
577         {
578             flag wholesize = !ctl->server.base_protocol->fetch_body;
579             flag separatefetchbody = (ctl->server.base_protocol->fetch_body) ? TRUE : FALSE;
580
581             /* request a message */
582             err = (ctl->server.base_protocol->fetch_headers)(mailserver_socket,ctl,num, &len);
583             if (err == PS_TRANSIENT)    /* server is probably Exchange */
584             {
585                 report(stdout,
586                              GT_("couldn't fetch headers, message %s@%s:%d (%d octets)\n"),
587                              ctl->remotename, ctl->server.truename, num,
588                              msgsize);
589                 continue;
590             }
591             else if (err != 0)
592                 return(err);
593
594             /* -1 means we didn't see a size in the response */
595             if (len == -1)
596             {
597                 len = msgsize;
598                 wholesize = TRUE;
599             }
600
601             if (outlevel > O_SILENT)
602             {
603                 report_build(stdout, GT_("reading message %s@%s:%d of %d"),
604                              ctl->remotename, ctl->server.truename,
605                              num, count);
606
607                 if (len > 0)
608                     report_build(stdout, wholesize ? GT_(" (%d octets)")
609                                  : GT_(" (%d header octets)"), len);
610                 if (outlevel >= O_VERBOSE)
611                     report_complete(stdout, "\n");
612                 else
613                     report_complete(stdout, " ");
614             }
615
616             /* 
617              * Read the message headers and ship them to the
618              * output sink.  
619              */
620             err = readheaders(mailserver_socket, len, msgsize,
621                              ctl, num,
622                              /* pass the suppress_readbody flag only if the underlying
623                               * protocol does not fetch the body separately */
624                              separatefetchbody ? 0 : &suppress_readbody);
625             if (err == PS_RETAINED)
626                 suppress_forward = suppress_delete = retained = TRUE;
627             else if (err == PS_TRANSIENT)
628                 suppress_delete = suppress_forward = TRUE;
629             else if (err == PS_REFUSED)
630                 suppress_forward = TRUE;
631             else if (err == PS_TRUNCATED)
632                 suppress_readbody = TRUE;
633             else if (err)
634                 return(err);
635
636             /* tell server we got it OK and resynchronize */
637             if (separatefetchbody && ctl->server.base_protocol->trail)
638             {
639                 if (outlevel >= O_VERBOSE && !isafile(1))
640                 {
641                     fputc('\n', stdout);
642                     fflush(stdout);
643                 }
644
645                 if ((err = (ctl->server.base_protocol->trail)(mailserver_socket, ctl, num)))
646                     return(err);
647             }
648
649             /* do not read the body which is not being forwarded only if
650              * the underlying protocol allows the body to be fetched
651              * separately */
652             if (separatefetchbody && suppress_forward)
653                 suppress_readbody = TRUE;
654
655             /* 
656              * If we're using IMAP4 or something else that
657              * can fetch headers separately from bodies,
658              * it's time to request the body now.  This
659              * fetch may be skipped if we got an anti-spam
660              * or other PS_REFUSED error response during
661              * readheaders.
662              */
663             if (!suppress_readbody)
664             {
665                 if (separatefetchbody)
666                 {
667                     len = -1;
668                     if ((err=(ctl->server.base_protocol->fetch_body)(mailserver_socket,ctl,num,&len)))
669                         return(err);
670                     /*
671                      * Work around a bug in Novell's
672                      * broken GroupWise IMAP server;
673                      * its body FETCH response is missing
674                      * the required length for the data
675                      * string.  This violates RFC2060.
676                      */
677                     if (len == -1)
678                         len = msgsize - msgblk.msglen;
679                     if (outlevel > O_SILENT && !wholesize)
680                         report_complete(stdout,
681                                         GT_(" (%d body octets) "), len);
682                 }
683
684                 /* process the body now */
685                 err = readbody(mailserver_socket,
686                               ctl,
687                               !suppress_forward,
688                               len);
689                 if (err == PS_TRANSIENT)
690                     suppress_delete = suppress_forward = TRUE;
691                 else if (err)
692                     return(err);
693
694                 /* tell server we got it OK and resynchronize */
695                 if (ctl->server.base_protocol->trail)
696                 {
697                     if (outlevel >= O_VERBOSE && !isafile(1))
698                     {
699                         fputc('\n', stdout);
700                         fflush(stdout);
701                     }
702
703                     err = (ctl->server.base_protocol->trail)(mailserver_socket, ctl, num);
704                     if (err != 0)
705                         return(err);
706                 }
707             }
708
709             /* count # messages forwarded on this pass */
710             if (!suppress_forward)
711                 (*dispatches)++;
712
713             /*
714              * Check to see if the numbers matched?
715              *
716              * Yes, some servers foo this up horribly.
717              * All IMAP servers seem to get it right, and
718              * so does Eudora QPOP at least in 2.xx
719              * versions.
720              *
721              * Microsoft Exchange gets it completely
722              * wrong, reporting compressed rather than
723              * actual sizes (so the actual length of
724              * message is longer than the reported size).
725              * Another fine example of Microsoft brain death!
726              *
727              * Some older POP servers, like the old UCB
728              * POP server and the pre-QPOP QUALCOMM
729              * versions, report a longer size in the LIST
730              * response than actually gets shipped up.
731              * It's unclear what is going on here, as the
732              * QUALCOMM server (at least) seems to be
733              * reporting the on-disk size correctly.
734              */
735             if (msgblk.msglen != msgsize)
736             {
737                 if (outlevel >= O_DEBUG)
738                     report(stdout,
739                            GT_("message %s@%s:%d was not the expected length (%d actual != %d expected)\n"),
740                            ctl->remotename, ctl->server.truename, num,
741                            msgblk.msglen, msgsize);
742             }
743
744             /* end-of-message processing starts here */
745             if (!close_sink(ctl, &msgblk, !suppress_forward))
746             {
747                 ctl->errcount++;
748                 suppress_delete = TRUE;
749             }
750             if (!retained)
751                 (*fetches)++;
752         }
753
754 flagthemail:
755         /*
756          * At this point in flow of control, either
757          * we've bombed on a protocol error or had
758          * delivery refused by the SMTP server
759          * (unlikely -- I've never seen it) or we've
760          * seen `accepted for delivery' and the
761          * message is shipped.  It's safe to mark the
762          * message seen and delete it on the server
763          * now.
764          */
765
766         /* maybe we delete this message now? */
767         if (retained)
768         {
769             if (outlevel > O_SILENT) 
770                 report(stdout, GT_(" retained\n"));
771         }
772         else if (ctl->server.base_protocol->delete
773                  && !suppress_delete
774                  && ((msgcode >= 0 && !ctl->keep)
775                      /* XXX FIXME: Debian's patch uses here:
776                       * 
777                       * (msgcode == MSGLEN_OLD || msgcode ==
778                       * MSGLEN_TOOLARGE) && ctl->flush
779                       *
780                       * do we want to flush oversized messages? */
781                      || (msgcode == MSGLEN_OLD && ctl->flush)))
782         {
783             (*deletions)++;
784             if (outlevel > O_SILENT) 
785                 report_complete(stdout, GT_(" flushed\n"));
786             err = (ctl->server.base_protocol->delete)(mailserver_socket, ctl, num);
787             if (err != 0)
788                 return(err);
789         }
790         else
791         {
792             if (   (outlevel >= O_VERBOSE) ||
793                         /* To avoid flooding the syslog when using --keep,
794                          * report "Skipped message" only when:
795                          *  1) --verbose is on, or
796                          *  2) fetchmail does not use syslog, or
797                          *  3) the message was skipped for some other
798                          *     reason than just being old.
799                          */
800                    (outlevel > O_SILENT && (!run.use_syslog || msgcode != MSGLEN_OLD))
801                )
802             report_complete(stdout, GT_(" not flushed\n"));
803
804             /* maybe we mark this message as seen now? */
805             if (ctl->server.base_protocol->mark_seen
806                 && !suppress_delete
807                 && (msgcode >= 0 && ctl->keep))
808             {
809                 err = (ctl->server.base_protocol->mark_seen)(mailserver_socket, ctl, num);
810                 if (err != 0)
811                     return(err);
812             }
813         }
814
815         /* perhaps this as many as we're ready to handle */
816         if (maxfetch && maxfetch <= *fetches && num < count)
817         {
818             report(stdout,
819                    ngettext("fetchlimit %d reached; %d message left on server %s account %s\n",
820                             "fetchlimit %d reached; %d messages left on server %s account %s\n", count - *fetches),
821                    maxfetch, count - *fetches, ctl->server.truename, ctl->remotename);
822             return(PS_MAXFETCH);
823         }
824     }
825
826     return(PS_SUCCESS);
827 }
828
829 /* retrieve messages from server using given protocol method table */
830 static int do_session(
831         /* parsed options with merged-in defaults */
832         struct query *ctl,
833         /* protocol method table */
834         const struct method *proto,
835         /* maximum number of messages to fetch */
836         const int maxfetch)
837 {
838     static int *msgsizes;
839     volatile int err, mailserver_socket = -1;   /* pacifies -Wall */
840     int deletions = 0, js;
841     const char *msg;
842     SIGHANDLERTYPE pipesave;
843     SIGHANDLERTYPE alrmsave;
844
845     ctl->server.base_protocol = proto;
846
847     msgsizes = NULL;
848     pass = 0;
849     err = 0;
850     init_transact(proto);
851
852     /* set up the server-nonresponse timeout */
853     alrmsave = set_signal_handler(SIGALRM, timeout_handler);
854     mytimeout = ctl->server.timeout;
855
856     /* set up the broken-pipe timeout */
857     pipesave = set_signal_handler(SIGPIPE, sigpipe_handler);
858
859     if ((js = setjmp(restart)))
860     {
861         /* exception caught */
862 #ifdef HAVE_SIGPROCMASK
863         /*
864          * Don't rely on setjmp() to restore the blocked-signal mask.
865          * It does this under BSD but is required not to under POSIX.
866          *
867          * If your Unix doesn't have sigprocmask, better hope it has
868          * BSD-like behavior.  Otherwise you may see fetchmail get
869          * permanently wedged after a second timeout on a bad read,
870          * because alarm signals were blocked after the first.
871          */
872         sigset_t        allsigs;
873
874         sigfillset(&allsigs);
875         sigprocmask(SIG_UNBLOCK, &allsigs, NULL);
876 #endif /* HAVE_SIGPROCMASK */
877         
878         if (js == THROW_SIGPIPE)
879         {
880             set_signal_handler(SIGPIPE, SIG_IGN);
881             report(stdout,
882                    GT_("SIGPIPE thrown from an MDA or a stream socket error\n"));
883             wait(0);
884         }
885         else if (js == THROW_TIMEOUT)
886         {
887             if (phase == OPEN_WAIT)
888                 report(stdout,
889                        GT_("timeout after %d seconds waiting to connect to server %s.\n"),
890                        ctl->server.timeout, ctl->server.pollname);
891             else if (phase == SERVER_WAIT)
892                 report(stdout,
893                        GT_("timeout after %d seconds waiting for server %s.\n"),
894                        ctl->server.timeout, ctl->server.pollname);
895             else if (phase == FORWARDING_WAIT)
896                 report(stdout,
897                        GT_("timeout after %d seconds waiting for %s.\n"),
898                        ctl->server.timeout,
899                        ctl->mda ? "MDA" : "SMTP");
900             else if (phase == LISTENER_WAIT)
901                 report(stdout,
902                        GT_("timeout after %d seconds waiting for listener to respond.\n"), ctl->server.timeout);
903             else
904                 report(stdout, 
905                        GT_("timeout after %d seconds.\n"), ctl->server.timeout);
906
907             /*
908              * If we've exceeded our threshold for consecutive timeouts, 
909              * try to notify the user, then mark the connection wedged.
910              * Don't do this if the connection can idle, though; idle
911              * timeouts just mean the frequency of mail is low.
912              */
913             if (timeoutcount > MAX_TIMEOUTS 
914                 && !open_warning_by_mail(ctl, (struct msgblk *)NULL))
915             {
916                 stuff_warning(iana_charset, ctl,
917                               GT_("Subject: fetchmail sees repeated timeouts"));
918                 stuff_warning(NULL, ctl, "");
919                 stuff_warning(NULL, ctl,
920                               GT_("Fetchmail saw more than %d timeouts while attempting to get mail from %s@%s.\n"), 
921                               MAX_TIMEOUTS,
922                               ctl->remotename, ctl->server.truename);
923                 stuff_warning(NULL, ctl, 
924     GT_("This could mean that your mailserver is stuck, or that your SMTP\n" \
925     "server is wedged, or that your mailbox file on the server has been\n" \
926     "corrupted by a server error.  You can run `fetchmail -v -v' to\n" \
927     "diagnose the problem.\n\n" \
928     "Fetchmail won't poll this mailbox again until you restart it.\n"));
929                 close_warning_by_mail(ctl, (struct msgblk *)NULL);
930                 ctl->wedged = TRUE;
931             }
932         }
933
934         err = PS_SOCKET;
935         goto cleanUp;
936     }
937     else
938     {
939         /* setjmp returned zero -> normal operation */
940         char buf[MSGBUFSIZE+1], *realhost;
941         int count, new, bytes;
942 #ifdef INET6_ENABLE
943         int fetches, dispatches, oldphase;
944 #else /* INET6_ENABLE */
945         int port, fetches, dispatches, oldphase;
946 #endif /* INET6_ENABLE */
947         struct idlist *idp;
948
949         /* execute pre-initialization command, if any */
950         if (ctl->preconnect && (err = system(ctl->preconnect)))
951         {
952             report(stderr, 
953                    GT_("pre-connection command failed with status %d\n"), err);
954             err = PS_SYNTAX;
955             goto closeUp;
956         }
957
958         /* open a socket to the mail server */
959         oldphase = phase;
960         phase = OPEN_WAIT;
961         set_timeout(mytimeout);
962 #ifndef INET6_ENABLE
963 #ifdef SSL_ENABLE
964         port = ctl->server.port ? ctl->server.port : ( ctl->use_ssl ? ctl->server.base_protocol->sslport : ctl->server.base_protocol->port );
965 #else
966         port = ctl->server.port ? ctl->server.port : ctl->server.base_protocol->port;
967 #endif
968 #endif /* !INET6_ENABLE */
969
970 #ifdef HAVE_PKG_hesiod
971         /* If either the pollname or vianame are "hesiod" we want to
972            lookup the user's hesiod pobox host */
973         if (!strcasecmp(ctl->server.queryname, "hesiod")) {
974             struct hes_postoffice *hes_p;
975             hes_p = hes_getmailhost(ctl->remotename);
976             if (hes_p != NULL && strcmp(hes_p->po_type, "POP") == 0) {
977                  free(ctl->server.queryname);
978                  ctl->server.queryname = xstrdup(hes_p->po_host);
979                  if (ctl->server.via)
980                      free(ctl->server.via);
981                  ctl->server.via = xstrdup(hes_p->po_host);
982             } else {
983                  report(stderr,
984                         GT_("couldn't find HESIOD pobox for %s\n"),
985                         ctl->remotename);
986             }
987         }
988 #endif /* HESIOD */
989
990 #ifdef HAVE_GETHOSTBYNAME
991         /*
992          * Canonicalize the server truename for later use.  This also
993          * functions as a probe for whether the mailserver is accessible.
994          * We try it on each poll cycle until we get a result.  This way,
995          * fetchmail won't fail if started up when the network is inaccessible.
996          */
997         if (ctl->server.dns && !ctl->server.trueaddr)
998         {
999             if (ctl->server.lead_server)
1000             {
1001                 char    *leadname = ctl->server.lead_server->truename;
1002
1003                 /* prevent core dump from ill-formed or duplicate entry */
1004                 if (!leadname)
1005                 {
1006                     report(stderr, GT_("Lead server has no name.\n"));
1007                     err = PS_DNS;
1008                     set_timeout(0);
1009                     phase = oldphase;
1010                     goto closeUp;
1011                 }
1012
1013                 ctl->server.truename = xstrdup(leadname);
1014             }
1015             else
1016             {
1017 #ifdef INET6_ENABLE
1018                 struct addrinfo hints, *res;
1019                 int error;
1020
1021                 memset(&hints, 0, sizeof(hints));
1022                 hints.ai_socktype = SOCK_STREAM;
1023                 hints.ai_family = AF_UNSPEC;
1024                 hints.ai_flags = AI_CANONNAME;
1025
1026                 error = getaddrinfo(ctl->server.queryname, NULL, &hints, &res);
1027                 if (error)
1028                 {
1029                     report(stderr,
1030                            GT_("couldn't find canonical DNS name of %s (%s)\n"),
1031                            ctl->server.pollname, ctl->server.queryname);
1032                     err = PS_DNS;
1033                     set_timeout(0);
1034                     phase = oldphase;
1035                     goto closeUp;
1036                 }
1037                 else
1038                 {
1039                     ctl->server.truename=xstrdup(res->ai_canonname);
1040                     ctl->server.trueaddr=xmalloc(res->ai_addrlen);
1041                     memcpy(ctl->server.trueaddr, res->ai_addr, res->ai_addrlen);
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.netsec, ctl->server.plugin)) == -1)
1085 #else /* INET6_ENABLE */
1086         if ((mailserver_socket = SockOpen(realhost, port, NULL, 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                         strcpy(errbuf, GT_("host is unknown."));
1111 #ifndef __BEOS__
1112                     else if (h_errno == NO_ADDRESS)
1113                         strcpy(errbuf, GT_("name is valid but has no IP address."));
1114 #endif
1115                     else if (h_errno == NO_RECOVERY)
1116                         strcpy(errbuf, GT_("unrecoverable name server error."));
1117                     else if (h_errno == TRY_AGAIN)
1118                         strcpy(errbuf, GT_("temporary name server error."));
1119                     else
1120                         snprintf (errbuf, sizeof(errbuf),
1121                                 GT_("unknown DNS error %d."), h_errno);
1122                 }
1123                 else
1124 #endif /* HAVE_RES_SEARCH */
1125                     strcpy(errbuf, strerror(err_no));
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 */