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