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