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