]> Pileus Git - ~andy/fetchmail/blob - driver.c
Solve a SIGCLD compilation problem.
[~andy/fetchmail] / driver.c
1 /*
2  * driver.c -- generic driver for mail fetch method protocols
3  *
4  * Copyright 1996 by Eric S. Raymond
5  * All rights reserved.
6  * For license terms, see the file COPYING in this directory.
7  */
8
9 #include  <config.h>
10 #include  <stdio.h>
11 #include  <setjmp.h>
12 #include  <ctype.h>
13 #include  <string.h>
14 #if defined(STDC_HEADERS)
15 #include  <stdlib.h>
16 #endif
17 #if defined(HAVE_UNISTD_H)
18 #include <unistd.h>
19 #endif
20 #if defined(HAVE_STDARG_H)
21 #include  <stdarg.h>
22 #else
23 #include  <varargs.h>
24 #endif
25 #if defined(HAVE_ALLOCA_H)
26 #include <alloca.h>
27 #endif
28 #include  <sys/time.h>
29 #include  <signal.h>
30
31 #ifdef HAVE_GETHOSTBYNAME
32 #include <netdb.h>
33 #include "mx.h"
34 #endif /* HAVE_GETHOSTBYNAME */
35
36 #ifdef KERBEROS_V4
37 #include <krb.h>
38 #include <des.h>
39 #include <netinet/in.h>         /* must be included before "socket.h".*/
40 #include <netdb.h>
41 #endif /* KERBEROS_V4 */
42 #include  "socket.h"
43 #include  "fetchmail.h"
44 #include  "smtp.h"
45
46 /* BSD portability hack...I know, this is an ugly place to put it */
47 #if !defined(SIGCLD) && defined(SIGCHLD)
48 #define SIGCLD  SIGCHLD
49 #endif
50
51 #define SMTP_PORT       25      /* standard SMTP service port */
52
53 int batchlimit;         /* how often to tear down the delivery connection */
54 int batchcount;         /* count of messages sent in current batch */
55 int peek_capable;       /* can we peek for better error recovery? */
56
57 static const struct method *protocol;
58 static jmp_buf  restart;
59
60 char tag[TAGLEN];
61 static int tagnum;
62 #define GENSYM  (sprintf(tag, "a%04d", ++tagnum), tag)
63
64 static char *shroud;    /* string to shroud in debug output, if  non-NULL */
65 static int mytimeout;   /* value of nonreponse timeout */
66
67 static int strcrlf(dst, src, count)
68 /* replace LFs with CR-LF; return length of string with replacements */
69 char *dst;      /* new string with CR-LFs */
70 char *src;      /* original string with LFs */
71 int count;      /* length of src */
72 {
73   int len = count;
74
75   while (count--)
76   {
77       if (*src == '\n')
78       {
79           *dst++ = '\r';
80           len++;
81       }
82       *dst++ = *src++;
83   }
84   *dst = '\0';
85   return len;
86 }
87
88 static void vtalarm(int timeleft)
89 /* reset the nonresponse-timeout */
90 {
91     struct itimerval ntimeout;
92
93     ntimeout.it_interval.tv_sec = ntimeout.it_interval.tv_usec = 0;
94     ntimeout.it_value.tv_sec  = timeleft;
95     ntimeout.it_value.tv_usec = 0;
96     setitimer(ITIMER_VIRTUAL, &ntimeout, (struct itimerval *)NULL);
97 }
98
99 static void vtalarm_handler (int signal)
100 /* handle server-timeout SIGVTALARM signal */
101 {
102     longjmp(restart, 1);
103 }
104
105 #ifdef HAVE_RES_SEARCH
106 #define MX_RETRIES      3
107
108 static int is_host_alias(const char *name, struct query *ctl)
109 /* determine whether name is a DNS alias of the hostname */
110 {
111     struct hostent      *he;
112     struct mxentry      *mxp, *mxrecords;
113
114     /*
115      * The first two checks are optimizations that will catch a good
116      * many cases.  (1) check against the hostname the user
117      * specified.  Odds are good this will either be the mailserver's
118      * FQDN or a suffix of it with the mailserver's domain's default
119      * host name omitted.  Then check the rest of the `also known as'
120      * cache accumulated by previous DNS checks.  This cache is primed
121      * by the aka list option.
122      *
123      * (2) check against the mailserver's FQDN, in case
124      * it's not the same as the declared hostname.
125      *
126      * Either of these on a mail address is definitive.  Only if the
127      * name doesn't match either is it time to call the bind library.
128      * If this happens odds are good we're looking at an MX name.
129      */
130     if (str_in_list(&ctl->lead_server->servernames, name))
131         return(TRUE);
132     else if (strcmp(name, ctl->canonical_name) == 0)
133         return(TRUE);
134
135     /*
136      * We know DNS service was up at the beginning of this poll cycle.
137      * If it's down, our nameserver has crashed.  We don't want to try
138      * delivering the current message or anything else from this
139      * mailbox until it's back up.
140      */
141     else if ((he = gethostbyname(name)) != (struct hostent *)NULL)
142     {
143         if (strcmp(ctl->canonical_name, he->h_name) == 0)
144             goto match;
145         else
146             return(FALSE);
147     }
148     else
149         switch (h_errno)
150         {
151         case HOST_NOT_FOUND:    /* specified host is unknown */
152         case NO_ADDRESS:        /* valid, but does not have an IP address */
153             break;
154
155         case NO_RECOVERY:       /* non-recoverable name server error */
156         case TRY_AGAIN:         /* temporary error on authoritative server */
157         default:
158             if (outlevel != O_SILENT)
159                 putchar('\n');  /* terminate the progress message */
160             fprintf(stderr,
161                 "fetchmail: nameserver failure while looking for `%s' during poll of %s.\n",
162                 name, ctl->servernames->id);
163             ctl->errcount++;
164             longjmp(restart, 2);        /* try again next poll cycle */
165             break;
166         }
167
168     /*
169      * We're only here if DNS was OK but the gethostbyname() failed
170      * with a HOST_NOT_FOUND or NO_ADDRESS error.
171      * Search for a name match on MX records pointing to the server.
172      */
173     h_errno = 0;
174     if ((mxrecords = getmxrecords(name)) == (struct mxentry *)NULL)
175     {
176         switch (h_errno)
177         {
178         case HOST_NOT_FOUND:    /* specified host is unknown */
179             return(FALSE);
180
181         case NO_ADDRESS:        /* valid, but does not have an IP address */
182             for (mxp = mxrecords; mxp->name; mxp++)
183                 if (strcmp(name, mxp->name) == 0)
184                     goto match;
185             return(FALSE);
186             break;
187
188         case NO_RECOVERY:       /* non-recoverable name server error */
189         case TRY_AGAIN:         /* temporary error on authoritative server */
190         default:
191             fprintf(stderr,
192                 "fetchmail: nameserver failure while looking for `%s' during poll of %s.\n",
193                 name, ctl->servernames->id);
194             ctl->errcount++;
195             longjmp(restart, 2);        /* try again next poll cycle */
196             break;
197         }
198     }
199
200 match:
201     /* add this name to relevant server's `also known as' list */
202     save_str(&ctl->lead_server->servernames, -1, name);
203     return(TRUE);
204 }
205
206 static void map_name(name, ctl, xmit_names)
207 /* add given name to xmit_names if it matches declared localnames */
208 const char *name;               /* name to map */
209 struct query *ctl;              /* list of permissible aliases */
210 struct idlist **xmit_names;     /* list of recipient names parsed out */
211 {
212     const char  *lname;
213
214     lname = idpair_find(&ctl->localnames, name);
215     if (!lname && ctl->wildcard)
216         lname = name;
217
218     if (lname != (char *)NULL)
219     {
220         if (outlevel == O_VERBOSE)
221             fprintf(stderr,
222                     "fetchmail: mapped %s to local %s\n",
223                     name, lname);
224         save_str(xmit_names, -1, lname);
225     }
226 }
227
228 void find_server_names(hdr, ctl, xmit_names)
229 /* parse names out of a RFC822 header into an ID list */
230 const char *hdr;                /* RFC822 header in question */
231 struct query *ctl;              /* list of permissible aliases */
232 struct idlist **xmit_names;     /* list of recipient names parsed out */
233 {
234     if (hdr == (char *)NULL)
235         return;
236     else
237     {
238         char    *cp, *lname;
239
240         if ((cp = nxtaddr(hdr)) != (char *)NULL)
241             do {
242                 char    *atsign;
243
244                 if ((atsign = strchr(cp, '@')))
245                 {
246                     /*
247                      * Address has an @. Check to see if the right-hand part
248                      * is an alias or MX equivalent of the mailserver.  If it's
249                      * not, skip this name.  If it is, we'll keep going and try
250                      * to find a mapping to a client name.
251                      */
252                     if (!is_host_alias(atsign+1, ctl))
253                         continue;
254                     atsign[0] = '\0';
255                 }
256
257                 map_name(cp, ctl, xmit_names);
258             } while
259                 ((cp = nxtaddr((char *)NULL)) != (char *)NULL);
260     }
261 }
262 #endif /* HAVE_RES_SEARCH */
263
264 static FILE *smtp_open(struct query *ctl)
265 /* try to open a socket to the appropriate SMTP server for this query */ 
266 {
267     ctl = ctl->lead_smtp; /* go to the SMTP leader for this query */
268
269     /* maybe it's time to close the socket in order to force delivery */
270     if (batchlimit && ctl->smtp_sockfp && batchcount++ == batchlimit)
271     {
272         fclose(ctl->smtp_sockfp);
273         ctl->smtp_sockfp = (FILE *)NULL;
274         batchcount = 0;
275     }
276
277     /* if no socket to this host is already set up, try to open one */
278     if (ctl->smtp_sockfp == (FILE *)NULL)
279     {
280         if ((ctl->smtp_sockfp = Socket(ctl->smtphost, SMTP_PORT)) == (FILE *)NULL)
281             return((FILE *)NULL);
282         else if (SMTP_ok(ctl->smtp_sockfp) != SM_OK
283                  || SMTP_helo(ctl->smtp_sockfp, ctl->servernames->id) != SM_OK)
284         {
285             fclose(ctl->smtp_sockfp);
286             ctl->smtp_sockfp = (FILE *)NULL;
287         }
288     }
289
290     return(ctl->smtp_sockfp);
291 }
292
293 static int gen_readmsg (sockfp, len, delimited, ctl)
294 /* read message content and ship to SMTP or MDA */
295 FILE *sockfp;           /* to which the server is connected */
296 long len;               /* length of message */
297 int delimited;          /* does the protocol use a message delimiter? */
298 struct query *ctl;      /* query control record */
299 {
300     char buf [MSGBUFSIZE+1]; 
301     char *bufp, *headers, *fromhdr,*tohdr,*cchdr,*bcchdr,*received_for,*envto;
302     int n, oldlen, mboxfd;
303     int inheaders,lines,sizeticker;
304     FILE *sinkfp;
305     RETSIGTYPE (*sigchld)();
306 #ifdef HAVE_GETHOSTBYNAME
307     char rbuf[HOSTLEN + USERNAMELEN + 4]; 
308 #endif /* HAVE_GETHOSTBYNAME */
309
310     /* read the message content from the server */
311     inheaders = 1;
312     headers = fromhdr = tohdr = cchdr = bcchdr = received_for = envto = NULL;
313     lines = 0;
314     sizeticker = 0;
315     oldlen = 0;
316     while (delimited || len > 0)
317     {
318         if ((n = SockGets(buf,sizeof(buf),sockfp)) < 0)
319             return(PS_SOCKET);
320         vtalarm(ctl->timeout);
321
322         /* write the message size dots */
323         if (n > 0)
324         {
325             sizeticker += n;
326             while (sizeticker >= SIZETICKER)
327             {
328                 if (outlevel > O_SILENT)
329                     fputc('.',stderr);
330                 sizeticker -= SIZETICKER;
331             }
332         }
333         len -= n;
334         bufp = buf;
335         if (buf[0] == '\0' || buf[0] == '\r' || buf[0] == '\n')
336             inheaders = 0;
337         if (delimited && *bufp == '.') {
338             bufp++;
339             if (*bufp == 0)
340                 break;  /* end of message */
341         }
342         strcat(bufp, "\n");
343      
344         if (inheaders)
345         {
346             if (!ctl->norewrite)
347                 reply_hack(bufp, ctl->servernames->id);
348
349             if (!lines)
350             {
351                 oldlen = strlen(bufp);
352                 headers = xmalloc(oldlen + 1);
353                 (void) strcpy(headers, bufp);
354                 bufp = headers;
355             }
356             else
357             {
358                 int     newlen;
359
360                 /*
361                  * We deal with RFC822 continuation lines here.
362                  * Replace previous '\n' with '\r' so nxtaddr 
363                  * and reply_hack will be able to see past it.
364                  * (We know this is safe because SocketGets stripped
365                  * out all carriage returns in the read loop above
366                  * and we haven't reintroduced any since then.)
367                  * We'll undo this before writing the header.
368                  */
369                 if (isspace(bufp[0]))
370                     headers[oldlen-1] = '\r';
371
372                 newlen = oldlen + strlen(bufp);
373                 headers = realloc(headers, newlen + 1);
374                 if (headers == NULL)
375                     return(PS_IOERR);
376                 strcpy(headers + oldlen, bufp);
377                 bufp = headers + oldlen;
378                 oldlen = newlen;
379             }
380
381             if (!strncasecmp("From:", bufp, 5))
382                 fromhdr = bufp;
383             else if (!fromhdr && !strncasecmp("Resent-From:", bufp, 12))
384                 fromhdr = bufp;
385             else if (!fromhdr && !strncasecmp("Apparently-From:", bufp, 16))
386                 fromhdr = bufp;
387             else if (!strncasecmp("To:", bufp, 3))
388                 tohdr = bufp;
389             else if (!strncasecmp("Apparently-To:", bufp, 14))
390                 envto = bufp;
391             else if (!strncasecmp(ctl->envelope, bufp, 14))
392                 envto = bufp;
393             else if (!strncasecmp("Cc:", bufp, 3))
394                 cchdr = bufp;
395             else if (!strncasecmp("Bcc:", bufp, 4))
396                 bcchdr = bufp;
397 #ifdef HAVE_GETHOSTBYNAME
398             else if (MULTIDROP(ctl) && !strncasecmp("Received:", bufp, 9))
399             {
400                 char *ok;
401
402                 /*
403                  * Try to extract the real envelope addressee.  We look here
404                  * specifically for the mailserver's Received line.
405                  * Note: this will only work for sendmail, or an MTA that
406                  * shares sendmail's convention of embedding the envelope
407                  * address in the Received line.
408                  */
409                 strcpy(rbuf, "by ");
410                 strcat(rbuf, ctl->canonical_name);
411                 if ((ok = strstr(bufp, rbuf)))
412                     ok = strstr(ok, "for <");
413                 else
414                     ok = (char *)NULL;
415                 if (ok != 0)
416                 {
417                     char        *sp, *tp;
418
419                     tp = rbuf;
420                     sp = ok + 4;
421                     if (*sp == '<')
422                         sp++;
423                     while (*sp && *sp != '>' && *sp != '@' && *sp != ';')
424                         if (!isspace(*sp))
425                             *tp++ = *sp++;
426                         else
427                         {
428                             /* uh oh -- whitespace here can't be right! */
429                             ok = (char *)NULL;
430                             break;
431                         }
432                     *tp = '\0';
433                 }
434
435                 if (ok != 0)
436                 {
437                     received_for = alloca(strlen(rbuf)+1);
438                     strcpy(received_for, rbuf);
439                     if (outlevel == O_VERBOSE)
440                         fprintf(stderr, 
441                                 "fetchmail: found Received address `%s'\n",
442                                 received_for);
443                 }
444             }
445 #endif /* HAVE_GETHOSTBYNAME */
446
447             goto skipwrite;
448         }
449         else if (headers)       /* OK, we're at end of headers now */
450         {
451             char                *cp;
452             struct idlist       *idp, *xmit_names;
453             int                 good_addresses, bad_addresses;
454 #ifdef HAVE_RES_SEARCH
455             int                 no_local_matches = FALSE;
456 #endif /* HAVE_RES_SEARCH */
457
458             /* cons up a list of local recipients */
459             xmit_names = (struct idlist *)NULL;
460             bad_addresses = good_addresses = 0;
461 #ifdef HAVE_RES_SEARCH
462             /* is this a multidrop box? */
463             if (MULTIDROP(ctl))
464             {
465                 if (envto)          /* We have the actual envelope addressee */
466                     find_server_names(envto, ctl, &xmit_names);
467                 else if (received_for)
468                     /*
469                      * We have the Received for addressee.  
470                      * It has to be a mailserver address, or we
471                      * wouldn't have got here.
472                      */
473                     map_name(received_for, ctl, &xmit_names);
474                 else
475                 {
476                     /*
477                      * We haven't extracted the envelope address.
478                      * So check all the header addresses.
479                      */
480                     find_server_names(tohdr,  ctl, &xmit_names);
481                     find_server_names(cchdr,  ctl, &xmit_names);
482                     find_server_names(bcchdr, ctl, &xmit_names);
483                 }
484                 if (!xmit_names)
485                 {
486                     no_local_matches = TRUE;
487                     save_str(&xmit_names, -1, user);
488                     if (outlevel == O_VERBOSE)
489                         fprintf(stderr, 
490                                 "fetchmail: no local matches, forwarding to %s\n",
491                                 user);
492                 }
493             }
494             else        /* it's a single-drop box, use first localname */
495 #endif /* HAVE_RES_SEARCH */
496                 save_str(&xmit_names, -1, ctl->localnames->id);
497
498             /* time to address the message */
499             if (ctl->mda[0])    /* we have a declared MDA */
500             {
501                 int     i, nlocals = 0;
502                 char    **sargv, **sp;
503
504                 /*
505                  * We go through this in order to be able to handle very
506                  * long lists of users and (re)implement %s.
507                  */
508                 for (idp = xmit_names; idp; idp = idp->next)
509                     nlocals++;
510                 sp = sargv = (char **)alloca(sizeof(char **) * ctl->mda_argcount+nlocals+2);
511                 for (i = 0; i < ctl->mda_argcount; i++)
512                     if (strcmp("%s", ctl->mda_argv[i]))
513                         *sp++ = ctl->mda_argv[i];
514                     else
515                         for (idp = xmit_names; idp; idp = idp->next)
516                             *sp++ = idp->id;
517                 *sp =  (char *)NULL;
518
519 #ifdef HAVE_SETEUID
520                 /*
521                  * Arrange to run with user's permissions if we're root.
522                  * This will initialize the ownership of any files the
523                  * MDA creates properly.  (The seteuid call is available
524                  * under all BSDs and Linux)
525                  */
526                 seteuid(ctl->uid);
527 #endif /* HAVE_SETEUID */
528
529                 mboxfd = openmailpipe(sargv);
530
531 #ifdef HAVE_SETEUID
532                 /* this will fail quietly if we didn't start as root */
533                 seteuid(0);
534 #endif /* HAVE_SETEUID */
535
536                 if (mboxfd < 0)
537                 {
538                     fprintf(stderr, "fetchmail: MDA open failed\n");
539                     return(PS_IOERR);
540                 }
541
542                 sigchld = signal(SIGCLD, SIG_DFL);
543             }
544             else
545             {
546                 char    *ap;
547
548                 /* build a connection to the SMTP listener */
549                 if (ctl->mda[0] == '\0' && ((sinkfp = smtp_open(ctl)) == NULL))
550                 {
551                     free_str_list(&xmit_names);
552                     fprintf(stderr, "fetchmail: SMTP connect failed\n");
553                     return(PS_SMTP);
554                 }
555
556                 /*
557                  * Try to get the SMTP listener to take the header
558                  * From address as MAIL FROM (this makes the logging
559                  * nicer).  If it won't, fall back on the calling-user
560                  * ID.  This won't affect replies, which use the header
561                  * From address anyway.
562                  */
563                 if (!fromhdr || !(ap = nxtaddr(fromhdr)))
564                 {
565                     if (SMTP_from(sinkfp, user) != SM_OK)
566                         return(PS_SMTP);        /* should never happen */
567                 }
568                 else if (SMTP_from(sinkfp, ap) != SM_OK)
569                     if (smtp_response == 571)
570                     {
571                         /*
572                          * SMTP listener explicitly refuses to deliver
573                          * mail coming from this address, probably due
574                          * to an anti-spam domain exclusion.  Respect
575                          * this.
576                          */
577                         sinkfp = (FILE *)NULL;
578                         goto skiptext;
579                     }
580                     else if (SMTP_from(sinkfp, user) != SM_OK)
581                         return(PS_SMTP);        /* should never happen */
582
583                 /* now list the recipient addressees */
584                 for (idp = xmit_names; idp; idp = idp->next)
585                     if (SMTP_rcpt(sinkfp, idp->id) == SM_OK)
586                         good_addresses++;
587                     else
588                     {
589                         bad_addresses++;
590                         idp->val.num = 0;
591                         fprintf(stderr, 
592                                 "fetchmail: SMTP listener doesn't like recipient address `%s'\n", idp->id);
593                     }
594                 if (!good_addresses && SMTP_rcpt(sinkfp, user) != SM_OK)
595                 {
596                     fprintf(stderr, 
597                             "fetchmail: can't even send to calling user!\n");
598                     return(PS_SMTP);
599                 }
600
601                 /* tell it we're ready to send data */
602                 SMTP_data(sinkfp);
603                 if (outlevel == O_VERBOSE)
604                     fputs("SMTP> ", stderr);
605
606             skiptext:;
607             }
608
609             /* change continuation markers back to regular newlines */
610             for (cp = headers; cp < headers + oldlen; cp++)
611                 if (*cp == '\r')
612                     *cp = '\n';
613
614             /* replace all LFs with CR-LF before sending to the SMTP server */
615             if (!ctl->mda[0])
616             {
617                 char *newheaders = xmalloc(1 + oldlen * 2);
618
619                 oldlen = strcrlf(newheaders, headers, oldlen);
620                 free(headers);
621                 headers = newheaders;
622             }
623
624             /* write all the headers */
625             if (ctl->mda[0])
626                 n = write(mboxfd,headers,oldlen);
627             else if (sinkfp)
628                 n = SockWrite(headers, oldlen, sinkfp);
629
630             if (n < 0)
631             {
632                 free(headers);
633                 headers = NULL;
634                 perror("fetchmail: writing RFC822 headers");
635                 if (ctl->mda[0])
636                 {
637                     closemailpipe(mboxfd);
638                     signal(SIGCLD, sigchld);
639                 }
640                 return(PS_IOERR);
641             }
642             else if (outlevel == O_VERBOSE)
643                 fputs("#", stderr);
644             free(headers);
645             headers = NULL;
646
647             /* write error notifications */
648 #ifdef HAVE_RES_SEARCH
649             if (no_local_matches || bad_addresses)
650 #else
651             if (bad_addresses)
652 #endif /* HAVE_RES_SEARCH */
653             {
654                 int     errlen = 0;
655                 char    errhd[USERNAMELEN + POPBUFSIZE], *errmsg;
656
657                 errmsg = errhd;
658                 (void) strcpy(errhd, "X-Fetchmail-Warning: ");
659 #ifdef HAVE_RES_SEARCH
660                 if (no_local_matches)
661                 {
662                     strcat(errhd, "no recipient addresses matched declared local names");
663                     if (bad_addresses)
664                         strcat(errhd, "; ");
665                 }
666 #endif /* HAVE_RES_SEARCH */
667
668                 if (bad_addresses)
669                 {
670                     strcat(errhd, "SMTP listener rejected local recipient addresses: ");
671                     errlen = strlen(errhd);
672                     for (idp = xmit_names; idp; idp = idp->next)
673                         if (!idp->val.num)
674                             errlen += strlen(idp->id) + 2;
675
676                     errmsg = alloca(errlen+3);
677                     (void) strcpy(errmsg, errhd);
678                     for (idp = xmit_names; idp; idp = idp->next)
679                         if (!idp->val.num)
680                         {
681                             strcat(errmsg, idp->id);
682                             if (idp->next)
683                                 strcat(errmsg, ", ");
684                         }
685                 }
686
687                 strcat(errmsg, "\n");
688
689                 if (ctl->mda[0])
690                     write(mboxfd, errmsg, strlen(errmsg));
691                 else if (sinkfp)
692                     SockWrite(errmsg, strlen(errmsg), sinkfp);
693             }
694
695             free_str_list(&xmit_names);
696         }
697
698         /* SMTP byte-stuffing */
699         if (*bufp == '.' && ctl->mda[0] == 0)
700             if (sinkfp)
701                 SockWrite(".", 1, sinkfp);
702
703         /* replace all LFs with CR-LF  in the line */
704         if (!ctl->mda[0])
705         {
706             char *newbufp = xmalloc(1 + strlen(bufp) * 2);
707
708             strcrlf(newbufp, bufp, strlen(bufp));
709             bufp = newbufp;
710         }
711
712         /* ship out the text line */
713         if (ctl->mda[0])
714             n = write(mboxfd,bufp,strlen(bufp));
715         else if (sinkfp)
716             n = SockWrite(bufp, strlen(bufp), sinkfp);
717
718         if (!ctl->mda[0])
719             free(bufp);
720         if (n < 0)
721         {
722             perror("fetchmail: writing message text");
723             if (ctl->mda[0])
724             {
725                 closemailpipe(mboxfd);
726                 signal(SIGCLD, sigchld);
727             }
728             return(PS_IOERR);
729         }
730         else if (outlevel == O_VERBOSE)
731             fputc('*', stderr);
732
733     skipwrite:;
734         lines++;
735     }
736
737     if (ctl->mda[0])
738     {
739         int rc;
740
741         /* close the delivery pipe, we'll reopen before next message */
742         rc = closemailpipe(mboxfd);
743         signal(SIGCLD, sigchld);
744         if (rc)
745             return(PS_IOERR);
746     }
747     else if (sinkfp)
748     {
749         /* write message terminator */
750         if (SMTP_eom(sinkfp) != SM_OK)
751         {
752             fputs("fetchmail: SMTP listener refused delivery\n", stderr);
753             return(PS_SMTP);
754         }
755     }
756
757     return(0);
758 }
759
760 #ifdef KERBEROS_V4
761 int
762 kerberos_auth (socket, canonical) 
763 /* authenticate to the server host using Kerberos V4 */
764 int socket;             /* socket to server host */
765 const char *canonical;  /* server name */
766 {
767     char * host_primary;
768     KTEXT ticket;
769     MSG_DAT msg_data;
770     CREDENTIALS cred;
771     Key_schedule schedule;
772     int rem;
773   
774     ticket = ((KTEXT) (malloc (sizeof (KTEXT_ST))));
775     rem = (krb_sendauth (0L, socket, ticket, "pop",
776                          canonical,
777                          ((char *) (krb_realmofhost (canonical))),
778                          ((unsigned long) 0),
779                          (&msg_data),
780                          (&cred),
781                          (schedule),
782                          ((struct sockaddr_in *) 0),
783                          ((struct sockaddr_in *) 0),
784                          "KPOPV0.1"));
785     free (ticket);
786     if (rem != KSUCCESS)
787     {
788         fprintf (stderr, "fetchmail: kerberos error %s\n", (krb_get_err_text (rem)));
789         return (PS_ERROR);
790     }
791     return (0);
792 }
793 #endif /* KERBEROS_V4 */
794
795 int do_protocol(ctl, proto)
796 /* retrieve messages from server using given protocol method table */
797 struct query *ctl;              /* parsed options with merged-in defaults */
798 const struct method *proto;     /* protocol method table */
799 {
800     int ok, js;
801     void (*sigsave)();
802
803 #ifndef KERBEROS_V4
804     if (ctl->authenticate == A_KERBEROS)
805     {
806         fputs("fetchmail: Kerberos support not linked.\n", stderr);
807         return(PS_ERROR);
808     }
809 #endif /* KERBEROS_V4 */
810
811     /* lacking methods, there are some options that may fail */
812     if (!proto->is_old)
813     {
814         /* check for unsupported options */
815         if (ctl->flush) {
816             fprintf(stderr,
817                     "Option --flush is not supported with %s\n",
818                     proto->name);
819             return(PS_SYNTAX);
820         }
821         else if (ctl->fetchall) {
822             fprintf(stderr,
823                     "Option --all is not supported with %s\n",
824                     proto->name);
825             return(PS_SYNTAX);
826         }
827     }
828     if (!proto->getsizes && ctl->limit)
829     {
830         fprintf(stderr,
831                 "Option --limit is not supported with %s\n",
832                 proto->name);
833         return(PS_SYNTAX);
834     }
835
836     protocol = proto;
837     tagnum = 0;
838     tag[0] = '\0';      /* nuke any tag hanging out from previous query */
839     ok = 0;
840
841     /* set up the server-nonresponse timeout */
842     sigsave = signal(SIGVTALRM, vtalarm_handler);
843     vtalarm(mytimeout = ctl->timeout);
844
845     if ((js = setjmp(restart)) == 1)
846     {
847         fprintf(stderr,
848                 "fetchmail: timeout after %d seconds waiting for %s.\n",
849                 ctl->timeout, ctl->servernames->id);
850         ok = PS_ERROR;
851     }
852     else if (js == 2)
853     {
854         /* error message printed at point of longjmp */
855         ok = PS_ERROR;
856     }
857     else
858     {
859         char buf [POPBUFSIZE+1];
860         int *msgsizes, len, num, count, new, deletions = 0;
861         FILE *sockfp;
862
863         /* open a socket to the mail server */
864         if ((sockfp = Socket(ctl->servernames->id,
865                              ctl->port ? ctl->port : protocol->port)) == NULL)
866         {
867             perror("fetchmail, connecting to host");
868             ok = PS_SOCKET;
869             goto closeUp;
870         }
871
872 #ifdef KERBEROS_V4
873         if (ctl->authenticate == A_KERBEROS)
874         {
875             ok = kerberos_auth(fileno(sockfp), ctl->canonical_name);
876             if (ok != 0)
877                 goto cleanUp;
878             vtalarm(ctl->timeout);
879         }
880 #endif /* KERBEROS_V4 */
881
882         /* accept greeting message from mail server */
883         ok = (protocol->parse_response)(sockfp, buf);
884         if (ok != 0)
885             goto cleanUp;
886         vtalarm(ctl->timeout);
887
888         /* try to get authorized to fetch mail */
889         shroud = ctl->password;
890         ok = (protocol->getauth)(sockfp, ctl, buf);
891         shroud = (char *)NULL;
892         if (ok == PS_ERROR)
893             ok = PS_AUTHFAIL;
894         if (ok != 0)
895             goto cleanUp;
896         vtalarm(ctl->timeout);
897
898         /* compute number of messages and number of new messages waiting */
899         ok = (protocol->getrange)(sockfp, ctl, &count, &new);
900         if (ok != 0)
901             goto cleanUp;
902         vtalarm(ctl->timeout);
903
904         /* show user how many messages we downloaded */
905         if (outlevel > O_SILENT)
906             if (count == 0)
907                 fprintf(stderr, "No mail from %s@%s\n", 
908                         ctl->remotename,
909                         ctl->servernames->id);
910             else
911             {
912                 fprintf(stderr, "%d message%s", count, count > 1 ? "s" : ""); 
913                 if (new != -1 && (count - new) > 0)
914                     fprintf(stderr, " (%d seen)", count-new);
915                 fprintf(stderr,
916                         " from %s@%s.\n",
917                         ctl->remotename,
918                         ctl->servernames->id);
919             }
920
921         /* we may need to get sizes in order to check message limits */
922         msgsizes = (int *)NULL;
923         if (!ctl->fetchall && proto->getsizes && ctl->limit)
924         {
925             msgsizes = (int *)alloca(sizeof(int) * count);
926
927             ok = (proto->getsizes)(sockfp, count, msgsizes);
928             if (ok != 0)
929                 goto cleanUp;
930             vtalarm(ctl->timeout);
931         }
932
933
934         if (check_only)
935         {
936             if (new == -1 || ctl->fetchall)
937                 new = count;
938             ok = ((new > 0) ? PS_SUCCESS : PS_NOMAIL);
939             goto cleanUp;
940         }
941         else if (count > 0)
942         {    
943             /*
944              * What forces this code is that in POP3 and IMAP2BIS you can't
945              * fetch a message without having it marked `seen'.  In IMAP4,
946              * on the other hand, you can (peek_capable is set to convey
947              * this).
948              *
949              * The result of being unable to peek is that if there's
950              * any kind of transient error (DNS lookup failure, or
951              * sendmail refusing delivery due to process-table limits)
952              * the message will be marked "seen" on the server without
953              * having been delivered.  This is not a big problem if
954              * fetchmail is running in foreground, because the user
955              * will see a "skipped" message when it next runs and get
956              * clued in.
957              *
958              * But in daemon mode this leads to the message being silently
959              * ignored forever.  This is not acceptable.
960              *
961              * We compensate for this by checking the error count from the 
962              * previous pass and forcing all messages to be considered new
963              * if it's nonzero.
964              */
965             int force_retrieval = !peek_capable && (ctl->errcount > 0);
966
967             ctl->errcount = 0;
968
969             /* read, forward, and delete messages */
970             for (num = 1; num <= count; num++)
971             {
972                 int     toolarge = msgsizes && (msgsizes[num-1] > ctl->limit);
973                 int     fetch_it = ctl->fetchall ||
974                     (!toolarge && (force_retrieval || !(protocol->is_old && (protocol->is_old)(sockfp,ctl,num))));
975
976                 /* we may want to reject this message if it's old */
977                 if (!fetch_it)
978                 {
979                     if (outlevel > O_SILENT)
980                     {
981                         fprintf(stderr, "skipping message %d", num);
982                         if (toolarge)
983                             fprintf(stderr, " (oversized, %d bytes)", msgsizes[num-1]);
984                     }
985                 }
986                 else
987                 {
988                     /* request a message */
989                     ok = (protocol->fetch)(sockfp, num, &len);
990                     if (ok != 0)
991                         goto cleanUp;
992                     vtalarm(ctl->timeout);
993
994                     if (outlevel > O_SILENT)
995                     {
996                         fprintf(stderr, "reading message %d", num);
997                         if (len > 0)
998                             fprintf(stderr, " (%d bytes)", len);
999                         if (outlevel == O_VERBOSE)
1000                             fputc('\n', stderr);
1001                         else
1002                             fputc(' ', stderr);
1003                     }
1004
1005                     /* read the message and ship it to the output sink */
1006                     ok = gen_readmsg(sockfp,
1007                                      len, 
1008                                      protocol->delimited,
1009                                      ctl);
1010                     if (ok != 0)
1011                         goto cleanUp;
1012                     vtalarm(ctl->timeout);
1013
1014                     /* tell the server we got it OK and resynchronize */
1015                     if (protocol->trail)
1016                     {
1017                         ok = (protocol->trail)(sockfp, ctl, num);
1018                         if (ok != 0)
1019                             goto cleanUp;
1020                         vtalarm(ctl->timeout);
1021                     }
1022                 }
1023
1024                 /*
1025                  * At this point in flow of control, either we've bombed
1026                  * on a protocol error or had delivery refused by the SMTP
1027                  * server (unlikely -- I've never seen it) or we've seen
1028                  * `accepted for delivery' and the message is shipped.
1029                  * It's safe to mark the message seen and delete it on the
1030                  * server now.
1031                  */
1032
1033                 /* maybe we delete this message now? */
1034                 if (protocol->delete
1035                     && (fetch_it ? !ctl->keep : ctl->flush))
1036                 {
1037                     deletions++;
1038                     if (outlevel > O_SILENT) 
1039                         fprintf(stderr, " flushed\n");
1040                     ok = (protocol->delete)(sockfp, ctl, num);
1041                     if (ok != 0)
1042                         goto cleanUp;
1043                     vtalarm(ctl->timeout);
1044                     delete_str(&ctl->newsaved, num);
1045                 }
1046                 else if (outlevel > O_SILENT) 
1047                     fprintf(stderr, " not flushed\n");
1048             }
1049
1050             /* remove all messages flagged for deletion */
1051             if (protocol->expunge_cmd && deletions > 0)
1052             {
1053                 ok = gen_transact(sockfp, protocol->expunge_cmd);
1054                 if (ok != 0)
1055                     goto cleanUp;
1056                 vtalarm(ctl->timeout);
1057             }
1058
1059             ok = gen_transact(sockfp, protocol->exit_cmd);
1060             if (ok == 0)
1061                 ok = PS_SUCCESS;
1062             vtalarm(0);
1063             fclose(sockfp);
1064             goto closeUp;
1065         }
1066         else {
1067             ok = gen_transact(sockfp, protocol->exit_cmd);
1068             if (ok == 0)
1069                 ok = PS_NOMAIL;
1070             vtalarm(0);
1071             fclose(sockfp);
1072             goto closeUp;
1073         }
1074
1075     cleanUp:
1076         vtalarm(ctl->timeout);
1077         if (ok != 0 && ok != PS_SOCKET)
1078             gen_transact(sockfp, protocol->exit_cmd);
1079         vtalarm(0);
1080         fclose(sockfp);
1081     }
1082
1083     switch (ok)
1084     {
1085     case PS_SOCKET:
1086         fputs("fetchmail: socket", stderr);
1087         break;
1088     case PS_AUTHFAIL:
1089         fputs("fetchmail: authorization", stderr);
1090         break;
1091     case PS_SYNTAX:
1092         fputs("fetchmail: missing or bad RFC822 header", stderr);
1093         break;
1094     case PS_IOERR:
1095         fputs("fetchmail: MDA", stderr);
1096         break;
1097     case PS_ERROR:
1098         fputs("fetchmail: client/server synchronization", stderr);
1099         break;
1100     case PS_PROTOCOL:
1101         fputs("fetchmail: client/server protocol", stderr);
1102         break;
1103     case PS_SMTP:
1104         fputs("fetchmail: SMTP transaction", stderr);
1105         break;
1106     case PS_UNDEFINED:
1107         fputs("fetchmail: undefined", stderr);
1108         break;
1109     }
1110     if (ok==PS_SOCKET || ok==PS_AUTHFAIL || ok==PS_SYNTAX || ok==PS_IOERR
1111                 || ok==PS_ERROR || ok==PS_PROTOCOL || ok==PS_SMTP)
1112         fprintf(stderr, " error while talking to %s\n", ctl->servernames->id);
1113
1114 closeUp:
1115     signal(SIGVTALRM, sigsave);
1116     return(ok);
1117 }
1118
1119 #if defined(HAVE_STDARG_H)
1120 void gen_send(FILE *sockfp, char *fmt, ... )
1121 /* assemble command in printf(3) style and send to the server */
1122 {
1123 #else
1124 void gen_send(sockfp, fmt, va_alist)
1125 /* assemble command in printf(3) style and send to the server */
1126 FILE *sockfp;           /* socket to which server is connected */
1127 const char *fmt;        /* printf-style format */
1128 va_dcl {
1129 #endif
1130
1131     char buf [POPBUFSIZE+1];
1132     va_list ap;
1133
1134     if (protocol->tagged)
1135         (void) sprintf(buf, "%s ", GENSYM);
1136     else
1137         buf[0] = '\0';
1138
1139 #if defined(HAVE_STDARG_H)
1140     va_start(ap, fmt) ;
1141 #else
1142     va_start(ap);
1143 #endif
1144     vsprintf(buf + strlen(buf), fmt, ap);
1145     va_end(ap);
1146
1147     strcat(buf, "\r\n");
1148     SockWrite(buf, strlen(buf), sockfp);
1149
1150     if (outlevel == O_VERBOSE)
1151     {
1152         char *cp;
1153
1154         if (shroud && (cp = strstr(buf, shroud)))
1155             memset(cp, '*', strlen(shroud));
1156         fprintf(stderr,"> %s", buf);
1157     }
1158 }
1159
1160 #if defined(HAVE_STDARG_H)
1161 int gen_transact(FILE *sockfp, char *fmt, ... )
1162 /* assemble command in printf(3) style, send to server, accept a response */
1163 {
1164 #else
1165 int gen_transact(sockfp, fmt, va_alist)
1166 /* assemble command in printf(3) style, send to server, accept a response */
1167 FILE *sockfp;           /* socket to which server is connected */
1168 const char *fmt;        /* printf-style format */
1169 va_dcl {
1170 #endif
1171
1172   int ok;
1173   char buf [POPBUFSIZE+1];
1174   va_list ap;
1175
1176   if (protocol->tagged)
1177       (void) sprintf(buf, "%s ", GENSYM);
1178   else
1179       buf[0] = '\0';
1180
1181 #if defined(HAVE_STDARG_H)
1182   va_start(ap, fmt) ;
1183 #else
1184   va_start(ap);
1185 #endif
1186   vsprintf(buf + strlen(buf), fmt, ap);
1187   va_end(ap);
1188
1189   strcat(buf, "\r\n");
1190   SockWrite(buf, strlen(buf), sockfp);
1191   if (outlevel == O_VERBOSE)
1192   {
1193       char *cp;
1194
1195       if (shroud && (cp = strstr(buf, shroud)))
1196           memset(cp, '*', strlen(shroud));
1197       fprintf(stderr,"> %s", buf);
1198   }
1199
1200   /* we presume this does its own response echoing */
1201   ok = (protocol->parse_response)(sockfp, buf);
1202   vtalarm(mytimeout);
1203
1204   return(ok);
1205 }
1206
1207 /* driver.c ends here */