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