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