]> Pileus Git - ~andy/fetchmail/blob - driver.c
Fixup MD5 transition.
[~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 #ifdef __UNUSED__
1087                 /* 
1088                  * Don't use this.  It was an attempt to address Debian bug
1089                  * #47143 (Notify user by mail when pop server nonexistent).
1090                  * Trouble is, that doesn't work; you trip over the case 
1091                  * where your SLIP or PPP link is down...
1092                  */
1093                 /* warn the system administrator */
1094                 if (open_warning_by_mail(ctl) == 0)
1095                 {
1096                     stuff_warning(iana_charset, ctl,
1097                          GT_("Subject: Fetchmail unreachable-server warning."));
1098                     stuff_warning(NULL, ctl, "");
1099                     stuff_warning(NULL, ctl, GT_("Fetchmail could not reach the mail server %s:"),
1100                                   ctl->server.pollname);
1101                     stuff_warning(NULL, ctl, errbuf, ctl->server.pollname);
1102                     close_warning_by_mail(ctl, (struct msgblk *)NULL);
1103                 }
1104 #endif
1105             }
1106             err = PS_SOCKET;
1107             set_timeout(0);
1108             phase = oldphase;
1109             goto closeUp;
1110         }
1111
1112 #ifdef SSL_ENABLE
1113         /* Save the socket opened. Useful if Fetchmail hangs on SSLOpen 
1114          * because the socket can be closed.
1115          */
1116         mailserver_socket_temp = mailserver_socket;
1117         set_timeout(mytimeout);
1118
1119         /* perform initial SSL handshake on open connection */
1120         if (ctl->use_ssl &&
1121                 SSLOpen(mailserver_socket, ctl->sslcert, ctl->sslkey,
1122                     ctl->sslproto, ctl->sslcertck,
1123                     ctl->sslcertfile, ctl->sslcertpath,
1124                     ctl->sslfingerprint, ctl->sslcommonname ?
1125                     ctl->sslcommonname : realhost, ctl->server.pollname,
1126                     &ctl->remotename) == -1)
1127         {
1128             report(stderr, GT_("SSL connection failed.\n"));
1129             err = PS_SOCKET;
1130             goto cleanUp;
1131         }
1132         
1133         /* Fetchmail didn't hang on SSLOpen, 
1134          * then no need to set mailserver_socket_temp 
1135          */
1136         mailserver_socket_temp = -1;
1137 #endif
1138         
1139         /* A timeout is still defined before SSLOpen, 
1140          * then Fetchmail hanging on SSLOpen is handled.
1141          */
1142         set_timeout(0);
1143         phase = oldphase;
1144 #ifdef KERBEROS_V4
1145         if (ctl->server.authenticate == A_KERBEROS_V4 && (strcasecmp(proto->name,"IMAP") != 0))
1146         {
1147             set_timeout(mytimeout);
1148             err = kerberos_auth(mailserver_socket, ctl->server.truename,
1149                                ctl->server.principal);
1150             set_timeout(0);
1151             if (err != 0)
1152                 goto cleanUp;
1153         }
1154 #endif /* KERBEROS_V4 */
1155
1156 #ifdef KERBEROS_V5
1157         if (ctl->server.authenticate == A_KERBEROS_V5)
1158         {
1159             set_timeout(mytimeout);
1160             err = kerberos5_auth(mailserver_socket, ctl->server.truename);
1161             set_timeout(0);
1162             if (err != 0)
1163                 goto cleanUp;
1164         }
1165 #endif /* KERBEROS_V5 */
1166
1167         /* accept greeting message from mail server */
1168         err = (ctl->server.base_protocol->parse_response)(mailserver_socket, buf);
1169         if (err != 0)
1170             goto cleanUp;
1171
1172         /* try to get authorized to fetch mail */
1173         stage = STAGE_GETAUTH;
1174         if (ctl->server.base_protocol->getauth)
1175         {
1176             set_timeout(mytimeout);
1177             err = (ctl->server.base_protocol->getauth)(mailserver_socket, ctl, buf);
1178             set_timeout(0);
1179
1180             if (err != 0)
1181             {
1182                 if (err == PS_LOCKBUSY)
1183                     report(stderr, GT_("Lock-busy error on %s@%s\n"),
1184                           ctl->remotename,
1185                           ctl->server.truename);
1186                 else if (err == PS_SERVBUSY)
1187                     report(stderr, GT_("Server busy error on %s@%s\n"),
1188                           ctl->remotename,
1189                           ctl->server.truename);
1190                 else if (err == PS_AUTHFAIL)
1191                 {
1192                     report(stderr, GT_("Authorization failure on %s@%s%s\n"), 
1193                            ctl->remotename,
1194                            ctl->server.truename,
1195                            (ctl->wehaveauthed ? GT_(" (previously authorized)") : "")
1196                         );
1197                     if (ctl->server.authenticate == A_ANY && !ctl->wehaveauthed) {
1198                         report(stderr, GT_("For help, see http://www.fetchmail.info/fetchmail-FAQ.html#R15\n"));
1199                     }
1200
1201                     /*
1202                      * If we're running in background, try to mail the
1203                      * calling user a heads-up about the authentication 
1204                      * failure once it looks like this isn't a fluke 
1205                      * due to the server being temporarily inaccessible.
1206                      * When we get third succesive failure, we notify the user
1207                      * but only if we haven't already managed to get
1208                      * authorization.  After that, once we get authorization
1209                      * we let the user know service is restored.
1210                      */
1211                     if (run.poll_interval
1212                         && !ctl->wehavesentauthnote
1213                         && ((ctl->wehaveauthed && ++ctl->authfailcount >= 10)
1214                             || (!ctl->wehaveauthed && ++ctl->authfailcount >= 3))
1215                         && !open_warning_by_mail(ctl))
1216                     {
1217                         ctl->wehavesentauthnote = 1;
1218                         stuff_warning(iana_charset, ctl,
1219                                       GT_("Subject: fetchmail authentication failed on %s@%s"),
1220                             ctl->remotename, ctl->server.truename);
1221                         stuff_warning(NULL, ctl, "%s", "");
1222                         stuff_warning(NULL, ctl,
1223                                       GT_("Fetchmail could not get mail from %s@%s.\n"), 
1224                                       ctl->remotename,
1225                                       ctl->server.truename);
1226                         if (ctl->wehaveauthed) {
1227                             stuff_warning(NULL, ctl, GT_("\
1228 The attempt to get authorization failed.\n\
1229 Since we have already succeeded in getting authorization for this\n\
1230 connection, this is probably another failure mode (such as busy server)\n\
1231 that fetchmail cannot distinguish because the server didn't send a useful\n\
1232 error message."));
1233                             stuff_warning(NULL, ctl, GT_("\
1234 \n\
1235 However, if you HAVE changed your account details since starting the\n\
1236 fetchmail daemon, you need to stop the daemon, change your configuration\n\
1237 of fetchmail, and then restart the daemon.\n\
1238 \n\
1239 The fetchmail daemon will continue running and attempt to connect\n\
1240 at each cycle.  No future notifications will be sent until service\n\
1241 is restored."));
1242                         } else {
1243                             stuff_warning(NULL, ctl, GT_("\
1244 The attempt to get authorization failed.\n\
1245 This probably means your password is invalid, but some servers have\n\
1246 other failure modes that fetchmail cannot distinguish from this\n\
1247 because they don't send useful error messages on login failure.\n\
1248 \n\
1249 The fetchmail daemon will continue running and attempt to connect\n\
1250 at each cycle.  No future notifications will be sent until service\n\
1251 is restored."));
1252                         }
1253                         close_warning_by_mail(ctl, (struct msgblk *)NULL);
1254                     }
1255                 }
1256                 else if (err == PS_REPOLL)
1257                 {
1258                   if (outlevel >= O_VERBOSE)
1259                     report(stderr, GT_("Repoll immediately on %s@%s\n"),
1260                            ctl->remotename,
1261                            ctl->server.truename);
1262                 }
1263                 else
1264                     report(stderr, GT_("Unknown login or authentication error on %s@%s\n"),
1265                            ctl->remotename,
1266                            ctl->server.truename);
1267                     
1268                 goto cleanUp;
1269             }
1270             else
1271             {
1272                 /*
1273                  * This connection has given us authorization at least once.
1274                  *
1275                  * There are dodgy server (clubinternet.fr for example) that
1276                  * give spurious authorization failures on patently good
1277                  * account/password details, then 5 minutes later let you in!
1278                  *
1279                  * This is meant to build in some tolerance of such nasty bits
1280                  * of work.
1281                  */
1282                 ctl->wehaveauthed = 1;
1283                 /*if (ctl->authfailcount >= 3)*/
1284                 if (ctl->wehavesentauthnote)
1285                 {
1286                     ctl->wehavesentauthnote = 0;
1287                     report(stderr,
1288                            GT_("Authorization OK on %s@%s\n"),
1289                            ctl->remotename,
1290                            ctl->server.truename);
1291                     if (!open_warning_by_mail(ctl))
1292                     {
1293                         stuff_warning(iana_charset, ctl,
1294                               GT_("Subject: fetchmail authentication OK on %s@%s"), 
1295                                       ctl->remotename, ctl->server.truename);
1296                         stuff_warning(NULL, ctl, "%s", "");
1297                         stuff_warning(NULL, ctl,
1298                               GT_("Fetchmail was able to log into %s@%s.\n"), 
1299                                       ctl->remotename,
1300                                       ctl->server.truename);
1301                         stuff_warning(NULL, ctl, 
1302                                       GT_("Service has been restored.\n"));
1303                         close_warning_by_mail(ctl, (struct msgblk *)NULL);
1304                     
1305                     }
1306                 }
1307                 /*
1308                  * Reporting only after the first three
1309                  * consecutive failures, or ten consecutive
1310                  * failures after we have managed to get
1311                  * authorization.
1312                  */
1313                 ctl->authfailcount = 0;
1314             }
1315         }
1316
1317         ctl->errcount = fetches = 0;
1318
1319         /* now iterate over each folder selected */
1320         for (idp = ctl->mailboxes; idp; idp = idp->next)
1321         {
1322             ctl->folder = idp->id;
1323             pass = 0;
1324             do {
1325                 dispatches = 0;
1326                 ++pass;
1327
1328                 /* reset timeout, in case we did an IDLE */
1329                 mytimeout = ctl->server.timeout;
1330
1331                 if (outlevel >= O_DEBUG)
1332                 {
1333                     if (idp->id)
1334                         report(stdout, GT_("selecting or re-polling folder %s\n"), idp->id);
1335                     else
1336                         report(stdout, GT_("selecting or re-polling default folder\n"));
1337                 }
1338
1339                 /* compute # of messages and number of new messages waiting */
1340                 stage = STAGE_GETRANGE;
1341                 err = (ctl->server.base_protocol->getrange)(mailserver_socket, ctl, idp->id, &count, &newm, &bytes);
1342                 if (err != 0)
1343                     goto cleanUp;
1344
1345                 /* show user how many messages we downloaded */
1346                 if (idp->id)
1347                     (void) snprintf(buf, sizeof(buf),
1348                                    GT_("%s at %s (folder %s)"),
1349                                    ctl->remotename, ctl->server.pollname, idp->id);
1350                 else
1351                     (void) snprintf(buf, sizeof(buf), GT_("%s at %s"),
1352                                    ctl->remotename, ctl->server.pollname);
1353                 if (outlevel > O_SILENT)
1354                 {
1355                     if (count == -1)            /* only used for ETRN */
1356                         report(stdout, GT_("Polling %s\n"), ctl->server.truename);
1357                     else if (count != 0)
1358                     {
1359                         if (newm != -1 && (count - newm) > 0)
1360                             report_build(stdout, ngettext("%d message (%d %s) for %s", "%d messages (%d %s) for %s", (unsigned long)count),
1361                                   count,
1362                                   count - newm, 
1363                                   ngettext("seen", "seen", (unsigned long)count-newm),
1364                                   buf);
1365                         else
1366                             report_build(stdout, ngettext("%d message for %s",
1367                                                           "%d messages for %s",
1368                                                           count), 
1369                                   count, buf);
1370                         if (bytes == -1)
1371                             report_complete(stdout, ".\n");
1372                         else
1373                             report_complete(stdout, GT_(" (%d octets).\n"), bytes);
1374                     }
1375                     else
1376                     {
1377                         /* these are pointless in normal daemon mode */
1378                         if (pass == 1 && (run.poll_interval == 0 || outlevel >= O_VERBOSE))
1379                             report(stdout, GT_("No mail for %s\n"), buf); 
1380                     }
1381                 }
1382
1383                 /* very important, this is where we leave the do loop */ 
1384                 if (count == 0)
1385                     break;
1386
1387                 if (check_only)
1388                 {
1389                     if (newm == -1 || ctl->fetchall)
1390                         newm = count;
1391                     fetches = newm;     /* set error status correctly */
1392                     /*
1393                      * There used to be a `goto noerror' here, but this
1394                      * prevented checking of multiple folders.  This
1395                      * comment is a reminder in case I introduced some
1396                      * subtle bug by removing it...
1397                      */
1398                 }
1399                 else if (count > 0)
1400                 {    
1401                     int         i;
1402
1403                     /*
1404                      * Don't trust the message count passed by the server.
1405                      * Without this check, it might be possible to do a
1406                      * DNS-spoofing attack that would pass back a ridiculous 
1407                      * count, and allocate a malloc area that would overlap
1408                      * a portion of the stack.
1409                      */
1410                     if ((unsigned)count > INT_MAX/sizeof(int))
1411                     {
1412                         report(stderr, GT_("bogus message count!"));
1413                         err = PS_PROTOCOL;
1414                         goto cleanUp;
1415                     }
1416
1417                     /* 
1418                      * We need the size of each message before it's
1419                      * loaded in order to pass it to the ESMTP SIZE
1420                      * option.  If the protocol has a getsizes method,
1421                      * we presume this means it doesn't get reliable
1422                      * sizes from message fetch responses.
1423                      *
1424                      * If the protocol supports getting sizes of subset of
1425                      * messages, we skip this step now.
1426                      */
1427                     if (proto->getsizes &&
1428                         !(proto->getpartialsizes && NUM_NONZERO(ctl->fetchsizelimit)))
1429                     {
1430                         xfree(msgsizes);
1431                         msgsizes = (int *)xmalloc(sizeof(int) * count);
1432                         for (i = 0; i < count; i++)
1433                             msgsizes[i] = 0;
1434
1435                         stage = STAGE_GETSIZES;
1436                         err = (proto->getsizes)(mailserver_socket, count, msgsizes);
1437                         if (err != 0)
1438                             goto cleanUp;
1439
1440                         if (bytes == -1)
1441                         {
1442                             bytes = 0;
1443                             for (i = 0; i < count; i++)
1444                                 bytes += msgsizes[i];
1445                         }
1446                     }
1447
1448                     /* read, forward, and delete messages */
1449                     stage = STAGE_FETCH;
1450
1451                     /* fetch in lockstep mode */
1452                     err = fetch_messages(mailserver_socket, ctl, 
1453                                          count, &msgsizes,
1454                                          maxfetch,
1455                                          &fetches, &dispatches, &deletions);
1456                     if (err != PS_SUCCESS && err != PS_MAXFETCH)
1457                         goto cleanUp;
1458
1459                     if (!check_only && ctl->skipped
1460                         && run.poll_interval > 0 && !nodetach)
1461                     {
1462                         clean_skipped_list(&ctl->skipped);
1463                         send_size_warnings(ctl);
1464                     }
1465                 }
1466
1467                 /* end-of-mailbox processing before we repoll or switch to another one */
1468                 if (ctl->server.base_protocol->end_mailbox_poll)
1469                 {
1470                     tmperr = (ctl->server.base_protocol->end_mailbox_poll)(mailserver_socket, ctl);
1471                     if (tmperr) {
1472                         err = tmperr;
1473                         goto cleanUp;
1474                     }
1475                 }
1476                 /* Return now if we have reached the fetchlimit */
1477                 if (maxfetch && maxfetch <= fetches)
1478                     goto no_error;
1479             } while
1480                   /*
1481                    * Only repoll if we either had some actual forwards
1482                    * or are idling for new mails and had no errors.
1483                    * Otherwise it is far too easy to get into infinite loops.
1484                    */
1485                   (ctl->server.base_protocol->retry && (dispatches || ctl->idle) && !ctl->errcount);
1486         }
1487
1488         /* XXX: From this point onwards, preserve err unless a new error has occurred */
1489
1490     no_error:
1491         /* PS_SUCCESS, PS_MAXFETCH: ordinary termination with no errors -- officially log out */
1492         stage = STAGE_LOGOUT;
1493         tmperr = (ctl->server.base_protocol->logout_cmd)(mailserver_socket, ctl);
1494         if (tmperr != PS_SUCCESS)
1495             err = tmperr;
1496         /*
1497          * Hmmmm...arguably this would be incorrect if we had fetches but
1498          * no dispatches (due to oversized messages, etc.)
1499          */
1500         else if (err == PS_SUCCESS && fetches == 0)
1501             err = PS_NOMAIL;
1502         /*
1503          * Close all SMTP delivery sockets.  For optimum performance
1504          * we'd like to hold them open til end of run, but (1) this
1505          * loses if our poll interval is longer than the MTA's
1506          * inactivity timeout, and (2) some MTAs (like smail) don't
1507          * deliver after each message, but rather queue up mail and
1508          * wait to actually deliver it until the input socket is
1509          * closed.
1510          *
1511          * don't send QUIT for ODMR case because we're acting as a
1512          * proxy between the SMTP server and client.
1513          */
1514         smtp_close(ctl, ctl->server.protocol != P_ODMR);
1515         cleanupSockClose(mailserver_socket);
1516         goto closeUp;
1517
1518     cleanUp:
1519         /* we only get here on error */
1520         if (err != 0 && err != PS_SOCKET && err != PS_REPOLL)
1521         {
1522             stage = STAGE_LOGOUT;
1523             (ctl->server.base_protocol->logout_cmd)(mailserver_socket, ctl);
1524         }
1525
1526         /* try to clean up all streams */
1527         release_sink(ctl);
1528         /*
1529          * Sending SMTP QUIT on signal is theoretically nice, but led
1530          * to a subtle bug.  If fetchmail was terminated by signal
1531          * while it was shipping message text, it would hang forever
1532          * waiting for a command acknowledge.  In theory we could
1533          * enable the QUIT only outside of the message send.  In
1534          * practice, we don't care.  All mailservers hang up on a
1535          * dropped TCP/IP connection anyway.
1536          */
1537         smtp_close(ctl, 0);
1538         if (mailserver_socket != -1) {
1539             cleanupSockClose(mailserver_socket);
1540         }
1541         /* If there was a connect timeout, the socket should be closed.
1542          * mailserver_socket_temp contains the socket to close.
1543          */
1544         if (mailserver_socket_temp != -1) {
1545             cleanupSockClose(mailserver_socket_temp);
1546             mailserver_socket_temp = -1;
1547         }
1548     }
1549
1550     /* no report on PS_AUTHFAIL */
1551     msg = NULL;
1552     switch (err)
1553     {
1554     case PS_SOCKET:
1555         msg = GT_("socket");
1556         break;
1557     case PS_SYNTAX:
1558         msg = GT_("missing or bad RFC822 header");
1559         break;
1560     case PS_IOERR:
1561         msg = GT_("MDA");
1562         break;
1563     case PS_ERROR:
1564         msg = GT_("client/server synchronization");
1565         break;
1566     case PS_PROTOCOL:
1567         msg = GT_("client/server protocol");
1568         break;
1569     case PS_LOCKBUSY:
1570         msg = GT_("lock busy on server");
1571         break;
1572     case PS_SMTP:
1573         msg = GT_("SMTP transaction");
1574         break;
1575     case PS_DNS:
1576         msg = GT_("DNS lookup");
1577         break;
1578     case PS_UNDEFINED:
1579         msg = GT_("undefined");
1580         break;
1581     }
1582     if (msg) {
1583         if (phase == FORWARDING_WAIT || phase == LISTENER_WAIT
1584                 || err == PS_SMTP)
1585             report(stderr, GT_("%s error while fetching from %s@%s and delivering to SMTP host %s\n"),
1586                     msg, ctl->remotename, ctl->server.pollname,
1587                     ctl->smtphost ? ctl->smtphost : GT_("unknown"));
1588         else
1589             report(stderr, GT_("%s error while fetching from %s@%s\n"),
1590                     msg, ctl->remotename, ctl->server.pollname);
1591     }
1592
1593 closeUp:
1594     xfree(msgsizes);
1595     ctl->folder = NULL;
1596
1597     /* execute wrapup command, if any */
1598     if (ctl->postconnect && (tmperr = system(ctl->postconnect)))
1599     {
1600         if (WIFSIGNALED(tmperr))
1601             report(stderr, GT_("post-connection command terminated with signal %d\n"), WTERMSIG(tmperr));
1602         else
1603             report(stderr, GT_("post-connection command failed with status %d\n"), WEXITSTATUS(tmperr));
1604         if (err == PS_SUCCESS)
1605             err = PS_SYNTAX;
1606     }
1607
1608     set_timeout(0); /* cancel any pending alarm */
1609     set_signal_handler(SIGALRM, alrmsave);
1610     return(err);
1611 }
1612
1613 /** retrieve messages from server using given protocol method table */
1614 int do_protocol(struct query *ctl /** parsed options with merged-in defaults */,
1615                 const struct method *proto /** protocol method table */)
1616 {
1617     int err;
1618
1619 #ifndef KERBEROS_V4
1620     if (ctl->server.authenticate == A_KERBEROS_V4)
1621     {
1622         report(stderr, GT_("Kerberos V4 support not linked.\n"));
1623         return(PS_ERROR);
1624     }
1625 #endif /* KERBEROS_V4 */
1626
1627 #ifndef KERBEROS_V5
1628     if (ctl->server.authenticate == A_KERBEROS_V5)
1629     {
1630         report(stderr, GT_("Kerberos V5 support not linked.\n"));
1631         return(PS_ERROR);
1632     }
1633 #endif /* KERBEROS_V5 */
1634
1635     /* lacking methods, there are some options that may fail */
1636     if (!proto->is_old)
1637     {
1638         /* check for unsupported options */
1639         if (ctl->flush) {
1640             report(stderr,
1641                     GT_("Option --flush is not supported with %s\n"),
1642                     proto->name);
1643             return(PS_SYNTAX);
1644         }
1645         else if (ctl->fetchall) {
1646             report(stderr,
1647                     GT_("Option --all is not supported with %s\n"),
1648                     proto->name);
1649             return(PS_SYNTAX);
1650         }
1651     }
1652     if (!(proto->getsizes || proto->getpartialsizes)
1653             && NUM_SPECIFIED(ctl->limit))
1654     {
1655         report(stderr,
1656                 GT_("Option --limit is not supported with %s\n"),
1657                 proto->name);
1658         return(PS_SYNTAX);
1659     }
1660
1661     /*
1662      * If no expunge limit or we do expunges within the driver,
1663      * then just do one session, passing in any fetchlimit.
1664      */
1665     if ((ctl->keep && !ctl->flush) ||
1666         proto->retry || !NUM_SPECIFIED(ctl->expunge))
1667         return(do_session(ctl, proto, NUM_VALUE_OUT(ctl->fetchlimit)));
1668     /*
1669      * There's an expunge limit, and it isn't handled in the driver itself.
1670      * OK; do multiple sessions, each fetching a limited # of messages.
1671      * Stop if the total count of retrieved messages exceeds ctl->fetchlimit
1672      * (if it was nonzero).
1673      */
1674     else
1675     {
1676         int totalcount = 0; 
1677         int lockouts   = 0;
1678         int expunge    = NUM_VALUE_OUT(ctl->expunge);
1679         int fetchlimit = NUM_VALUE_OUT(ctl->fetchlimit);
1680
1681         do {
1682             if (fetchlimit > 0 && (expunge == 0 || expunge > fetchlimit - totalcount))
1683                 expunge = fetchlimit - totalcount;
1684             err = do_session(ctl, proto, expunge);
1685             totalcount += expunge;
1686             if (NUM_SPECIFIED(ctl->fetchlimit) && totalcount >= fetchlimit)
1687                 break;
1688             if (err != PS_LOCKBUSY)
1689                 lockouts = 0;
1690             else if (lockouts >= MAX_LOCKOUTS)
1691                 break;
1692             else /* err == PS_LOCKBUSY */
1693             {
1694                 /*
1695                  * Allow time for the server lock to release.  if we
1696                  * don't do this, we'll often hit a locked-mailbox
1697                  * condition and fail.
1698                  */
1699                 lockouts++;
1700                 sleep(3);
1701             }
1702         } while
1703             (err == PS_MAXFETCH || err == PS_LOCKBUSY);
1704
1705         return(err);
1706     }
1707 }
1708
1709
1710 /* driver.c ends here */