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