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