]> Pileus Git - ~andy/fetchmail/blob - driver.c
Tracepolls switch implemented.
[~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  <ctype.h>
13 #include  <string.h>
14 #ifdef HAVE_MEMORY_H
15 #include  <memory.h>
16 #endif /* HAVE_MEMORY_H */
17 #if defined(STDC_HEADERS)
18 #include  <stdlib.h>
19 #endif
20 #if defined(HAVE_UNISTD_H)
21 #include <unistd.h>
22 #endif
23 #if defined(HAVE_STDARG_H)
24 #include  <stdarg.h>
25 #else
26 #include  <varargs.h>
27 #endif
28 #if defined(HAVE_SYS_ITIMER_H)
29 #include <sys/itimer.h>
30 #endif
31 #include  <sys/time.h>
32 #include  <signal.h>
33
34 #ifdef HAVE_NET_SOCKET_H
35 #include <net/socket.h>
36 #endif
37
38 #ifdef HAVE_RES_SEARCH
39 #include <netdb.h>
40 #include "mx.h"
41 #endif /* HAVE_RES_SEARCH */
42
43 #include "kerberos.h"
44 #ifdef KERBEROS_V4
45 #include <netinet/in.h>
46 #include <netdb.h>
47 #endif /* KERBEROS_V4 */
48
49 #include "i18n.h"
50
51 #include "socket.h"
52 #include "fetchmail.h"
53 #include "tunable.h"
54
55 /* throw types for runtime errors */
56 #define THROW_TIMEOUT   1               /* server timed out */
57 #define THROW_SIGPIPE   2               /* SIGPIPE on stream socket */
58
59 #ifndef strstr          /* glibc-2.1 declares this as a macro */
60 extern char *strstr();  /* needed on sysV68 R3V7.1. */
61 #endif /* strstr */
62
63 int batchcount;         /* count of messages sent in current batch */
64 flag peek_capable;      /* can we peek for better error recovery? */
65 int pass;               /* how many times have we re-polled? */
66 int stage;              /* where are we? */
67 int phase;              /* where are we, for error-logging purposes? */
68 int mytimeout;          /* value of nonreponse timeout */
69 int suppress_tags;      /* emit tags? */
70 char shroud[PASSWORDLEN];       /* string to shroud in debug output */
71
72 static const struct method *protocol;
73 static jmp_buf  restart;
74
75 char tag[TAGLEN];
76 static int tagnum;
77 #define GENSYM  (sprintf(tag, "A%04d", ++tagnum % TAGMOD), tag)
78
79 static int timeoutcount;                /* count consecutive timeouts */
80 static int msglen;                      /* actual message length */
81
82 void set_timeout(int timeleft)
83 /* reset the nonresponse-timeout */
84 {
85 #if !defined(__EMX__) && !defined(__BEOS__) 
86     struct itimerval ntimeout;
87
88     if (timeleft == 0)
89         timeoutcount = 0;
90
91     ntimeout.it_interval.tv_sec = ntimeout.it_interval.tv_usec = 0;
92     ntimeout.it_value.tv_sec  = timeleft;
93     ntimeout.it_value.tv_usec = 0;
94     setitimer(ITIMER_REAL, &ntimeout, (struct itimerval *)NULL);
95 #endif
96 }
97
98 static void timeout_handler (int signal)
99 /* handle SIGALRM signal indicating a server timeout */
100 {
101     timeoutcount++;
102     longjmp(restart, THROW_TIMEOUT);
103 }
104
105 static void sigpipe_handler (int signal)
106 /* handle SIGPIPE signal indicating a broken stream socket */
107 {
108     longjmp(restart, THROW_SIGPIPE);
109 }
110
111 static int accept_count, reject_count;
112
113 static void map_name(const char *name, struct query *ctl, struct idlist **xmit_names)
114 /* add given name to xmit_names if it matches declared localnames */
115 /*   name:       name to map */
116 /*   ctl:        list of permissible aliases */
117 /*   xmit_names: list of recipient names parsed out */
118 {
119     const char  *lname;
120     int off = 0;
121     
122     lname = idpair_find(&ctl->localnames, name+off);
123     if (!lname && ctl->wildcard)
124         lname = name+off;
125
126     if (lname != (char *)NULL)
127     {
128         if (outlevel >= O_DEBUG)
129             report(stdout, _("mapped %s to local %s\n"), name, lname);
130         save_str(xmit_names, lname, XMIT_ACCEPT);
131         accept_count++;
132     }
133 }
134
135 static void find_server_names(const char *hdr,
136                               struct query *ctl,
137                               struct idlist **xmit_names)
138 /* parse names out of a RFC822 header into an ID list */
139 /*   hdr:               RFC822 header in question */
140 /*   ctl:               list of permissible aliases */
141 /*   xmit_names:        list of recipient names parsed out */
142 {
143     if (hdr == (char *)NULL)
144         return;
145     else
146     {
147         char    *cp;
148
149         for (cp = nxtaddr(hdr);
150              cp != NULL;
151              cp = nxtaddr(NULL))
152         {
153             char        *atsign;
154
155             /*
156              * If the name of the user begins with a qmail virtual
157              * domain prefix, ignore the prefix.  Doing this here
158              * means qvirtual will work either with ordinary name
159              * mapping or with a localdomains option.
160              */
161             if (ctl->server.qvirtual)
162             {
163                 int sl = strlen(ctl->server.qvirtual);
164  
165                 if (!strncasecmp(cp, ctl->server.qvirtual, sl))
166                     cp += sl;
167             }
168
169             if ((atsign = strchr(cp, '@'))) {
170                 struct idlist   *idp;
171
172                 /*
173                  * Does a trailing segment of the hostname match something
174                  * on the localdomains list?  If so, save the whole name
175                  * and keep going.
176                  */
177                 for (idp = ctl->server.localdomains; idp; idp = idp->next) {
178                     char        *rhs;
179
180                     rhs = atsign + (strlen(atsign) - strlen(idp->id));
181                     if (rhs > atsign &&
182                         (rhs[-1] == '.' || rhs[-1] == '@') &&
183                         strcasecmp(rhs, idp->id) == 0)
184                     {
185                         if (outlevel >= O_DEBUG)
186                             report(stdout, _("passed through %s matching %s\n"), 
187                                   cp, idp->id);
188                         save_str(xmit_names, cp, XMIT_ACCEPT);
189                         accept_count++;
190                         goto nomap;
191                     }
192                 }
193
194                 /* if we matched a local domain, idp != NULL */
195                 if (!idp)
196                 {
197                     /*
198                      * Check to see if the right-hand part is an alias
199                      * or MX equivalent of the mailserver.  If it's
200                      * not, skip this name.  If it is, we'll keep
201                      * going and try to find a mapping to a client name.
202                      */
203                     if (!is_host_alias(atsign+1, ctl))
204                     {
205                         save_str(xmit_names, cp, XMIT_REJECT);
206                         reject_count++;
207                         continue;
208                     }
209                 }
210                 atsign[0] = '\0';
211                 map_name(cp, ctl, xmit_names);
212             nomap:;
213             }
214         }
215     }
216 }
217
218 /*
219  * Return zero on a syntactically invalid address, nz on a valid one.
220  *
221  * This used to be strchr(a, '.'), but it turns out that lines like this
222  *
223  * Received: from punt-1.mail.demon.net by mailstore for markb@ordern.com
224  *          id 938765929:10:27223:2; Fri, 01 Oct 99 08:18:49 GMT
225  *
226  * are not uncommon.  So now we just check that the following token is
227  * not itself an email address.
228  */
229 #define VALID_ADDRESS(a)        !strchr(a, '@')
230
231 static char *parse_received(struct query *ctl, char *bufp)
232 /* try to extract real address from the Received line */
233 /* If a valid Received: line is found, we return the full address in
234  * a buffer which can be parsed from nxtaddr().  This is to ansure that
235  * the local domain part of the address can be passed along in 
236  * find_server_names() if it contains one.
237  * Note: We should return a dummy header containing the address 
238  * which makes nxtaddr() behave correctly. 
239  */
240 {
241     char *base, *ok = (char *)NULL;
242     static char rbuf[HOSTLEN + USERNAMELEN + 4]; 
243
244     /*
245      * Try to extract the real envelope addressee.  We look here
246      * specifically for the mailserver's Received line.
247      * Note: this will only work for sendmail, or an MTA that
248      * shares sendmail's convention for embedding the envelope
249      * address in the Received line.  Sendmail itself only
250      * does this when the mail has a single recipient.
251      */
252     if (outlevel >= O_DEBUG)
253         report(stdout, _("analyzing Received line:\n%s"), bufp);
254
255     /* search for whitepace-surrounded "by" followed by valid address */
256     for (base = bufp;  ; base = ok + 2)
257     {
258         if (!(ok = strstr(base, "by")))
259             break;
260         else if (!isspace(ok[-1]) || !isspace(ok[2]))
261             continue;
262         else
263         {
264             char        *sp, *tp;
265
266             /* extract space-delimited token after "by" */
267             for (sp = ok + 2; isspace(*sp); sp++)
268                 continue;
269             tp = rbuf;
270             for (; !isspace(*sp); sp++)
271                 *tp++ = *sp;
272             *tp = '\0';
273
274             /* look for valid address */
275             if (VALID_ADDRESS(rbuf))
276                 break;
277             else
278                 ok = sp - 1;    /* arrange to skip this token */
279         }
280     }
281     if (ok)
282     {
283         /*
284          * If it's a DNS name of the mail server, look for the
285          * recipient name after a following "for".  Otherwise
286          * punt.
287          */
288         if (is_host_alias(rbuf, ctl))
289         {
290             if (outlevel >= O_DEBUG)
291                 report(stdout, 
292                       _("line accepted, %s is an alias of the mailserver\n"), rbuf);
293         }
294         else
295         {
296             if (outlevel >= O_DEBUG)
297                 report(stdout, 
298                       _("line rejected, %s is not an alias of the mailserver\n"), 
299                       rbuf);
300             return(NULL);
301         }
302
303         /* search for whitepace-surrounded "for" followed by xxxx@yyyy */
304         for (base = ok + 4 + strlen(rbuf);  ; base = ok + 2)
305         {
306             if (!(ok = strstr(base, "for")))
307                 break;
308             else if (!isspace(ok[-1]) || !isspace(ok[3]))
309                 continue;
310             else
311             {
312                 char    *sp, *tp;
313
314                 /* extract space-delimited token after "for" */
315                 for (sp = ok + 3; isspace(*sp); sp++)
316                     continue;
317                 tp = rbuf;
318                 for (; !isspace(*sp); sp++)
319                     *tp++ = *sp;
320                 *tp = '\0';
321
322                 if (strchr(rbuf, '@'))
323                     break;
324                 else
325                     ok = sp - 1;        /* arrange to skip this token */
326             }
327         }
328         if (ok)
329         {
330             flag        want_gt = FALSE;
331             char        *sp, *tp;
332
333             /* char after "for" could be space or a continuation newline */
334             for (sp = ok + 4; isspace(*sp); sp++)
335                 continue;
336             tp = rbuf;
337             *tp++ = ':';        /* Here is the hack.  This is to be friends */
338             *tp++ = ' ';        /* with nxtaddr()... */
339             if (*sp == '<')
340             {
341                 want_gt = TRUE;
342                 sp++;
343             }
344             while (*sp == '@')          /* skip routes */
345                 while (*sp && *sp++ != ':')
346                     continue;
347             while (*sp
348                    && (want_gt ? (*sp != '>') : !isspace(*sp))
349                    && *sp != ';')
350                 if (!isspace(*sp))
351                     *tp++ = *sp++;
352                 else
353                 {
354                     /* uh oh -- whitespace here can't be right! */
355                     ok = (char *)NULL;
356                     break;
357                 }
358             *tp++ = '\n';
359             *tp = '\0';
360             if (strlen(rbuf) <= 3)      /* apparently nothing has been found */
361                 ok = NULL;
362         } else
363             ok = (char *)NULL;
364     }
365
366     if (!ok)
367     {
368         if (outlevel >= O_DEBUG)
369             report(stdout, _("no Received address found\n"));
370         return(NULL);
371     }
372     else
373     {
374         if (outlevel >= O_DEBUG) {
375             char *lf = rbuf + strlen(rbuf)-1;
376             *lf = '\0';
377             if (outlevel >= O_DEBUG)
378                 report(stdout, _("found Received address `%s'\n"), rbuf+2);
379             *lf = '\n';
380         }
381         return(rbuf);
382     }
383 }
384
385 /* shared by readheaders and readbody */
386 static int sizeticker;
387 static struct msgblk msgblk;
388
389 #define EMPTYLINE(s)    ((s)[0] == '\r' && (s)[1] == '\n' && (s)[2] == '\0')
390
391 static int readheaders(int sock,
392                        long fetchlen,
393                        long reallen,
394                        struct query *ctl,
395                        int num)
396 /* read message headers and ship to SMTP or MDA */
397 /*   sock:              to which the server is connected */
398 /*   fetchlen:          length of message according to fetch response */
399 /*   reallen:           length of message according to getsizes */
400 /*   ctl:               query control record */
401 /*   num:               index of message */
402 {
403     struct addrblk
404     {
405         int             offset;
406         struct addrblk  *next;
407     };
408     struct addrblk      *to_addrchain = NULL;
409     struct addrblk      **to_chainptr = &to_addrchain;
410     struct addrblk      *resent_to_addrchain = NULL;
411     struct addrblk      **resent_to_chainptr = &resent_to_addrchain;
412
413     char                buf[MSGBUFSIZE+1];
414     int                 from_offs, reply_to_offs, resent_from_offs;
415     int                 app_from_offs, sender_offs, resent_sender_offs;
416     int                 env_offs;
417     char                *received_for, *rcv, *cp, *delivered_to;
418     int                 n, linelen, oldlen, ch, remaining, skipcount;
419     struct idlist       *idp;
420     flag                no_local_matches = FALSE;
421     flag                headers_ok, has_nuls;
422     int                 olderrs, good_addresses, bad_addresses;
423
424     sizeticker = 0;
425     has_nuls = headers_ok = FALSE;
426     msgblk.return_path[0] = '\0';
427     olderrs = ctl->errcount;
428
429     /* read message headers */
430     msgblk.reallen = reallen;
431
432     /*
433      * We used to free the header block unconditionally at the end of 
434      * readheaders, but it turns out that if close_sink() hits an error
435      * condition the code for sending bouncemail will actually look
436      * at the freed storage and coredump...
437      */
438     if (msgblk.headers)
439        free(msgblk.headers);
440
441     msgblk.headers = received_for = delivered_to = NULL;
442     from_offs = reply_to_offs = resent_from_offs = app_from_offs = 
443         sender_offs = resent_sender_offs = env_offs = -1;
444     oldlen = 0;
445     msglen = 0;
446     skipcount = 0;
447     ctl->mimemsg = 0;
448
449     for (remaining = fetchlen; remaining > 0 || protocol->delimited; remaining -= linelen)
450     {
451         char *line;
452
453         line = xmalloc(sizeof(buf));
454         linelen = 0;
455         line[0] = '\0';
456         do {
457             set_timeout(mytimeout);
458             if ((n = SockRead(sock, buf, sizeof(buf)-1)) == -1) {
459                 set_timeout(0);
460                 free(line);
461                 free(msgblk.headers);
462                 msgblk.headers = NULL;
463                 return(PS_SOCKET);
464             }
465             set_timeout(0);
466             linelen += n;
467             msglen += n;
468
469             /* lines may not be properly CRLF terminated; fix this for qmail */
470             if (ctl->forcecr)
471             {
472                 cp = buf + strlen(buf) - 1;
473                 if (*cp == '\n' && (cp == buf || cp[-1] != '\r'))
474                 {
475                     *cp++ = '\r';
476                     *cp++ = '\n';
477                     *cp++ = '\0';
478                 }
479             }
480
481             /*
482              * Decode MIME encoded headers. We MUST do this before
483              * looking at the Content-Type / Content-Transfer-Encoding
484              * headers (RFC 2046).
485              */
486             if (ctl->mimedecode)
487                 UnMimeHeader(buf);
488
489             line = (char *) realloc(line, strlen(line) + strlen(buf) +1);
490
491             strcat(line, buf);
492
493             /* check for end of headers */
494             if (EMPTYLINE(line))
495             {
496                 headers_ok = TRUE;
497                 has_nuls = (linelen != strlen(line));
498                 free(line);
499                 goto process_headers;
500             }
501
502             /*
503              * Check for end of message immediately.  If one of your folders
504              * has been mangled, the delimiter may occur directly after the
505              * header.
506              */
507             if (protocol->delimited && line[0] == '.' && EMPTYLINE(line+1))
508             {
509                 free(line);
510                 has_nuls = (linelen != strlen(line));
511                 goto process_headers;
512             }
513
514             /*
515              * At least one brain-dead website (netmind.com) is known to
516              * send out robotmail that's missing the RFC822 delimiter blank
517              * line before the body! Without this check fetchmail segfaults.
518              * With it, we treat such messages as though they had the missing
519              * blank line.
520              */
521             if (!isspace(line[0]) && !strchr(line, ':'))
522             {
523                 headers_ok = TRUE;
524                 free(line);
525                 has_nuls = (linelen != strlen(line));
526                 goto process_headers;
527             }
528
529             /* check for RFC822 continuations */
530             set_timeout(mytimeout);
531             ch = SockPeek(sock);
532             set_timeout(0);
533         } while
534             (ch == ' ' || ch == '\t');  /* continuation to next line? */
535
536         /* write the message size dots */
537         if ((outlevel > O_SILENT && outlevel < O_VERBOSE) && linelen > 0)
538         {
539             sizeticker += linelen;
540             while (sizeticker >= SIZETICKER)
541             {
542                 if ((!run.use_syslog && !isafile(1)) || run.showdots)
543                 {
544                     fputc('.', stdout);
545                     fflush(stdout);
546                 }
547                 sizeticker -= SIZETICKER;
548             }
549         }
550
551         /* we see an ordinary (non-header, non-message-delimiter line */
552         has_nuls = (linelen != strlen(line));
553
554         /*
555          * When mail delivered to a multidrop mailbox on the server is
556          * addressed to multiple people on the client machine, there
557          * will be one copy left in the box for each recipient.  Thus,
558          * if the mail is addressed to N people, each recipient will
559          * get N copies.  This is bad when N > 1.
560          *
561          * Foil this by suppressing all but one copy of a message with
562          * a given Message-ID.  The accept_count test ensures that
563          * multiple pieces of email with the same Message-ID, each
564          * with a *single* addressee (the N == 1 case), won't be 
565          * suppressed.
566          *
567          * Note: This implementation only catches runs of successive
568          * messages with the same ID, but that should be good
569          * enough. A more general implementation would have to store
570          * ever-growing lists of seen message-IDs; in a long-running
571          * daemon this would turn into a memory leak even if the 
572          * implementation were perfect.
573          * 
574          * Don't mess with this code casually.  It would be way too easy
575          * to break it in a way that blackholed mail.  Better to pass
576          * the occasional duplicate than to do that...
577          */
578         if (MULTIDROP(ctl) && !strncasecmp(line, "Message-ID:", 11))
579         {
580             if (ctl->lastid && !strcasecmp(ctl->lastid, line))
581             {
582                 if (accept_count > 1)
583                     return(PS_REFUSED);
584             }
585             else
586             {
587                 if (ctl->lastid)
588                     free(ctl->lastid);
589                 ctl->lastid = strdup(line);
590             }
591         }
592
593         /*
594          * The University of Washington IMAP server (the reference
595          * implementation of IMAP4 written by Mark Crispin) relies
596          * on being able to keep base-UID information in a special
597          * message at the head of the mailbox.  This message should
598          * neither be deleted nor forwarded.
599          */
600 #ifdef POP2_ENABLE
601         /*
602          * We disable this check under POP2 because there's no way to
603          * prevent deletion of the message.  So at least we ought to 
604          * forward it to the user so he or she will have some clue
605          * that things have gone awry.
606          */
607 #if INET6_ENABLE
608         if (strncmp(protocol->service, "pop2", 4))
609 #else /* INET6_ENABLE */
610         if (protocol->port != 109)
611 #endif /* INET6_ENABLE */
612 #endif /* POP2_ENABLE */
613             if (num == 1 && !strncasecmp(line, "X-IMAP:", 7)) {
614                 free(line);
615                 free(msgblk.headers);
616                 msgblk.headers = NULL;
617                 return(PS_RETAINED);
618             }
619
620         /*
621          * This code prevents fetchmail from becoming an accessory after
622          * the fact to upstream sendmails with the `E' option on.  It also
623          * copes with certain brain-dead POP servers (like NT's) that pass
624          * through Unix from_ lines.
625          *
626          * Either of these bugs can result in a non-RFC822 line at the
627          * beginning of the headers.  If fetchmail just passes it
628          * through, the client listener may think the message has *no*
629          * headers (since the first) line it sees doesn't look
630          * RFC822-conformant) and fake up a set.
631          *
632          * What the user would see in this case is bogus (synthesized)
633          * headers, followed by a blank line, followed by the >From, 
634          * followed by the real headers, followed by a blank line,
635          * followed by text.
636          *
637          * We forestall this lossage by tossing anything that looks
638          * like an escaped or passed-through From_ line in headers.
639          * These aren't RFC822 so our conscience is clear...
640          */
641         if (!strncasecmp(line, ">From ", 6) || !strncasecmp(line, "From ", 5))
642         {
643             free(line);
644             continue;
645         }
646
647         /*
648          * We remove all Delivered-To: headers.
649          * 
650          * This is to avoid false mail loops messages when delivering
651          * local messages to and from a Postfix/qmail mailserver. 
652          */
653         if (ctl->dropdelivered && !strncasecmp(line, "Delivered-To:", 13)) 
654         {
655             if (delivered_to)
656                 free(line);
657             else 
658                 delivered_to = line;
659             continue;
660         }
661
662         /*
663          * If we see a Status line, it may have been inserted by an MUA
664          * on the mail host, or it may have been inserted by the server
665          * program after the headers in the transaction stream.  This
666          * can actually hose some new-mail notifiers such as xbuffy,
667          * which assumes any Status line came from a *local* MDA and
668          * therefore indicates that the message has been seen.
669          *
670          * Some buggy POP servers (including at least the 3.3(20)
671          * version of the one distributed with IMAP) insert empty
672          * Status lines in the transaction stream; we'll chuck those
673          * unconditionally.  Nonempty ones get chucked if the user
674          * turns on the dropstatus flag.
675          */
676         {
677             char        *cp;
678
679             if (!strncasecmp(line, "Status:", 7))
680                 cp = line + 7;
681             else if (!strncasecmp(line, "X-Mozilla-Status:", 17))
682                 cp = line + 17;
683             else
684                 cp = NULL;
685             if (cp) {
686                 while (*cp && isspace(*cp)) cp++;
687                 if (!*cp || ctl->dropstatus)
688                 {
689                     free(line);
690                     continue;
691                 }
692             }
693         }
694
695         if (ctl->rewrite)
696             line = reply_hack(line, ctl->server.truename);
697
698         /*
699          * OK, this is messy.  If we're forwarding by SMTP, it's the
700          * SMTP-receiver's job (according to RFC821, page 22, section
701          * 4.1.1) to generate a Return-Path line on final delivery.
702          * The trouble is, we've already got one because the
703          * mailserver's SMTP thought *it* was responsible for final
704          * delivery.
705          *
706          * Stash away the contents of Return-Path (as modified by reply_hack)
707          * for use in generating MAIL FROM later on, then prevent the header
708          * from being saved with the others.  In effect, we strip it off here.
709          *
710          * If the SMTP server conforms to the standards, and fetchmail gets the
711          * envelope sender from the Return-Path, the new Return-Path should be
712          * exactly the same as the original one.
713          *
714          * We do *not* want to ignore empty Return-Path headers.  These should
715          * be passed through as a way of indicating that a message should
716          * not trigger bounces if delivery fails.  What we *do* need to do is
717          * make sure we never try to rewrite such a blank Return-Path.  We
718          * handle this with a check for <> in the rewrite logic above.
719          */
720         if (!strncasecmp("Return-Path:", line, 12) && (cp = nxtaddr(line)))
721         {
722             strcpy(msgblk.return_path, cp);
723             if (!ctl->mda) {
724                 free(line);
725                 continue;
726             }
727         }
728
729         if (!msgblk.headers)
730         {
731             oldlen = strlen(line);
732             msgblk.headers = xmalloc(oldlen + 1);
733             (void) strcpy(msgblk.headers, line);
734             free(line);
735             line = msgblk.headers;
736         }
737         else
738         {
739             char *newhdrs;
740             int newlen;
741
742             newlen = oldlen + strlen(line);
743             newhdrs = (char *) realloc(msgblk.headers, newlen + 1);
744             if (newhdrs == NULL) {
745                 free(line);
746                 return(PS_IOERR);
747             }
748             msgblk.headers = newhdrs;
749             strcpy(msgblk.headers + oldlen, line);
750             free(line);
751             line = msgblk.headers + oldlen;
752             oldlen = newlen;
753         }
754
755         if (!strncasecmp("From:", line, 5))
756             from_offs = (line - msgblk.headers);
757         else if (!strncasecmp("Reply-To:", line, 9))
758             reply_to_offs = (line - msgblk.headers);
759         else if (!strncasecmp("Resent-From:", line, 12))
760             resent_from_offs = (line - msgblk.headers);
761         else if (!strncasecmp("Apparently-From:", line, 16))
762             app_from_offs = (line - msgblk.headers);
763         /*
764          * Netscape 4.7 puts "Sender: zap" in mail headers.  Perverse...
765          *
766          * But a literal reading of RFC822 sec. 4.4.2 supports the idea
767          * that Sender: *doesn't* have to be a working email address.
768          *
769          * The definition of the Sender header in RFC822 says, in
770          * part, "The Sender mailbox specification includes a word
771          * sequence which must correspond to a specific agent (i.e., a
772          * human user or a computer program) rather than a standard
773          * address."  That implies that the contents of the Sender
774          * field don't need to be a legal email address at all So
775          * ignore any Sender or Resent-Semnder lines unless they
776          * contain @.
777          *
778          * (RFC2822 says the condents of Sender must be a valid mailbox
779          * address, which is also what RFC822 4.4.4 implies.)
780          */
781         else if (!strncasecmp("Sender:", line, 7) && strchr(line, '@'))
782             sender_offs = (line - msgblk.headers);
783         else if (!strncasecmp("Resent-Sender:", line, 14) && strchr(line, '@'))
784             resent_sender_offs = (line - msgblk.headers);
785
786 #ifdef __UNUSED__
787         else if (!strncasecmp("Message-Id:", line, 11))
788         {
789             if (ctl->server.uidl)
790             {
791                 char id[IDLEN+1];
792
793                 line[IDLEN+12] = 0;             /* prevent stack overflow */
794                 sscanf(line+12, "%s", id);
795                 if (!str_find( &ctl->newsaved, num))
796                 {
797                     struct idlist *new = save_str(&ctl->newsaved,id,UID_SEEN);
798                     new->val.status.num = num;
799                 }
800             }
801         }
802 #endif /* __UNUSED__ */
803
804         else if (!MULTIDROP(ctl))
805             continue;
806
807         else if (!strncasecmp("To:", line, 3)
808                         || !strncasecmp("Cc:", line, 3)
809                         || !strncasecmp("Bcc:", line, 4)
810                         || !strncasecmp("Apparently-To:", line, 14))
811         {
812             *to_chainptr = xmalloc(sizeof(struct addrblk));
813             (*to_chainptr)->offset = (line - msgblk.headers);
814             to_chainptr = &(*to_chainptr)->next; 
815             *to_chainptr = NULL;
816         }
817
818         else if (!strncasecmp("Resent-To:", line, 10)
819                         || !strncasecmp("Resent-Cc:", line, 10)
820                         || !strncasecmp("Resent-Bcc:", line, 11))
821         {
822             *resent_to_chainptr = xmalloc(sizeof(struct addrblk));
823             (*resent_to_chainptr)->offset = (line - msgblk.headers);
824             resent_to_chainptr = &(*resent_to_chainptr)->next; 
825             *resent_to_chainptr = NULL;
826         }
827
828         else if (ctl->server.envelope != STRING_DISABLED)
829         {
830             if (ctl->server.envelope 
831                         && strcasecmp(ctl->server.envelope, "Received"))
832             {
833                 if (env_offs == -1 && !strncasecmp(ctl->server.envelope,
834                                                 line,
835                                                 strlen(ctl->server.envelope)))
836                 {                               
837                     if (skipcount++ != ctl->server.envskip)
838                         continue;
839                     env_offs = (line - msgblk.headers);
840                 }    
841             }
842             else if (!received_for && !strncasecmp("Received:", line, 9))
843             {
844                 if (skipcount++ != ctl->server.envskip)
845                     continue;
846                 received_for = parse_received(ctl, line);
847             }
848         }
849     }
850
851  process_headers:
852     /*
853      * We want to detect this early in case there are so few headers that the
854      * dispatch logic barfs.
855      */
856     if (!headers_ok)
857     {
858         if (outlevel > O_SILENT)
859             report(stdout,
860                    _("message delimiter found while scanning headers\n"));
861     }
862
863     /*
864      * Hack time.  If the first line of the message was blank, with no headers
865      * (this happens occasionally due to bad gatewaying software) cons up
866      * a set of fake headers.  
867      *
868      * If you modify the fake header template below, be sure you don't
869      * make either From or To address @-less, otherwise the reply_hack
870      * logic will do bad things.
871      */
872     if (msgblk.headers == (char *)NULL)
873     {
874 #ifdef HAVE_SNPRINTF
875         snprintf(buf, sizeof(buf),
876 #else
877         sprintf(buf, 
878 #endif /* HAVE_SNPRINTF */
879         "From: FETCHMAIL-DAEMON\r\nTo: %s@%s\r\nSubject: Headerless mail from %s's mailbox on %s\r\n",
880                 user, fetchmailhost, ctl->remotename, ctl->server.truename);
881         msgblk.headers = xstrdup(buf);
882     }
883
884     /*
885      * We can now process message headers before reading the text.
886      * In fact we have to, as this will tell us where to forward to.
887      */
888
889     /* Check for MIME headers indicating possible 8-bit data */
890     ctl->mimemsg = MimeBodyType(msgblk.headers, ctl->mimedecode);
891
892 #ifdef SDPS_ENABLE
893     if (ctl->server.sdps && sdps_envfrom)
894     {
895         /* We have the real envelope return-path, stored out of band by
896          * SDPS - that's more accurate than any header is going to be.
897          */
898         strcpy(msgblk.return_path, sdps_envfrom);
899         free(sdps_envfrom);
900     } else
901 #endif /* SDPS_ENABLE */
902     /*
903      * If there is a Return-Path address on the message, this was
904      * almost certainly the MAIL FROM address given the originating
905      * sendmail.  This is the best thing to use for logging the
906      * message origin (it sets up the right behavior for bounces and
907      * mailing lists).  Otherwise, fall down to the next available 
908      * envelope address (which is the most probable real sender).
909      * *** The order is important! ***
910      * This is especially useful when receiving mailing list
911      * messages in multidrop mode.  if a local address doesn't
912      * exist, the bounce message won't be returned blindly to the 
913      * author or to the list itself but rather to the list manager
914      * (ex: specified by "Sender:") which is much less annoying.  This 
915      * is true for most mailing list packages.
916      */
917     if( !msgblk.return_path[0] ){
918         char *ap = NULL;
919         if (resent_sender_offs >= 0 && (ap = nxtaddr(msgblk.headers + resent_sender_offs)));
920         else if (sender_offs >= 0 && (ap = nxtaddr(msgblk.headers + sender_offs)));
921         else if (resent_from_offs >= 0 && (ap = nxtaddr(msgblk.headers + resent_from_offs)));
922         else if (from_offs >= 0 && (ap = nxtaddr(msgblk.headers + from_offs)));
923         else if (reply_to_offs >= 0 && (ap = nxtaddr(msgblk.headers + reply_to_offs)));
924         else if (app_from_offs >= 0 && (ap = nxtaddr(msgblk.headers + app_from_offs)));
925         /* multi-line MAIL FROM addresses confuse SMTP terribly */
926         if (ap && !strchr(ap, '\n')) 
927             strcpy(msgblk.return_path, ap);
928     }
929
930     /* cons up a list of local recipients */
931     msgblk.recipients = (struct idlist *)NULL;
932     accept_count = reject_count = 0;
933     /* is this a multidrop box? */
934     if (MULTIDROP(ctl))
935     {
936 #ifdef SDPS_ENABLE
937         if (ctl->server.sdps && sdps_envto)
938         {
939             /* We have the real envelope recipient, stored out of band by
940              * SDPS - that's more accurate than any header is going to be.
941              */
942             find_server_names(sdps_envto, ctl, &msgblk.recipients);
943             free(sdps_envto);
944         } else
945 #endif /* SDPS_ENABLE */ 
946         if (env_offs > -1)          /* We have the actual envelope addressee */
947             find_server_names(msgblk.headers + env_offs, ctl, &msgblk.recipients);
948         else if (delivered_to && ctl->server.envelope != STRING_DISABLED &&
949       ctl->server.envelope && !strcasecmp(ctl->server.envelope, "Delivered-To"))
950    {
951             find_server_names(delivered_to, ctl, &msgblk.recipients);
952        free(delivered_to);
953    }
954         else if (received_for)
955             /*
956              * We have the Received for addressee.  
957              * It has to be a mailserver address, or we
958              * wouldn't have got here.
959              * We use find_server_names() to let local 
960              * hostnames go through.
961              */
962             find_server_names(received_for, ctl, &msgblk.recipients);
963         else
964         {
965             /*
966              * We haven't extracted the envelope address.
967              * So check all the "Resent-To" header addresses if 
968              * they exist.  If and only if they don't, consider
969              * the "To" addresses.
970              */
971             register struct addrblk *nextptr;
972             if (resent_to_addrchain) {
973                 /* delete the "To" chain and substitute it 
974                  * with the "Resent-To" list 
975                  */
976                 while (to_addrchain) {
977                     nextptr = to_addrchain->next;
978                     free(to_addrchain);
979                     to_addrchain = nextptr;
980                 }
981                 to_addrchain = resent_to_addrchain;
982                 resent_to_addrchain = NULL;
983             }
984             /* now look for remaining adresses */
985             while (to_addrchain) {
986                 find_server_names(msgblk.headers+to_addrchain->offset, ctl, &msgblk.recipients);
987                 nextptr = to_addrchain->next;
988                 free(to_addrchain);
989                 to_addrchain = nextptr;
990             }
991         }
992         if (!accept_count)
993         {
994             no_local_matches = TRUE;
995             save_str(&msgblk.recipients, run.postmaster, XMIT_ACCEPT);
996             if (outlevel >= O_DEBUG)
997                 report(stdout,
998                       _("no local matches, forwarding to %s\n"),
999                       run.postmaster);
1000         }
1001     }
1002     else        /* it's a single-drop box, use first localname */
1003         save_str(&msgblk.recipients, ctl->localnames->id, XMIT_ACCEPT);
1004
1005
1006     /*
1007      * Time to either address the message or decide we can't deliver it yet.
1008      */
1009     if (ctl->errcount > olderrs)        /* there were DNS errors above */
1010     {
1011         if (outlevel >= O_DEBUG)
1012             report(stdout,
1013                    _("forwarding and deletion suppressed due to DNS errors\n"));
1014         free(msgblk.headers);
1015         msgblk.headers = NULL;
1016         free_str_list(&msgblk.recipients);
1017         return(PS_TRANSIENT);
1018     }
1019     else
1020     {
1021         /* set up stuffline() so we can deliver the message body through it */ 
1022         if ((n = open_sink(ctl, &msgblk,
1023                            &good_addresses, &bad_addresses)) != PS_SUCCESS)
1024         {
1025             free(msgblk.headers);
1026             msgblk.headers = NULL;
1027             free_str_list(&msgblk.recipients);
1028             return(n);
1029         }
1030     }
1031
1032     n = 0;
1033     /*
1034      * Some server/sendmail combinations cause problems when our
1035      * synthetic Received line is before the From header.  Cope
1036      * with this...
1037      */
1038     if ((rcv = strstr(msgblk.headers, "Received:")) == (char *)NULL)
1039         rcv = msgblk.headers;
1040     /* handle ">Received:" lines too */
1041     while (rcv > msgblk.headers && rcv[-1] != '\n')
1042         rcv--;
1043     if (rcv > msgblk.headers)
1044     {
1045         char    c = *rcv;
1046
1047         *rcv = '\0';
1048         n = stuffline(ctl, msgblk.headers);
1049         *rcv = c;
1050     }
1051     if (!run.invisible && n != -1)
1052     {
1053         /* utter any per-message Received information we need here */
1054         if (ctl->server.trueaddr) {
1055             sprintf(buf, "Received: from %s [%u.%u.%u.%u]\r\n", 
1056                     ctl->server.truename,
1057                     (unsigned char)ctl->server.trueaddr[0],
1058                     (unsigned char)ctl->server.trueaddr[1],
1059                     (unsigned char)ctl->server.trueaddr[2],
1060                     (unsigned char)ctl->server.trueaddr[3]);
1061         } else {
1062           sprintf(buf, "Received: from %s\r\n", ctl->server.truename);
1063         }
1064         n = stuffline(ctl, buf);
1065         if (n != -1)
1066         {
1067             /*
1068              * This header is technically invalid under RFC822.
1069              * POP3, IMAP, etc. are not legal mail-parameter values.
1070              */
1071             sprintf(buf, "\tby %s with %s (fetchmail-%s)",
1072                     fetchmailhost,
1073                     protocol->name,
1074                     VERSION);
1075             if (ctl->tracepolls)
1076             {
1077                 sprintf(buf + strlen(buf), " polling %s account %s",
1078                         ctl->server.pollname, 
1079                         ctl->remotename);
1080             }
1081             strcat(buf, "\r\n");
1082             n = stuffline(ctl, buf);
1083             if (n != -1)
1084             {
1085                 buf[0] = '\t';
1086                 if (good_addresses == 0)
1087                 {
1088                     sprintf(buf+1, 
1089                             "for %s@%s (by default); ",
1090                             user, ctl->destaddr);
1091                 }
1092                 else if (good_addresses == 1)
1093                 {
1094                     for (idp = msgblk.recipients; idp; idp = idp->next)
1095                         if (idp->val.status.mark == XMIT_ACCEPT)
1096                             break;      /* only report first address */
1097                     if (strchr(idp->id, '@'))
1098                         sprintf(buf+1, "for %s", idp->id);
1099                     else
1100                         /*
1101                          * This could be a bit misleading, as destaddr is
1102                          * the forwarding host rather than the actual 
1103                          * destination.  Most of the time they coincide.
1104                          */
1105                         sprintf(buf+1, "for %s@%s", idp->id, ctl->destaddr);
1106                     sprintf(buf+strlen(buf), " (%s); ",
1107                             MULTIDROP(ctl) ? "multi-drop" : "single-drop");
1108                 }
1109                 else
1110                     buf[1] = '\0';
1111
1112                 strcat(buf, rfc822timestamp());
1113                 strcat(buf, "\r\n");
1114                 n = stuffline(ctl, buf);
1115             }
1116         }
1117     }
1118
1119     if (n != -1)
1120         n = stuffline(ctl, rcv);        /* ship out rest of msgblk.headers */
1121
1122     if (n == -1)
1123     {
1124         report(stdout, _("writing RFC822 msgblk.headers\n"));
1125         release_sink(ctl);
1126         free(msgblk.headers);
1127         msgblk.headers = NULL;
1128         free_str_list(&msgblk.recipients);
1129         return(PS_IOERR);
1130     }
1131     else if ((run.poll_interval == 0 || nodetach) && outlevel >= O_VERBOSE && !isafile(2))
1132         fputs("#", stderr);
1133
1134     /* write error notifications */
1135     if (no_local_matches || has_nuls || bad_addresses)
1136     {
1137         int     errlen = 0;
1138         char    errhd[USERNAMELEN + POPBUFSIZE], *errmsg;
1139
1140         errmsg = errhd;
1141         (void) strcpy(errhd, "X-Fetchmail-Warning: ");
1142         if (no_local_matches)
1143         {
1144             if (reject_count != 1)
1145                 strcat(errhd, _("no recipient addresses matched declared local names"));
1146             else
1147             {
1148                 for (idp = msgblk.recipients; idp; idp = idp->next)
1149                     if (idp->val.status.mark == XMIT_REJECT)
1150                         break;
1151                 sprintf(errhd+strlen(errhd), _("recipient address %s didn't match any local name"), idp->id);
1152             }
1153         }
1154
1155         if (has_nuls)
1156         {
1157             if (errhd[sizeof("X-Fetchmail-Warning: ")])
1158                 strcat(errhd, "; ");
1159             strcat(errhd, _("message has embedded NULs"));
1160         }
1161
1162         if (bad_addresses)
1163         {
1164             if (errhd[sizeof("X-Fetchmail-Warning: ")])
1165                 strcat(errhd, "; ");
1166             strcat(errhd, _("SMTP listener rejected local recipient addresses: "));
1167             errlen = strlen(errhd);
1168             for (idp = msgblk.recipients; idp; idp = idp->next)
1169                 if (idp->val.status.mark == XMIT_RCPTBAD)
1170                     errlen += strlen(idp->id) + 2;
1171
1172             xalloca(errmsg, char *, errlen+3);
1173             (void) strcpy(errmsg, errhd);
1174             for (idp = msgblk.recipients; idp; idp = idp->next)
1175                 if (idp->val.status.mark == XMIT_RCPTBAD)
1176                 {
1177                     strcat(errmsg, idp->id);
1178                     if (idp->next)
1179                         strcat(errmsg, ", ");
1180                 }
1181
1182         }
1183
1184         strcat(errmsg, "\r\n");
1185
1186         /* ship out the error line */
1187         stuffline(ctl, errmsg);
1188     }
1189
1190     /* issue the delimiter line */
1191     cp = buf;
1192     *cp++ = '\r';
1193     *cp++ = '\n';
1194     *cp++ = '\0';
1195     stuffline(ctl, buf);
1196
1197 /*    free(msgblk.headers); */
1198     free_str_list(&msgblk.recipients);
1199     return(headers_ok ? PS_SUCCESS : PS_TRUNCATED);
1200 }
1201
1202 static int readbody(int sock, struct query *ctl, flag forward, int len)
1203 /* read and dispose of a message body presented on sock */
1204 /*   ctl:               query control record */
1205 /*   sock:              to which the server is connected */
1206 /*   len:               length of message */
1207 /*   forward:           TRUE to forward */
1208 {
1209     int linelen;
1210     unsigned char buf[MSGBUFSIZE+4];
1211     unsigned char *inbufp = buf;
1212     flag issoftline = FALSE;
1213
1214     /*
1215      * Pass through the text lines in the body.
1216      *
1217      * Yes, this wants to be ||, not &&.  The problem is that in the most
1218      * important delimited protocol, POP3, the length is not reliable.
1219      * As usual, the problem is Microsoft brain damage; see FAQ item S2.
1220      * So, for delimited protocols we need to ignore the length here and
1221      * instead drop out of the loop with a break statement when we see
1222      * the message delimiter.
1223      */
1224     while (protocol->delimited || len > 0)
1225     {
1226         set_timeout(mytimeout);
1227         if ((linelen = SockRead(sock, inbufp, sizeof(buf)-4-(inbufp-buf)))==-1)
1228         {
1229             set_timeout(0);
1230             release_sink(ctl);
1231             return(PS_SOCKET);
1232         }
1233         set_timeout(0);
1234
1235         /* write the message size dots */
1236         if (linelen > 0)
1237         {
1238             sizeticker += linelen;
1239             while (sizeticker >= SIZETICKER)
1240             {
1241                 if (outlevel > O_SILENT && (((run.poll_interval == 0 || nodetach) && !isafile(1)) || run.showdots))
1242                 {
1243                     fputc('.', stdout);
1244                     fflush(stdout);
1245                 }
1246                 sizeticker -= SIZETICKER;
1247             }
1248         }
1249         len -= linelen;
1250
1251         /* check for end of message */
1252         if (protocol->delimited && *inbufp == '.')
1253         {
1254             if (inbufp[1] == '\r' && inbufp[2] == '\n' && inbufp[3] == '\0')
1255                 break;
1256             else if (inbufp[1] == '\n' && inbufp[2] == '\0')
1257                 break;
1258             else
1259                 msglen--;       /* subtract the size of the dot escape */
1260         }
1261
1262         msglen += linelen;
1263
1264         if (ctl->mimedecode && (ctl->mimemsg & MSG_NEEDS_DECODE)) {
1265             issoftline = UnMimeBodyline(&inbufp, protocol->delimited, issoftline);
1266             if (issoftline && (sizeof(buf)-1-(inbufp-buf) < 200))
1267             {
1268                 /*
1269                  * Soft linebreak, but less than 200 bytes left in
1270                  * input buffer. Rather than doing a buffer overrun,
1271                  * ignore the soft linebreak, NL-terminate data and
1272                  * deliver what we have now.
1273                  * (Who writes lines longer than 2K anyway?)
1274                  */
1275                 *inbufp = '\n'; *(inbufp+1) = '\0';
1276                 issoftline = 0;
1277             }
1278         }
1279
1280         /* ship out the text line */
1281         if (forward && (!issoftline))
1282         {
1283             int n;
1284             inbufp = buf;
1285
1286             /* guard against very long lines */
1287             buf[MSGBUFSIZE+1] = '\r';
1288             buf[MSGBUFSIZE+2] = '\n';
1289             buf[MSGBUFSIZE+3] = '\0';
1290
1291             n = stuffline(ctl, buf);
1292
1293             if (n < 0)
1294             {
1295                 report(stdout, _("writing message text\n"));
1296                 release_sink(ctl);
1297                 return(PS_IOERR);
1298             }
1299             else if (outlevel >= O_VERBOSE && !isafile(1))
1300             {
1301                 fputc('*', stdout);
1302                 fflush(stdout);
1303             }
1304         }
1305     }
1306
1307     return(PS_SUCCESS);
1308 }
1309
1310 #ifdef KERBEROS_V4
1311 int
1312 kerberos_auth (socket, canonical, principal) 
1313 /* authenticate to the server host using Kerberos V4 */
1314 int socket;             /* socket to server host */
1315 char *canonical;        /* server name */
1316 char *principal;
1317 {
1318     char * host_primary;
1319     KTEXT ticket;
1320     MSG_DAT msg_data;
1321     CREDENTIALS cred;
1322     Key_schedule schedule;
1323     int rem;
1324     char * prin_copy = (char *) NULL;
1325     char * prin = (char *) NULL;
1326     char * inst = (char *) NULL;
1327     char * realm = (char *) NULL;
1328
1329     if (principal != (char *)NULL && *principal)
1330     {
1331         char *cp;
1332         prin = prin_copy = xstrdup(principal);
1333         for (cp = prin_copy; *cp && *cp != '.'; ++cp)
1334             ;
1335         if (*cp)
1336         {
1337             *cp++ = '\0';
1338             inst = cp;
1339             while (*cp && *cp != '@')
1340                 ++cp;
1341             if (*cp)
1342             {
1343                 *cp++ = '\0';
1344                 realm = cp;
1345             }
1346         }
1347     }
1348   
1349     xalloca(ticket, KTEXT, sizeof (KTEXT_ST));
1350     rem = (krb_sendauth (0L, socket, ticket,
1351                          prin ? prin : "pop",
1352                          inst ? inst : canonical,
1353                          realm ? realm : ((char *) (krb_realmofhost (canonical))),
1354                          ((unsigned long) 0),
1355                          (&msg_data),
1356                          (&cred),
1357                          (schedule),
1358                          ((struct sockaddr_in *) 0),
1359                          ((struct sockaddr_in *) 0),
1360                          "KPOPV0.1"));
1361     if (prin_copy)
1362     {
1363         free(prin_copy);
1364     }
1365     if (rem != KSUCCESS)
1366     {
1367         report(stderr, _("kerberos error %s\n"), (krb_get_err_text (rem)));
1368         return (PS_AUTHFAIL);
1369     }
1370     return (0);
1371 }
1372 #endif /* KERBEROS_V4 */
1373
1374 #ifdef KERBEROS_V5
1375 static int kerberos5_auth(socket, canonical)
1376 /* authenticate to the server host using Kerberos V5 */
1377 int socket;             /* socket to server host */
1378 const char *canonical;  /* server name */
1379 {
1380     krb5_error_code retval;
1381     krb5_context context;
1382     krb5_ccache ccdef;
1383     krb5_principal client = NULL, server = NULL;
1384     krb5_error *err_ret = NULL;
1385
1386     krb5_auth_context auth_context = NULL;
1387
1388     krb5_init_context(&context);
1389     krb5_init_ets(context);
1390     krb5_auth_con_init(context, &auth_context);
1391
1392     if (retval = krb5_cc_default(context, &ccdef)) {
1393         report(stderr, "krb5_cc_default: %s\n", error_message(retval));
1394         return(PS_ERROR);
1395     }
1396
1397     if (retval = krb5_cc_get_principal(context, ccdef, &client)) {
1398         report(stderr, "krb5_cc_get_principal: %s\n", error_message(retval));
1399         return(PS_ERROR);
1400     }
1401
1402     if (retval = krb5_sname_to_principal(context, canonical, "pop",
1403            KRB5_NT_UNKNOWN,
1404            &server)) {
1405         report(stderr, "krb5_sname_to_principal: %s\n", error_message(retval));
1406         return(PS_ERROR);
1407     }
1408
1409     retval = krb5_sendauth(context, &auth_context, (krb5_pointer) &socket,
1410          "KPOPV1.0", client, server,
1411          AP_OPTS_MUTUAL_REQUIRED,
1412          NULL,  /* no data to checksum */
1413          0,   /* no creds, use ccache instead */
1414          ccdef,
1415          &err_ret, 0,
1416
1417          NULL); /* don't need reply */
1418
1419     krb5_free_principal(context, server);
1420     krb5_free_principal(context, client);
1421     krb5_auth_con_free(context, auth_context);
1422
1423     if (retval) {
1424 #ifdef HEIMDAL
1425       if (err_ret && err_ret->e_text) {
1426           report(stderr, _("krb5_sendauth: %s [server says '%*s'] \n"),
1427                  error_message(retval),
1428                  err_ret->e_text);
1429 #else
1430       if (err_ret && err_ret->text.length) {
1431           report(stderr, _("krb5_sendauth: %s [server says '%*s'] \n"),
1432                  error_message(retval),
1433                  err_ret->text.length,
1434                  err_ret->text.data);
1435 #endif
1436           krb5_free_error(context, err_ret);
1437       } else
1438           report(stderr, "krb5_sendauth: %s\n", error_message(retval));
1439       return(PS_ERROR);
1440     }
1441
1442     return 0;
1443 }
1444 #endif /* KERBEROS_V5 */
1445
1446 static void clean_skipped_list(struct idlist **skipped_list)
1447 /* struct "idlist" contains no "prev" ptr; we must remove unused items first */
1448 {
1449     struct idlist *current=NULL, *prev=NULL, *tmp=NULL, *head=NULL;
1450     prev = current = head = *skipped_list;
1451
1452     if (!head)
1453         return;
1454     do
1455     {
1456         /* if item has no reference, remove it */
1457         if (current && current->val.status.mark == 0)
1458         {
1459             if (current == head) /* remove first item (head) */
1460             {
1461                 head = current->next;
1462                 if (current->id) free(current->id);
1463                 free(current);
1464                 prev = current = head;
1465             }
1466             else /* remove middle/last item */
1467             {
1468                 tmp = current->next;
1469                 prev->next = tmp;
1470                 if (current->id) free(current->id);
1471                 free(current);
1472                 current = tmp;
1473             }
1474         }
1475         else /* skip this item */
1476         {
1477             prev = current;
1478             current = current->next;
1479         }
1480     } while(current);
1481
1482     *skipped_list = head;
1483 }
1484
1485 static void send_size_warnings(struct query *ctl)
1486 /* send warning mail with skipped msg; reset msg count when user notified */
1487 {
1488     int size, nbr;
1489     int msg_to_send = FALSE;
1490     struct idlist *head=NULL, *current=NULL;
1491     int max_warning_poll_count;
1492
1493     head = ctl->skipped;
1494     if (!head)
1495         return;
1496
1497     /* don't start a notification message unless we need to */
1498     for (current = head; current; current = current->next)
1499         if (current->val.status.num == 0 && current->val.status.mark)
1500             msg_to_send = TRUE;
1501     if (!msg_to_send)
1502         return;
1503
1504     /*
1505      * There's no good way to recover if we can't send notification mail, 
1506      * but it's not a disaster, either, since the skipped mail will not
1507      * be deleted.
1508      */
1509     if (open_warning_by_mail(ctl, (struct msgblk *)NULL))
1510         return;
1511     stuff_warning(ctl,
1512            _("Subject: Fetchmail oversized-messages warning.\r\n"
1513              "\r\n"
1514              "The following oversized messages remain on the mail server %s:"),
1515                   ctl->server.pollname);
1516  
1517     if (run.poll_interval == 0)
1518         max_warning_poll_count = 0;
1519     else
1520         max_warning_poll_count = ctl->warnings/run.poll_interval;
1521
1522     /* parse list of skipped msg, adding items to the mail */
1523     for (current = head; current; current = current->next)
1524     {
1525         if (current->val.status.num == 0 && current->val.status.mark)
1526         {
1527             nbr = current->val.status.mark;
1528             size = atoi(current->id);
1529             stuff_warning(ctl, 
1530                     _("\t%d msg %d octets long skipped by fetchmail.\r\n"),
1531                     nbr, size);
1532         }
1533         current->val.status.num++;
1534         current->val.status.mark = 0;
1535
1536         if (current->val.status.num >= max_warning_poll_count)
1537             current->val.status.num = 0;
1538     }
1539
1540     close_warning_by_mail(ctl, (struct msgblk *)NULL);
1541 }
1542
1543 static int do_session(ctl, proto, maxfetch)
1544 /* retrieve messages from server using given protocol method table */
1545 struct query *ctl;              /* parsed options with merged-in defaults */
1546 const struct method *proto;     /* protocol method table */
1547 const int maxfetch;             /* maximum number of messages to fetch */
1548 {
1549     int js;
1550 #ifdef HAVE_VOLATILE
1551     volatile int ok, mailserver_socket = -1;    /* pacifies -Wall */
1552 #else
1553     int ok, mailserver_socket = -1;
1554 #endif /* HAVE_VOLATILE */
1555     const char *msg;
1556     void (*pipesave)(int);
1557     void (*alrmsave)(int);
1558     struct idlist *current=NULL, *tmp=NULL;
1559
1560     protocol = proto;
1561     ctl->server.base_protocol = protocol;
1562
1563     pass = 0;
1564     tagnum = 0;
1565     tag[0] = '\0';      /* nuke any tag hanging out from previous query */
1566     ok = 0;
1567
1568     /* set up the server-nonresponse timeout */
1569     alrmsave = signal(SIGALRM, timeout_handler);
1570     mytimeout = ctl->server.timeout;
1571
1572     /* set up the broken-pipe timeout */
1573     pipesave = signal(SIGPIPE, sigpipe_handler);
1574
1575     if ((js = setjmp(restart)))
1576     {
1577 #ifdef HAVE_SIGPROCMASK
1578         /*
1579          * Don't rely on setjmp() to restore the blocked-signal mask.
1580          * It does this under BSD but is required not to under POSIX.
1581          *
1582          * If your Unix doesn't have sigprocmask, better hope it has
1583          * BSD-like behavior.  Otherwise you may see fetchmail get
1584          * permanently wedged after a second timeout on a bad read,
1585          * because alarm signals were blocked after the first.
1586          */
1587         sigset_t        allsigs;
1588
1589         sigfillset(&allsigs);
1590         sigprocmask(SIG_UNBLOCK, &allsigs, NULL);
1591 #endif /* HAVE_SIGPROCMASK */
1592
1593         if (js == THROW_SIGPIPE)
1594         {
1595             signal(SIGPIPE, SIG_IGN);
1596             report(stdout,
1597                    _("SIGPIPE thrown from an MDA or a stream socket error\n"));
1598             ok = PS_SOCKET;
1599             goto cleanUp;
1600         }
1601         else if (js == THROW_TIMEOUT)
1602         {
1603             if (phase == OPEN_WAIT)
1604                 report(stdout,
1605                        _("timeout after %d seconds waiting to connect to server %s.\n"),
1606                        ctl->server.timeout, ctl->server.pollname);
1607             else if (phase == SERVER_WAIT)
1608                 report(stdout,
1609                        _("timeout after %d seconds waiting for server %s.\n"),
1610                        ctl->server.timeout, ctl->server.pollname);
1611             else if (phase == FORWARDING_WAIT)
1612                 report(stdout,
1613                        _("timeout after %d seconds waiting for %s.\n"),
1614                        ctl->server.timeout,
1615                        ctl->mda ? "MDA" : "SMTP");
1616             else if (phase == LISTENER_WAIT)
1617                 report(stdout,
1618                        _("timeout after %d seconds waiting for listener to respond.\n"), ctl->server.timeout);
1619             else
1620                 report(stdout, 
1621                        _("timeout after %d seconds.\n"), ctl->server.timeout);
1622
1623             /*
1624              * If we've exceeded our threshold for consecutive timeouts, 
1625              * try to notify the user, then mark the connection wedged.
1626              * Don't do this if the connection can idle, though; idle
1627              * timeouts just mean the frequency of mail is low.
1628              */
1629             if (timeoutcount > MAX_TIMEOUTS 
1630                 && !open_warning_by_mail(ctl, (struct msgblk *)NULL))
1631             {
1632                 stuff_warning(ctl,
1633                               _("Subject: fetchmail sees repeated timeouts\r\n"));
1634                 stuff_warning(ctl,
1635                               _("Fetchmail saw more than %d timeouts while attempting to get mail from %s@%s.\r\n"), 
1636                               MAX_TIMEOUTS,
1637                               ctl->remotename,
1638                               ctl->server.truename);
1639                 stuff_warning(ctl, 
1640     _("This could mean that your mailserver is stuck, or that your SMTP\r\n" \
1641     "server is wedged, or that your mailbox file on the server has been\r\n" \
1642     "corrupted by a server error.  You can run `fetchmail -v -v' to\r\n" \
1643     "diagnose the problem.\r\n\r\n" \
1644     "Fetchmail won't poll this mailbox again until you restart it.\r\n"));
1645                 close_warning_by_mail(ctl, (struct msgblk *)NULL);
1646                 ctl->wedged = TRUE;
1647             }
1648
1649             ok = PS_ERROR;
1650         }
1651
1652         /* try to clean up all streams */
1653         release_sink(ctl);
1654         if (ctl->smtp_socket != -1)
1655             SockClose(ctl->smtp_socket);
1656         if (mailserver_socket != -1)
1657             SockClose(mailserver_socket);
1658     }
1659     else
1660     {
1661         char buf[MSGBUFSIZE+1], *realhost;
1662         int len, num, count, new, bytes, deletions = 0, *msgsizes = NULL;
1663 #if INET6_ENABLE
1664         int fetches, dispatches, oldphase;
1665 #else /* INET6_ENABLE */
1666         int port, fetches, dispatches, oldphase;
1667 #endif /* INET6_ENABLE */
1668         struct idlist *idp;
1669
1670         /* execute pre-initialization command, if any */
1671         if (ctl->preconnect && (ok = system(ctl->preconnect)))
1672         {
1673             report(stderr, 
1674                    _("pre-connection command failed with status %d\n"), ok);
1675             ok = PS_SYNTAX;
1676             goto closeUp;
1677         }
1678
1679         /* open a socket to the mail server */
1680         oldphase = phase;
1681         phase = OPEN_WAIT;
1682         set_timeout(mytimeout);
1683 #if !INET6_ENABLE
1684 #ifdef SSL_ENABLE
1685         port = ctl->server.port ? ctl->server.port : ( ctl->use_ssl ? protocol->sslport : protocol->port );
1686 #else
1687         port = ctl->server.port ? ctl->server.port : protocol->port;
1688 #endif
1689 #endif /* !INET6_ENABLE */
1690         realhost = ctl->server.via ? ctl->server.via : ctl->server.pollname;
1691
1692         /* allow time for the port to be set up if we have a plugin */
1693         if (ctl->server.plugin)
1694             (void)sleep(1);
1695 #if INET6_ENABLE
1696         if ((mailserver_socket = SockOpen(realhost, 
1697                              ctl->server.service ? ctl->server.service : ( ctl->use_ssl ? protocol->sslservice : protocol->service ),
1698                              ctl->server.netsec, ctl->server.plugin)) == -1)
1699 #else /* INET6_ENABLE */
1700         if ((mailserver_socket = SockOpen(realhost, port, NULL, ctl->server.plugin)) == -1)
1701 #endif /* INET6_ENABLE */
1702         {
1703             char        errbuf[BUFSIZ];
1704 #if !INET6_ENABLE
1705             int err_no = errno;
1706 #ifdef HAVE_RES_SEARCH
1707             if (err_no != 0 && h_errno != 0)
1708                 report(stderr, _("internal inconsistency\n"));
1709 #endif
1710             /*
1711              * Avoid generating a bogus error every poll cycle when we're
1712              * in daemon mode but the connection to the outside world
1713              * is down.
1714              */
1715             if (!((err_no == EHOSTUNREACH || err_no == ENETUNREACH) 
1716                   && run.poll_interval))
1717             {
1718                 report_build(stderr, _("%s connection to %s failed"), 
1719                              protocol->name, ctl->server.pollname);
1720 #ifdef HAVE_RES_SEARCH
1721                 if (h_errno != 0)
1722                 {
1723                     if (h_errno == HOST_NOT_FOUND)
1724                         strcpy(errbuf, _("host is unknown."));
1725 #ifndef __BEOS__
1726                     else if (h_errno == NO_ADDRESS)
1727                         strcpy(errbuf, _("name is valid but has no IP address."));
1728 #endif
1729                     else if (h_errno == NO_RECOVERY)
1730                         strcpy(errbuf, _("unrecoverable name server error."));
1731                     else if (h_errno == TRY_AGAIN)
1732                         strcpy(errbuf, _("temporary name server error."));
1733                     else
1734                         sprintf(errbuf, _("unknown DNS error %d."), h_errno);
1735                 }
1736                 else
1737 #endif /* HAVE_RES_SEARCH */
1738                     strcpy(errbuf, strerror(err_no));
1739                 report_complete(stderr, ": %s\n", errbuf);
1740
1741 #ifdef __UNUSED
1742                 /* 
1743                  * Don't use this.  It was an attempt to address Debian bug
1744                  * #47143 (Notify user by mail when pop server nonexistent).
1745                  * Trouble is, that doesn't work; you trip over the case 
1746                  * where your SLIP or PPP link is down...
1747                  */
1748                 /* warn the system administrator */
1749                 if (open_warning_by_mail(ctl, (struct msgblk *)NULL) == 0)
1750                 {
1751                     stuff_warning(ctl,
1752                          _("Subject: Fetchmail unreachable-server warning.\r\n"
1753                            "\r\n"
1754                            "Fetchmail could not reach the mail server %s:")
1755                                   ctl->server.pollname);
1756                     stuff_warning(ctl, errbuf, ctl->server.pollname);
1757                     close_warning_by_mail(ctl, (struct msgblk *)NULL);
1758                 }
1759 #endif
1760             }
1761 #endif /* INET6_ENABLE */
1762             ok = PS_SOCKET;
1763             set_timeout(0);
1764             phase = oldphase;
1765             goto closeUp;
1766         }
1767         set_timeout(0);
1768         phase = oldphase;
1769
1770 #ifdef SSL_ENABLE
1771         /* perform initial SSL handshake on open connection */
1772         /* Note:  We pass the realhost name over for certificate
1773                 verification.  We may want to make this configurable */
1774         if (ctl->use_ssl && SSLOpen(mailserver_socket,ctl->sslkey,ctl->sslcert,ctl->sslproto,ctl->sslcertck,
1775             ctl->sslcertpath,ctl->sslfingerprint,realhost,ctl->server.pollname) == -1) 
1776         {
1777             report(stderr, _("SSL connection failed.\n"));
1778             goto closeUp;
1779         }
1780 #endif
1781
1782 #ifdef KERBEROS_V4
1783         if (ctl->server.authenticate == A_KERBEROS_V4)
1784         {
1785             set_timeout(mytimeout);
1786             ok = kerberos_auth(mailserver_socket, ctl->server.truename,
1787                                ctl->server.principal);
1788             set_timeout(0);
1789             if (ok != 0)
1790                 goto cleanUp;
1791         }
1792 #endif /* KERBEROS_V4 */
1793
1794 #ifdef KERBEROS_V5
1795         if (ctl->server.authenticate == A_KERBEROS_V5)
1796         {
1797             set_timeout(mytimeout);
1798             ok = kerberos5_auth(mailserver_socket, ctl->server.truename);
1799             set_timeout(0);
1800             if (ok != 0)
1801                 goto cleanUp;
1802         }
1803 #endif /* KERBEROS_V5 */
1804
1805         /* accept greeting message from mail server */
1806         ok = (protocol->parse_response)(mailserver_socket, buf);
1807         if (ok != 0)
1808             goto cleanUp;
1809
1810         /* try to get authorized to fetch mail */
1811         stage = STAGE_GETAUTH;
1812         if (protocol->getauth)
1813         {
1814             ok = (protocol->getauth)(mailserver_socket, ctl, buf);
1815
1816             if (ok != 0)
1817             {
1818                 if (ok == PS_LOCKBUSY)
1819                     report(stderr, _("Lock-busy error on %s@%s\n"),
1820                           ctl->remotename,
1821                           ctl->server.truename);
1822                 else if (ok == PS_SERVBUSY)
1823                     report(stderr, _("Server busy error on %s@%s\n"),
1824                           ctl->remotename,
1825                           ctl->server.truename);
1826                 else if (ok == PS_AUTHFAIL)
1827                 {
1828                     report(stderr, _("Authorization failure on %s@%s%s\n"), 
1829                            ctl->remotename,
1830                            ctl->server.truename,
1831                            (ctl->wehaveauthed ? _(" (previously authorized)") : "")
1832                         );
1833
1834                     /*
1835                      * If we're running in background, try to mail the
1836                      * calling user a heads-up about the authentication 
1837                      * failure once it looks like this isn't a fluke 
1838                      * due to the server being temporarily inaccessible.
1839                      * When we get third succesive failure, we notify the user
1840                      * but only if we haven't already managed to get
1841                      * authorization.  After that, once we get authorization
1842                      * we let the user know service is restored.
1843                      */
1844                     if (run.poll_interval
1845                         && ctl->wehavesentauthnote
1846                         && ((ctl->wehaveauthed && ++ctl->authfailcount == 10)
1847                             || ++ctl->authfailcount == 3)
1848                         && !open_warning_by_mail(ctl, (struct msgblk *)NULL))
1849                     {
1850                         ctl->wehavesentauthnote = 1;
1851                         stuff_warning(ctl,
1852                                       _("Subject: fetchmail authentication failed on %s@%s\r\n"),
1853                             ctl->remotename, ctl->server.truename);
1854                         stuff_warning(ctl,
1855                                       _("Fetchmail could not get mail from %s@%s.\r\n"), 
1856                                       ctl->remotename,
1857                                       ctl->server.truename);
1858                         if (ctl->wehaveauthed)
1859                             stuff_warning(ctl, _("\
1860 The attempt to get authorization failed.\r\n\
1861 Since we have already succeeded in getting authorization for this\r\n\
1862 connection, this is probably another failure mode (such as busy server)\r\n\
1863 that fetchmail cannot distinguish because the server didn't send a useful\r\n\
1864 error message.\r\n\
1865 \r\n\
1866 However, if you HAVE changed you account details since starting the\r\n\
1867 fetchmail daemon, you need to stop the daemon, change your configuration\r\n\
1868 of fetchmail, and then restart the daemon.\r\n\
1869 \r\n\
1870 The fetchmail daemon will continue running and attempt to connect\r\n\
1871 at each cycle.  No future notifications will be sent until service\r\n\
1872 is restored."));
1873                         else
1874                             stuff_warning(ctl, _("\
1875 The attempt to get authorization failed.\r\n\
1876 This probably means your password is invalid, but some servers have\r\n\
1877 other failure modes that fetchmail cannot distinguish from this\r\n\
1878 because they don't send useful error messages on login failure.\r\n\
1879 \r\n\
1880 The fetchmail daemon will continue running and attempt to connect\r\n\
1881 at each cycle.  No future notifications will be sent until service\r\n\
1882 is restored."));
1883                         close_warning_by_mail(ctl, (struct msgblk *)NULL);
1884                     }
1885                 }
1886                 else
1887                     report(stderr, _("Unknown login or authentication error on %s@%s\n"),
1888                            ctl->remotename,
1889                            ctl->server.truename);
1890                     
1891                 goto cleanUp;
1892             }
1893             else
1894             {
1895                 /*
1896                  * This connection has given us authorization at least once.
1897                  *
1898                  * There are dodgy server (clubinternet.fr for example) that
1899                  * give spurious authorization failures on patently good
1900                  * account/password details, then 5 minutes later let you in!
1901                  *
1902                  * This is meant to build in some tolerance of such nasty bits
1903                  * of work.
1904                  */
1905                 ctl->wehaveauthed = 1;
1906                 /*if (ctl->authfailcount >= 3)*/
1907                 if (ctl->wehavesentauthnote)
1908                 {
1909                     ctl->wehavesentauthnote = 0;
1910                     report(stderr,
1911                            _("Authorization OK on %s@%s\n"),
1912                            ctl->remotename,
1913                            ctl->server.truename);
1914                     if (!open_warning_by_mail(ctl, (struct msgblk *)NULL))
1915                     {
1916                         stuff_warning(ctl,
1917                               _("Subject: fetchmail authentication OK on %s@%s\r\n"),
1918                                       ctl->remotename, ctl->server.truename);
1919                         stuff_warning(ctl,
1920                               _("Fetchmail was able to log into %s@%s.\r\n"), 
1921                                       ctl->remotename,
1922                                       ctl->server.truename);
1923                         stuff_warning(ctl, 
1924                                       _("Service has been restored.\r\n"));
1925                         close_warning_by_mail(ctl, (struct msgblk *)NULL);
1926                     
1927                     }
1928                 }
1929                 /*
1930                  * Reporting only after the first three
1931                  * consecutive failures, or ten consecutive
1932                  * failures after we have managed to get
1933                  * authorization.
1934                  */
1935                 ctl->authfailcount = 0;
1936             }
1937         }
1938
1939         ctl->errcount = fetches = 0;
1940
1941         /* now iterate over each folder selected */
1942         for (idp = ctl->mailboxes; idp; idp = idp->next)
1943         {
1944             pass = 0;
1945             do {
1946                 dispatches = 0;
1947                 ++pass;
1948
1949                 /* reset timeout, in case we did an IDLE */
1950                 mytimeout = ctl->server.timeout;
1951
1952                 if (outlevel >= O_DEBUG)
1953                 {
1954                     if (idp->id)
1955                         report(stdout, _("selecting or re-polling folder %s\n"), idp->id);
1956                     else
1957                         report(stdout, _("selecting or re-polling default folder\n"));
1958                 }
1959
1960                 /* compute # of messages and number of new messages waiting */
1961                 stage = STAGE_GETRANGE;
1962                 ok = (protocol->getrange)(mailserver_socket, ctl, idp->id, &count, &new, &bytes);
1963                 if (ok != 0)
1964                     goto cleanUp;
1965
1966                 /* show user how many messages we downloaded */
1967                 if (idp->id)
1968                     (void) sprintf(buf, _("%s at %s (folder %s)"),
1969                                    ctl->remotename, ctl->server.truename, idp->id);
1970                 else
1971                     (void) sprintf(buf, _("%s at %s"),
1972                                    ctl->remotename, ctl->server.truename);
1973                 if (outlevel > O_SILENT)
1974                 {
1975                     if (count == -1)            /* only used for ETRN */
1976                         report(stdout, _("Polling %s\n"), ctl->server.truename);
1977                     else if (count != 0)
1978                     {
1979                         if (new != -1 && (count - new) > 0)
1980                             report_build(stdout, _("%d %s (%d seen) for %s"),
1981                                   count, count > 1 ? _("messages") :
1982                                                      _("message"),
1983                                   count-new, buf);
1984                         else
1985                             report_build(stdout, _("%d %s for %s"), 
1986                                   count, count > 1 ? _("messages") :
1987                                                      _("message"), buf);
1988                         if (bytes == -1)
1989                             report_complete(stdout, ".\n");
1990                         else
1991                             report_complete(stdout, _(" (%d octets).\n"), bytes);
1992                     }
1993                     else
1994                     {
1995                         /* these are pointless in normal daemon mode */
1996                         if (pass == 1 && (run.poll_interval == 0 || outlevel >= O_VERBOSE))
1997                             report(stdout, _("No mail for %s\n"), buf); 
1998                     }
1999                 }
2000
2001                 /* very important, this is where we leave the do loop */ 
2002                 if (count == 0)
2003                     break;
2004
2005                 if (check_only)
2006                 {
2007                     if (new == -1 || ctl->fetchall)
2008                         new = count;
2009                     fetches = new;      /* set error status ccorrectly */
2010                     /*
2011                      * There used to be a `got noerror' here, but this
2012                      * prevneted checking of multiple folders.  This
2013                      * comment is a reminder in case I introduced some
2014                      * subtle bug by removing it...
2015                      */
2016                 }
2017                 else if (count > 0)
2018                 {    
2019                     flag        force_retrieval;
2020
2021                     /*
2022                      * What forces this code is that in POP2 and
2023                      * IMAP2bis you can't fetch a message without
2024                      * having it marked `seen'.  In POP3 and IMAP4, on the
2025                      * other hand, you can (peek_capable is set by 
2026                      * each driver module to convey this; it's not a
2027                      * method constant because of the difference between
2028                      * IMAP2bis and IMAP4, and because POP3 doesn't  peek
2029                      * if fetchall is on).
2030                      *
2031                      * The result of being unable to peek is that if there's
2032                      * any kind of transient error (DNS lookup failure, or
2033                      * sendmail refusing delivery due to process-table limits)
2034                      * the message will be marked "seen" on the server without
2035                      * having been delivered.  This is not a big problem if
2036                      * fetchmail is running in foreground, because the user
2037                      * will see a "skipped" message when it next runs and get
2038                      * clued in.
2039                      *
2040                      * But in daemon mode this leads to the message
2041                      * being silently ignored forever.  This is not
2042                      * acceptable.
2043                      *
2044                      * We compensate for this by checking the error
2045                      * count from the previous pass and forcing all
2046                      * messages to be considered new if it's nonzero.
2047                      */
2048                     force_retrieval = !peek_capable && (ctl->errcount > 0);
2049
2050                     /* 
2051                      * We need the size of each message before it's
2052                      * loaded in order to pass it to the ESMTP SIZE
2053                      * option.  If the protocol has a getsizes method,
2054                      * we presume this means it doesn't get reliable
2055                      * sizes from message fetch responses.
2056                      */
2057                     if (proto->getsizes)
2058                     {
2059                         int     i;
2060
2061                         xalloca(msgsizes, int *, sizeof(int) * count);
2062                         for (i = 0; i < count; i++)
2063                             msgsizes[i] = -1;
2064
2065                         stage = STAGE_GETSIZES;
2066                         ok = (proto->getsizes)(mailserver_socket, count, msgsizes);
2067                         if (ok != 0)
2068                             goto cleanUp;
2069
2070                         if (bytes == -1)
2071                         {
2072                             bytes = 0;
2073                             for (i = 0; i < count; i++)
2074                                 bytes += msgsizes[i];
2075                         }
2076                     }
2077
2078                     /* read, forward, and delete messages */
2079                     stage = STAGE_FETCH;
2080                     for (num = 1; num <= count; num++)
2081                     {
2082                         flag toolarge = NUM_NONZERO(ctl->limit)
2083                             && msgsizes && (msgsizes[num-1] > ctl->limit);
2084                         flag oldmsg = (!new) || (protocol->is_old && (protocol->is_old)(mailserver_socket,ctl,num));
2085                         flag fetch_it = !toolarge 
2086                             && (ctl->fetchall || force_retrieval || !oldmsg);
2087                         flag suppress_delete = FALSE;
2088                         flag suppress_forward = FALSE;
2089                         flag suppress_readbody = FALSE;
2090                         flag retained = FALSE;
2091
2092                         /*
2093                          * This check copes with Post Office/NT's
2094                          * annoying habit of randomly prepending bogus
2095                          * LIST items of length -1.  Patrick Audley
2096                          * <paudley@pobox.com> tells us: LIST shows a
2097                          * size of -1, RETR and TOP return "-ERR
2098                          * System error - couldn't open message", and
2099                          * DELE succeeds but doesn't actually delete
2100                          * the message.
2101                          */
2102                         if (msgsizes && msgsizes[num-1] == -1)
2103                         {
2104                             if (outlevel >= O_VERBOSE)
2105                                 report(stdout, 
2106                                       _("Skipping message %d, length -1\n"),
2107                                       num);
2108                             continue;
2109                         }
2110
2111                         /*
2112                          * We may want to reject this message if it's old
2113                          * or oversized, and we're not forcing retrieval.
2114                          */
2115                         if (!fetch_it)
2116                         {
2117                             if (outlevel > O_SILENT)
2118                             {
2119                                 report_build(stdout, 
2120                                      _("skipping message %d (%d octets)"),
2121                                      num, msgsizes[num-1]);
2122                                 if (toolarge && !check_only) 
2123                                 {
2124                                     char size[32];
2125                                     int cnt;
2126
2127                                     /* convert sz to string */
2128                                     sprintf(size, "%d", msgsizes[num-1]);
2129
2130                                     /* build a list of skipped messages
2131                                      * val.id = size of msg (string cnvt)
2132                                      * val.status.num = warning_poll_count
2133                                      * val.status.mask = nbr of msg this size
2134                                      */
2135
2136                                     current = ctl->skipped;
2137
2138                                     /* initialise warning_poll_count to the
2139                                      * current value so that all new msg will
2140                                      * be included in the next mail
2141                                      */
2142                                     cnt = current? current->val.status.num : 0;
2143
2144                                     /* if entry exists, increment the count */
2145                                     if (current && 
2146                                         str_in_list(&current, size, FALSE))
2147                                     {
2148                                         for ( ; current; 
2149                                                 current = current->next)
2150                                         {
2151                                             if (strcmp(current->id, size) == 0)
2152                                             {
2153                                                 current->val.status.mark++;
2154                                                 break;
2155                                             }
2156                                         }
2157                                     }
2158                                     /* otherwise, create a new entry */
2159                                     /* initialise with current poll count */
2160                                     else
2161                                     {
2162                                         tmp = save_str(&ctl->skipped, size, 1);
2163                                         tmp->val.status.num = cnt;
2164                                     }
2165
2166                                     report_build(stdout, _(" (oversized, %d octets)"),
2167                                                 msgsizes[num-1]);
2168                                 }
2169                             }
2170                         }
2171                         else
2172                         {
2173                             flag wholesize = !protocol->fetch_body;
2174
2175                             /* request a message */
2176                             ok = (protocol->fetch_headers)(mailserver_socket,ctl,num, &len);
2177                             if (ok != 0)
2178                                 goto cleanUp;
2179
2180                             /* -1 means we didn't see a size in the response */
2181                             if (len == -1 && msgsizes)
2182                             {
2183                                 len = msgsizes[num - 1];
2184                                 wholesize = TRUE;
2185                             }
2186
2187                             if (outlevel > O_SILENT)
2188                             {
2189                                 report_build(stdout, _("reading message %d of %d"),
2190                                             num,count);
2191
2192                                 if (len > 0)
2193                                     report_build(stdout, _(" (%d %soctets)"),
2194                                         len, wholesize ? "" : _("header "));
2195                                 if (outlevel >= O_VERBOSE)
2196                                     report_complete(stdout, "\n");
2197                                 else
2198                                     report_complete(stdout, " ");
2199                             }
2200
2201                             /* 
2202                              * Read the message headers and ship them to the
2203                              * output sink.  
2204                              */
2205                             ok = readheaders(mailserver_socket, len, msgsizes[num-1],
2206                                              ctl, num);
2207                             if (ok == PS_RETAINED)
2208                                 suppress_forward = retained = TRUE;
2209                             else if (ok == PS_TRANSIENT)
2210                                 suppress_delete = suppress_forward = TRUE;
2211                             else if (ok == PS_REFUSED)
2212                                 suppress_forward = TRUE;
2213                             else if (ok == PS_TRUNCATED)
2214                                 suppress_readbody = TRUE;
2215                             else if (ok)
2216                                 goto cleanUp;
2217
2218                             /* 
2219                              * If we're using IMAP4 or something else that
2220                              * can fetch headers separately from bodies,
2221                              * it's time to request the body now.  This
2222                              * fetch may be skipped if we got an anti-spam
2223                              * or other PS_REFUSED error response during
2224                              * readheaders.
2225                              */
2226                             if (protocol->fetch_body && !suppress_readbody) 
2227                             {
2228                                 if (outlevel >= O_VERBOSE && !isafile(1))
2229                                 {
2230                                     fputc('\n', stdout);
2231                                     fflush(stdout);
2232                                 }
2233
2234                                 if ((ok = (protocol->trail)(mailserver_socket, ctl, num)))
2235                                     goto cleanUp;
2236                                 len = 0;
2237                                 if (!suppress_forward)
2238                                 {
2239                                     if ((ok=(protocol->fetch_body)(mailserver_socket,ctl,num,&len)))
2240                                         goto cleanUp;
2241                                     /*
2242                                      * Work around a bug in Novell's
2243                                      * broken GroupWise IMAP server;
2244                                      * its body FETCH response is missing
2245                                      * the required length for the data
2246                                      * string.  This violates RFC2060.
2247                                      */
2248                                     if (len == -1)
2249                                        len = msgsizes[num-1] - msglen;
2250                                     if (outlevel > O_SILENT && !wholesize)
2251                                         report_complete(stdout,
2252                                                _(" (%d body octets) "), len);
2253                                 }
2254                             }
2255
2256                             /* process the body now */
2257                             if (len > 0)
2258                             {
2259                                 if (suppress_readbody)
2260                                 {
2261                                   /* When readheaders returns PS_TRUNCATED,
2262                                      the body (which has no content
2263                                      has already been read by readheaders,
2264                                      so we say readbody returned PS_SUCCESS */
2265                                   ok = PS_SUCCESS;
2266                                 }
2267                                 else
2268                                 {
2269                                   ok = readbody(mailserver_socket,
2270                                                 ctl,
2271                                                 !suppress_forward,
2272                                                 len);
2273                                 }
2274                                 if (ok == PS_TRANSIENT)
2275                                     suppress_delete = suppress_forward = TRUE;
2276                                 else if (ok)
2277                                     goto cleanUp;
2278
2279                                 /* tell server we got it OK and resynchronize */
2280                                 if (protocol->trail)
2281                                 {
2282                                     if (outlevel >= O_VERBOSE && !isafile(1))
2283                                     {
2284                                         fputc('\n', stdout);
2285                                         fflush(stdout);
2286                                     }
2287
2288                                     ok = (protocol->trail)(mailserver_socket, ctl, num);
2289                                     if (ok != 0)
2290                                         goto cleanUp;
2291                                 }
2292                             }
2293
2294                             /* count # messages forwarded on this pass */
2295                             if (!suppress_forward)
2296                                 dispatches++;
2297
2298                             /*
2299                              * Check to see if the numbers matched?
2300                              *
2301                              * Yes, some servers foo this up horribly.
2302                              * All IMAP servers seem to get it right, and
2303                              * so does Eudora QPOP at least in 2.xx
2304                              * versions.
2305                              *
2306                              * Microsoft Exchange gets it completely
2307                              * wrong, reporting compressed rather than
2308                              * actual sizes (so the actual length of
2309                              * message is longer than the reported size).
2310                              * Another fine example of Microsoft brain death!
2311                              *
2312                              * Some older POP servers, like the old UCB
2313                              * POP server and the pre-QPOP QUALCOMM
2314                              * versions, report a longer size in the LIST
2315                              * response than actually gets shipped up.
2316                              * It's unclear what is going on here, as the
2317                              * QUALCOMM server (at least) seems to be
2318                              * reporting the on-disk size correctly.
2319                              */
2320                             if (msgsizes && msglen != msgsizes[num-1])
2321                             {
2322                                 if (outlevel >= O_DEBUG)
2323                                     report(stdout,
2324                                           _("message %d was not the expected length (%d actual != %d expected)\n"),
2325                                           num, msglen, msgsizes[num-1]);
2326                             }
2327
2328                             /* end-of-message processing starts here */
2329                             if (!close_sink(ctl, &msgblk, !suppress_forward))
2330                             {
2331                                 ctl->errcount++;
2332                                 suppress_delete = TRUE;
2333                             }
2334                             fetches++;
2335                         }
2336
2337                         /*
2338                          * At this point in flow of control, either
2339                          * we've bombed on a protocol error or had
2340                          * delivery refused by the SMTP server
2341                          * (unlikely -- I've never seen it) or we've
2342                          * seen `accepted for delivery' and the
2343                          * message is shipped.  It's safe to mark the
2344                          * message seen and delete it on the server
2345                          * now.
2346                          */
2347
2348                         /* tell the UID code we've seen this */
2349                         if (ctl->newsaved)
2350                         {
2351                             struct idlist       *sdp;
2352
2353                             for (sdp = ctl->newsaved; sdp; sdp = sdp->next)
2354                                 if ((sdp->val.status.num == num)
2355                                                 && (!toolarge || oldmsg)) 
2356                                 {
2357                                     sdp->val.status.mark = UID_SEEN;
2358                                     save_str(&ctl->oldsaved, sdp->id,UID_SEEN);
2359                                 }
2360                         }
2361
2362                         /* maybe we delete this message now? */
2363                         if (retained)
2364                         {
2365                             if (outlevel > O_SILENT) 
2366                                 report(stdout, _(" retained\n"));
2367                         }
2368                         else if (protocol->delete
2369                                  && !suppress_delete
2370                                  && (fetch_it ? !ctl->keep : ctl->flush))
2371                         {
2372                             deletions++;
2373                             if (outlevel > O_SILENT) 
2374                                 report_complete(stdout, _(" flushed\n"));
2375                             ok = (protocol->delete)(mailserver_socket, ctl, num);
2376                             if (ok != 0)
2377                                 goto cleanUp;
2378 #ifdef POP3_ENABLE
2379                             delete_str(&ctl->newsaved, num);
2380 #endif /* POP3_ENABLE */
2381                         }
2382                         else if (outlevel > O_SILENT) 
2383                             report_complete(stdout, _(" not flushed\n"));
2384
2385                         /* perhaps this as many as we're ready to handle */
2386                         if (maxfetch && maxfetch <= fetches && fetches < count)
2387                         {
2388                             report(stdout, _("fetchlimit %d reached; %d messages left on server\n"),
2389                                   maxfetch, count - fetches);
2390                             ok = PS_MAXFETCH;
2391                             goto cleanUp;
2392                         }
2393                     }
2394
2395                     if (!check_only && ctl->skipped
2396                         && run.poll_interval > 0 && !nodetach)
2397                     {
2398                         clean_skipped_list(&ctl->skipped);
2399                         send_size_warnings(ctl);
2400                     }
2401                 }
2402             } while
2403                   /*
2404                    * Only re-poll if we either had some actual forwards and 
2405                    * either allowed deletions and had no errors.
2406                    * Otherwise it is far too easy to get into infinite loops.
2407                    */
2408                   (dispatches && protocol->retry && !ctl->keep && !ctl->errcount);
2409         }
2410
2411     /* no_error: */
2412         /* ordinary termination with no errors -- officially log out */
2413         ok = (protocol->logout_cmd)(mailserver_socket, ctl);
2414         /*
2415          * Hmmmm...arguably this would be incorrect if we had fetches but
2416          * no dispatches (due to oversized messages, etc.)
2417          */
2418         if (ok == 0)
2419             ok = (fetches > 0) ? PS_SUCCESS : PS_NOMAIL;
2420         SockClose(mailserver_socket);
2421         goto closeUp;
2422
2423     cleanUp:
2424         /* we only get here on error */
2425         if (ok != 0 && ok != PS_SOCKET)
2426         {
2427             stage = STAGE_LOGOUT;
2428             (protocol->logout_cmd)(mailserver_socket, ctl);
2429         }
2430         SockClose(mailserver_socket);
2431     }
2432
2433     msg = (const char *)NULL;   /* sacrifice to -Wall */
2434     switch (ok)
2435     {
2436     case PS_SOCKET:
2437         msg = _("socket");
2438         break;
2439     case PS_SYNTAX:
2440         msg = _("missing or bad RFC822 header");
2441         break;
2442     case PS_IOERR:
2443         msg = _("MDA");
2444         break;
2445     case PS_ERROR:
2446         msg = _("client/server synchronization");
2447         break;
2448     case PS_PROTOCOL:
2449         msg = _("client/server protocol");
2450         break;
2451     case PS_LOCKBUSY:
2452         msg = _("lock busy on server");
2453         break;
2454     case PS_SMTP:
2455         msg = _("SMTP transaction");
2456         break;
2457     case PS_DNS:
2458         msg = _("DNS lookup");
2459         break;
2460     case PS_UNDEFINED:
2461         report(stderr, _("undefined error\n"));
2462         break;
2463     }
2464     /* no report on PS_MAXFETCH or PS_UNDEFINED or PS_AUTHFAIL */
2465     if (ok==PS_SOCKET || ok==PS_SYNTAX
2466                 || ok==PS_IOERR || ok==PS_ERROR || ok==PS_PROTOCOL 
2467                 || ok==PS_LOCKBUSY || ok==PS_SMTP || ok==PS_DNS)
2468     {
2469         char    *stem;
2470
2471         if (phase == FORWARDING_WAIT || phase == LISTENER_WAIT)
2472             stem = _("%s error while delivering to SMTP host %s\n");
2473         else
2474             stem = _("%s error while fetching from %s\n");
2475         report(stderr, stem, msg, ctl->server.pollname);
2476     }
2477
2478 closeUp:
2479     /* execute wrapup command, if any */
2480     if (ctl->postconnect && (ok = system(ctl->postconnect)))
2481     {
2482         report(stderr, _("post-connection command failed with status %d\n"), ok);
2483         if (ok == PS_SUCCESS)
2484             ok = PS_SYNTAX;
2485     }
2486
2487     signal(SIGALRM, alrmsave);
2488     signal(SIGPIPE, pipesave);
2489     return(ok);
2490 }
2491
2492 int do_protocol(ctl, proto)
2493 /* retrieve messages from server using given protocol method table */
2494 struct query *ctl;              /* parsed options with merged-in defaults */
2495 const struct method *proto;     /* protocol method table */
2496 {
2497     int ok;
2498
2499 #ifndef KERBEROS_V4
2500     if (ctl->server.authenticate == A_KERBEROS_V4)
2501     {
2502         report(stderr, _("Kerberos V4 support not linked.\n"));
2503         return(PS_ERROR);
2504     }
2505 #endif /* KERBEROS_V4 */
2506
2507 #ifndef KERBEROS_V5
2508     if (ctl->server.authenticate == A_KERBEROS_V5)
2509     {
2510         report(stderr, _("Kerberos V5 support not linked.\n"));
2511         return(PS_ERROR);
2512     }
2513 #endif /* KERBEROS_V5 */
2514
2515     /* lacking methods, there are some options that may fail */
2516     if (!proto->is_old)
2517     {
2518         /* check for unsupported options */
2519         if (ctl->flush) {
2520             report(stderr,
2521                     _("Option --flush is not supported with %s\n"),
2522                     proto->name);
2523             return(PS_SYNTAX);
2524         }
2525         else if (ctl->fetchall) {
2526             report(stderr,
2527                     _("Option --all is not supported with %s\n"),
2528                     proto->name);
2529             return(PS_SYNTAX);
2530         }
2531     }
2532     if (!proto->getsizes && NUM_SPECIFIED(ctl->limit))
2533     {
2534         report(stderr,
2535                 _("Option --limit is not supported with %s\n"),
2536                 proto->name);
2537         return(PS_SYNTAX);
2538     }
2539
2540     /*
2541      * If no expunge limit or we do expunges within the driver,
2542      * then just do one session, passing in any fetchlimit.
2543      */
2544     if (proto->retry || !NUM_SPECIFIED(ctl->expunge))
2545         return(do_session(ctl, proto, NUM_VALUE_OUT(ctl->fetchlimit)));
2546     /*
2547      * There's an expunge limit, and it isn't handled in the driver itself.
2548      * OK; do multiple sessions, each fetching a limited # of messages.
2549      * Stop if the total count of retrieved messages exceeds ctl->fetchlimit
2550      * (if it was nonzero).
2551      */
2552     else
2553     {
2554         int totalcount = 0; 
2555         int lockouts   = 0;
2556         int expunge    = NUM_VALUE_OUT(ctl->expunge);
2557         int fetchlimit = NUM_VALUE_OUT(ctl->fetchlimit);
2558
2559         do {
2560             if (fetchlimit > 0 && (expunge == 0 || expunge > fetchlimit - totalcount))
2561                 expunge = fetchlimit - totalcount;
2562             ok = do_session(ctl, proto, expunge);
2563             totalcount += expunge;
2564             if (NUM_SPECIFIED(ctl->fetchlimit) && totalcount >= fetchlimit)
2565                 break;
2566             if (ok != PS_LOCKBUSY)
2567                 lockouts = 0;
2568             else if (lockouts >= MAX_LOCKOUTS)
2569                 break;
2570             else /* ok == PS_LOCKBUSY */
2571             {
2572                 /*
2573                  * Allow time for the server lock to release.  if we
2574                  * don't do this, we'll often hit a locked-mailbox
2575                  * condition and fail.
2576                  */
2577                 lockouts++;
2578                 sleep(3);
2579             }
2580         } while
2581             (ok == PS_MAXFETCH || ok == PS_LOCKBUSY);
2582
2583         return(ok);
2584     }
2585 }
2586
2587 #if defined(HAVE_STDARG_H)
2588 void gen_send(int sock, const char *fmt, ... )
2589 #else
2590 void gen_send(sock, fmt, va_alist)
2591 int sock;               /* socket to which server is connected */
2592 const char *fmt;        /* printf-style format */
2593 va_dcl
2594 #endif
2595 /* assemble command in printf(3) style and send to the server */
2596 {
2597     char buf [MSGBUFSIZE+1];
2598     va_list ap;
2599
2600     if (protocol->tagged && !suppress_tags)
2601         (void) sprintf(buf, "%s ", GENSYM);
2602     else
2603         buf[0] = '\0';
2604
2605 #if defined(HAVE_STDARG_H)
2606     va_start(ap, fmt) ;
2607 #else
2608     va_start(ap);
2609 #endif
2610 #ifdef HAVE_VSNPRINTF
2611     vsnprintf(buf + strlen(buf), sizeof(buf), fmt, ap);
2612 #else
2613     vsprintf(buf + strlen(buf), fmt, ap);
2614 #endif
2615     va_end(ap);
2616
2617     strcat(buf, "\r\n");
2618     SockWrite(sock, buf, strlen(buf));
2619
2620     if (outlevel >= O_MONITOR)
2621     {
2622         char *cp;
2623
2624         if (shroud[0] && (cp = strstr(buf, shroud)))
2625         {
2626             char        *sp;
2627
2628             sp = cp + strlen(shroud);
2629             *cp++ = '*';
2630             while (*sp)
2631                 *cp++ = *sp++;
2632             *cp = '\0';
2633         }
2634         buf[strlen(buf)-2] = '\0';
2635         report(stdout, "%s> %s\n", protocol->name, buf);
2636     }
2637 }
2638
2639 int gen_recv(sock, buf, size)
2640 /* get one line of input from the server */
2641 int sock;       /* socket to which server is connected */
2642 char *buf;      /* buffer to receive input */
2643 int size;       /* length of buffer */
2644 {
2645     int oldphase = phase;       /* we don't have to be re-entrant */
2646
2647     phase = SERVER_WAIT;
2648     set_timeout(mytimeout);
2649     if (SockRead(sock, buf, size) == -1)
2650     {
2651         set_timeout(0);
2652         phase = oldphase;
2653         return(PS_SOCKET);
2654     }
2655     else
2656     {
2657         set_timeout(0);
2658         if (buf[strlen(buf)-1] == '\n')
2659             buf[strlen(buf)-1] = '\0';
2660         if (buf[strlen(buf)-1] == '\r')
2661             buf[strlen(buf)-1] = '\0';
2662         if (outlevel >= O_MONITOR)
2663             report(stdout, "%s< %s\n", protocol->name, buf);
2664         phase = oldphase;
2665         return(PS_SUCCESS);
2666     }
2667 }
2668
2669 #if defined(HAVE_STDARG_H)
2670 int gen_transact(int sock, const char *fmt, ... )
2671 #else
2672 int gen_transact(int sock, fmt, va_alist)
2673 int sock;               /* socket to which server is connected */
2674 const char *fmt;        /* printf-style format */
2675 va_dcl
2676 #endif
2677 /* assemble command in printf(3) style, send to server, accept a response */
2678 {
2679     int ok;
2680     char buf [MSGBUFSIZE+1];
2681     va_list ap;
2682     int oldphase = phase;       /* we don't have to be re-entrant */
2683
2684     phase = SERVER_WAIT;
2685
2686     if (protocol->tagged && !suppress_tags)
2687         (void) sprintf(buf, "%s ", GENSYM);
2688     else
2689         buf[0] = '\0';
2690
2691 #if defined(HAVE_STDARG_H)
2692     va_start(ap, fmt) ;
2693 #else
2694     va_start(ap);
2695 #endif
2696 #ifdef HAVE_VSNPRINTF
2697     vsnprintf(buf + strlen(buf), sizeof(buf), fmt, ap);
2698 #else
2699     vsprintf(buf + strlen(buf), fmt, ap);
2700 #endif
2701     va_end(ap);
2702
2703     strcat(buf, "\r\n");
2704     SockWrite(sock, buf, strlen(buf));
2705
2706     if (outlevel >= O_MONITOR)
2707     {
2708         char *cp;
2709
2710         if (shroud && shroud[0] && (cp = strstr(buf, shroud)))
2711         {
2712             char        *sp;
2713
2714             sp = cp + strlen(shroud);
2715             *cp++ = '*';
2716             while (*sp)
2717                 *cp++ = *sp++;
2718             *cp = '\0';
2719         }
2720         buf[strlen(buf)-1] = '\0';
2721         report(stdout, "%s> %s\n", protocol->name, buf);
2722     }
2723
2724     /* we presume this does its own response echoing */
2725     ok = (protocol->parse_response)(sock, buf);
2726
2727     phase = oldphase;
2728     return(ok);
2729 }
2730
2731 /* driver.c ends here */