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