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