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