2 * driver.c -- generic driver for mail fetch method protocols
4 * Copyright 1996 by Eric S. Raymond
6 * For license terms, see the file COPYING in this directory.
15 #if defined(STDC_HEADERS)
18 #if defined(HAVE_UNISTD_H)
21 #if defined(HAVE_STDARG_H)
26 #if defined(HAVE_ALLOCA_H)
32 #ifdef HAVE_GETHOSTBYNAME
35 #endif /* HAVE_GETHOSTBYNAME */
40 #include <netinet/in.h>
42 #endif /* KERBEROS_V4 */
44 #include "fetchmail.h"
47 /* BSD portability hack...I know, this is an ugly place to put it */
48 #if !defined(SIGCHLD) && defined(SIGCLD)
49 #define SIGCHLD SIGCLD
52 #define SMTP_PORT 25 /* standard SMTP service port */
54 int batchlimit; /* how often to tear down the delivery connection */
55 int batchcount; /* count of messages sent in current batch */
56 int peek_capable; /* can we peek for better error recovery? */
58 static const struct method *protocol;
59 static jmp_buf restart;
63 #define GENSYM (sprintf(tag, "a%04d", ++tagnum), tag)
65 static char *shroud; /* string to shroud in debug output, if non-NULL */
66 static int mytimeout; /* value of nonreponse timeout */
68 static int strcrlf(dst, src, count)
69 /* replace LFs with CR-LF; return length of string with replacements */
70 char *dst; /* new string with CR-LFs */
71 char *src; /* original string with LFs */
72 int count; /* length of src */
89 static void vtalarm(int timeleft)
90 /* reset the nonresponse-timeout */
92 struct itimerval ntimeout;
94 ntimeout.it_interval.tv_sec = ntimeout.it_interval.tv_usec = 0;
95 ntimeout.it_value.tv_sec = timeleft;
96 ntimeout.it_value.tv_usec = 0;
97 setitimer(ITIMER_VIRTUAL, &ntimeout, (struct itimerval *)NULL);
100 static void vtalarm_handler (int signal)
101 /* handle server-timeout SIGVTALARM signal */
106 #ifdef HAVE_RES_SEARCH
109 static int is_host_alias(const char *name, struct query *ctl)
110 /* determine whether name is a DNS alias of the hostname */
113 struct mxentry *mxp, *mxrecords;
116 * The first two checks are optimizations that will catch a good
117 * many cases. (1) check against the hostname the user
118 * specified. Odds are good this will either be the mailserver's
119 * FQDN or a suffix of it with the mailserver's domain's default
120 * host name omitted. Then check the rest of the `also known as'
121 * cache accumulated by previous DNS checks. This cache is primed
122 * by the aka list option.
124 * (2) check against the mailserver's FQDN, in case
125 * it's not the same as the declared hostname.
127 * Either of these on a mail address is definitive. Only if the
128 * name doesn't match either is it time to call the bind library.
129 * If this happens odds are good we're looking at an MX name.
131 if (str_in_list(&ctl->lead_server->servernames, name))
133 else if (strcmp(name, ctl->canonical_name) == 0)
137 * We know DNS service was up at the beginning of this poll cycle.
138 * If it's down, our nameserver has crashed. We don't want to try
139 * delivering the current message or anything else from this
140 * mailbox until it's back up.
142 else if ((he = gethostbyname(name)) != (struct hostent *)NULL)
144 if (strcmp(ctl->canonical_name, he->h_name) == 0)
152 case HOST_NOT_FOUND: /* specified host is unknown */
153 case NO_ADDRESS: /* valid, but does not have an IP address */
156 case NO_RECOVERY: /* non-recoverable name server error */
157 case TRY_AGAIN: /* temporary error on authoritative server */
159 if (outlevel != O_SILENT)
160 putchar('\n'); /* terminate the progress message */
162 "nameserver failure while looking for `%s' during poll of %s.",
163 name, ctl->servernames->id);
165 longjmp(restart, 2); /* try again next poll cycle */
170 * We're only here if DNS was OK but the gethostbyname() failed
171 * with a HOST_NOT_FOUND or NO_ADDRESS error.
172 * Search for a name match on MX records pointing to the server.
175 if ((mxrecords = getmxrecords(name)) == (struct mxentry *)NULL)
179 case HOST_NOT_FOUND: /* specified host is unknown */
182 case NO_ADDRESS: /* valid, but does not have an IP address */
183 for (mxp = mxrecords; mxp->name; mxp++)
184 if (strcmp(name, mxp->name) == 0)
189 case NO_RECOVERY: /* non-recoverable name server error */
190 case TRY_AGAIN: /* temporary error on authoritative server */
193 "nameserver failure while looking for `%s' during poll of %s.",
194 name, ctl->servernames->id);
196 longjmp(restart, 2); /* try again next poll cycle */
202 /* add this name to relevant server's `also known as' list */
203 save_str(&ctl->lead_server->servernames, -1, name);
207 static void map_name(name, ctl, xmit_names)
208 /* add given name to xmit_names if it matches declared localnames */
209 const char *name; /* name to map */
210 struct query *ctl; /* list of permissible aliases */
211 struct idlist **xmit_names; /* list of recipient names parsed out */
215 lname = idpair_find(&ctl->localnames, name);
216 if (!lname && ctl->wildcard)
219 if (lname != (char *)NULL)
221 if (outlevel == O_VERBOSE)
222 error(0, 0, "mapped %s to local %s", name, lname);
223 save_str(xmit_names, -1, lname);
227 void find_server_names(hdr, ctl, xmit_names)
228 /* parse names out of a RFC822 header into an ID list */
229 const char *hdr; /* RFC822 header in question */
230 struct query *ctl; /* list of permissible aliases */
231 struct idlist **xmit_names; /* list of recipient names parsed out */
233 if (hdr == (char *)NULL)
239 if ((cp = nxtaddr(hdr)) != (char *)NULL)
243 if ((atsign = strchr(cp, '@')))
246 * Address has an @. Check to see if the right-hand part
247 * is an alias or MX equivalent of the mailserver. If it's
248 * not, skip this name. If it is, we'll keep going and try
249 * to find a mapping to a client name.
251 if (!is_host_alias(atsign+1, ctl))
256 map_name(cp, ctl, xmit_names);
258 ((cp = nxtaddr((char *)NULL)) != (char *)NULL);
261 #endif /* HAVE_RES_SEARCH */
263 static FILE *smtp_open(struct query *ctl)
264 /* try to open a socket to the appropriate SMTP server for this query */
266 ctl = ctl->lead_smtp; /* go to the SMTP leader for this query */
268 /* maybe it's time to close the socket in order to force delivery */
269 if (batchlimit && ctl->smtp_sockfp && batchcount++ == batchlimit)
271 fclose(ctl->smtp_sockfp);
272 ctl->smtp_sockfp = (FILE *)NULL;
276 /* if no socket to this host is already set up, try to open one */
277 if (ctl->smtp_sockfp == (FILE *)NULL)
279 if ((ctl->smtp_sockfp = sockopen(ctl->smtphost, SMTP_PORT)) == (FILE *)NULL)
280 return((FILE *)NULL);
281 else if (SMTP_ok(ctl->smtp_sockfp) != SM_OK
282 || SMTP_helo(ctl->smtp_sockfp, ctl->servernames->id) != SM_OK)
284 fclose(ctl->smtp_sockfp);
285 ctl->smtp_sockfp = (FILE *)NULL;
289 return(ctl->smtp_sockfp);
292 static int SockGets(char *buf, int len, FILE *sockfp)
293 /* get a LF-terminated line, removing \r characters */
299 if ((*buf = fgetc(sockfp)) == EOF)
305 if (*buf != '\r') /* remove all CRs */
312 static int gen_readmsg (sockfp, len, delimited, ctl)
313 /* read message content and ship to SMTP or MDA */
314 FILE *sockfp; /* to which the server is connected */
315 long len; /* length of message */
316 int delimited; /* does the protocol use a message delimiter? */
317 struct query *ctl; /* query control record */
319 char buf [MSGBUFSIZE+1];
320 char *bufp, *headers, *fromhdr,*tohdr,*cchdr,*bcchdr,*received_for,*envto;
322 int inheaders,lines,sizeticker;
324 RETSIGTYPE (*sigchld)();
325 #ifdef HAVE_GETHOSTBYNAME
326 char rbuf[HOSTLEN + USERNAMELEN + 4];
327 #endif /* HAVE_GETHOSTBYNAME */
329 /* read the message content from the server */
331 headers = fromhdr = tohdr = cchdr = bcchdr = received_for = envto = NULL;
335 while (delimited || len > 0)
337 if ((n = SockGets(buf,sizeof(buf),sockfp)) < 0)
339 vtalarm(ctl->timeout);
341 /* write the message size dots */
345 while (sizeticker >= SIZETICKER)
347 if (outlevel > O_SILENT)
349 sizeticker -= SIZETICKER;
354 if (buf[0] == '\0' || buf[0] == '\r' || buf[0] == '\n')
356 if (delimited && *bufp == '.') {
359 break; /* end of message */
366 reply_hack(bufp, ctl->servernames->id);
370 oldlen = strlen(bufp);
371 headers = xmalloc(oldlen + 1);
372 (void) strcpy(headers, bufp);
380 * We deal with RFC822 continuation lines here.
381 * Replace previous '\n' with '\r' so nxtaddr
382 * and reply_hack will be able to see past it.
383 * (We know this is safe because SocketGets stripped
384 * out all carriage returns in the read loop above
385 * and we haven't reintroduced any since then.)
386 * We'll undo this before writing the header.
388 if (isspace(bufp[0]))
389 headers[oldlen-1] = '\r';
391 newlen = oldlen + strlen(bufp);
392 headers = realloc(headers, newlen + 1);
395 strcpy(headers + oldlen, bufp);
396 bufp = headers + oldlen;
400 if (!strncasecmp("From:", bufp, 5))
402 else if (!fromhdr && !strncasecmp("Resent-From:", bufp, 12))
404 else if (!fromhdr && !strncasecmp("Apparently-From:", bufp, 16))
406 else if (!strncasecmp("To:", bufp, 3))
408 else if (!strncasecmp("Apparently-To:", bufp, 14))
410 else if (!strncasecmp(ctl->envelope, bufp, 14))
412 else if (!strncasecmp("Cc:", bufp, 3))
414 else if (!strncasecmp("Bcc:", bufp, 4))
416 #ifdef HAVE_GETHOSTBYNAME
417 else if (MULTIDROP(ctl) && !strncasecmp("Received:", bufp, 9))
422 * Try to extract the real envelope addressee. We look here
423 * specifically for the mailserver's Received line.
424 * Note: this will only work for sendmail, or an MTA that
425 * shares sendmail's convention for embedding the envelope
426 * address in the Received line. Sendmail itself only
427 * does this when the mail has a single recipient.
429 if ((ok = strstr(bufp, "by ")) == (char *)NULL)
435 /* extract space-delimited token after "by " */
437 for (sp = ok + 3; !isspace(*sp); sp++)
442 * If it's a DNS name of the mail server, look for the
443 * recipient name after a following "for". Otherwise
446 if (is_host_alias(rbuf, ctl))
447 ok = strstr(sp, "for ");
460 while (*sp && *sp != '>' && *sp != '@' && *sp != ';')
465 /* uh oh -- whitespace here can't be right! */
474 received_for = alloca(strlen(rbuf)+1);
475 strcpy(received_for, rbuf);
476 if (outlevel == O_VERBOSE)
478 "found Received address `%s'",
482 #endif /* HAVE_GETHOSTBYNAME */
486 else if (headers) /* OK, we're at end of headers now */
489 struct idlist *idp, *xmit_names;
490 int good_addresses, bad_addresses;
491 #ifdef HAVE_RES_SEARCH
492 int no_local_matches = FALSE;
493 #endif /* HAVE_RES_SEARCH */
495 /* cons up a list of local recipients */
496 xmit_names = (struct idlist *)NULL;
497 bad_addresses = good_addresses = 0;
498 #ifdef HAVE_RES_SEARCH
499 /* is this a multidrop box? */
502 if (envto) /* We have the actual envelope addressee */
503 find_server_names(envto, ctl, &xmit_names);
504 else if (received_for)
506 * We have the Received for addressee.
507 * It has to be a mailserver address, or we
508 * wouldn't have got here.
510 map_name(received_for, ctl, &xmit_names);
514 * We haven't extracted the envelope address.
515 * So check all the header addresses.
517 find_server_names(tohdr, ctl, &xmit_names);
518 find_server_names(cchdr, ctl, &xmit_names);
519 find_server_names(bcchdr, ctl, &xmit_names);
523 no_local_matches = TRUE;
524 save_str(&xmit_names, -1, user);
525 if (outlevel == O_VERBOSE)
527 "no local matches, forwarding to %s",
531 else /* it's a single-drop box, use first localname */
532 #endif /* HAVE_RES_SEARCH */
533 save_str(&xmit_names, -1, ctl->localnames->id);
535 /* time to address the message */
536 if (ctl->mda[0]) /* we have a declared MDA */
542 * We go through this in order to be able to handle very
543 * long lists of users and (re)implement %s.
545 for (idp = xmit_names; idp; idp = idp->next)
546 length += (strlen(idp->id) + 1);
547 names = (char *)alloca(length);
549 for (idp = xmit_names; idp; idp = idp->next)
551 strcat(names, idp->id);
554 cmd = (char *)alloca(strlen(ctl->mda) + length);
555 sprintf(cmd, ctl->mda, names);
556 if (outlevel == O_VERBOSE)
557 error(0, 0, "about to deliver with: %s", cmd);
561 * Arrange to run with user's permissions if we're root.
562 * This will initialize the ownership of any files the
563 * MDA creates properly. (The seteuid call is available
564 * under all BSDs and Linux)
567 #endif /* HAVE_SETEUID */
569 sinkfp = popen(cmd, "w");
572 /* this will fail quietly if we didn't start as root */
574 #endif /* HAVE_SETEUID */
578 error(0, 0, "MDA open failed");
582 sigchld = signal(SIGCHLD, SIG_DFL);
588 /* build a connection to the SMTP listener */
589 if (ctl->mda[0] == '\0' && ((sinkfp = smtp_open(ctl)) == NULL))
591 free_str_list(&xmit_names);
592 error(0, 0, "SMTP connect failed");
597 * Try to get the SMTP listener to take the header
598 * From address as MAIL FROM (this makes the logging
599 * nicer). If it won't, fall back on the calling-user
600 * ID. This won't affect replies, which use the header
601 * From address anyway.
603 if (!fromhdr || !(ap = nxtaddr(fromhdr)))
605 if (SMTP_from(sinkfp, user) != SM_OK)
606 return(PS_SMTP); /* should never happen */
608 else if (SMTP_from(sinkfp, ap) != SM_OK)
609 if (smtp_response == 571)
612 * SMTP listener explicitly refuses to deliver
613 * mail coming from this address, probably due
614 * to an anti-spam domain exclusion. Respect
617 sinkfp = (FILE *)NULL;
620 else if (SMTP_from(sinkfp, user) != SM_OK)
621 return(PS_SMTP); /* should never happen */
623 /* now list the recipient addressees */
624 for (idp = xmit_names; idp; idp = idp->next)
625 if (SMTP_rcpt(sinkfp, idp->id) == SM_OK)
632 "SMTP listener doesn't like recipient address `%s'", idp->id);
634 if (!good_addresses && SMTP_rcpt(sinkfp, user) != SM_OK)
637 "can't even send to calling user!");
641 /* tell it we're ready to send data */
647 /* change continuation markers back to regular newlines */
648 for (cp = headers; cp < headers + oldlen; cp++)
652 /* replace all LFs with CR-LF before sending to the SMTP server */
655 char *newheaders = xmalloc(1 + oldlen * 2);
657 oldlen = strcrlf(newheaders, headers, oldlen);
659 headers = newheaders;
662 /* write all the headers */
665 n = fwrite(headers, 1, oldlen, sinkfp);
671 error(0, errno, "writing RFC822 headers");
675 signal(SIGCHLD, sigchld);
679 else if (outlevel == O_VERBOSE)
684 /* write error notifications */
685 #ifdef HAVE_RES_SEARCH
686 if (no_local_matches || bad_addresses)
689 #endif /* HAVE_RES_SEARCH */
692 char errhd[USERNAMELEN + POPBUFSIZE], *errmsg;
695 (void) strcpy(errhd, "X-Fetchmail-Warning: ");
696 #ifdef HAVE_RES_SEARCH
697 if (no_local_matches)
699 strcat(errhd, "no recipient addresses matched declared local names");
703 #endif /* HAVE_RES_SEARCH */
707 strcat(errhd, "SMTP listener rejected local recipient addresses: ");
708 errlen = strlen(errhd);
709 for (idp = xmit_names; idp; idp = idp->next)
711 errlen += strlen(idp->id) + 2;
713 errmsg = alloca(errlen+3);
714 (void) strcpy(errmsg, errhd);
715 for (idp = xmit_names; idp; idp = idp->next)
718 strcat(errmsg, idp->id);
720 strcat(errmsg, ", ");
724 strcat(errmsg, "\n");
727 fputs(errmsg, sinkfp);
730 free_str_list(&xmit_names);
733 /* SMTP byte-stuffing */
734 if (*bufp == '.' && ctl->mda[0] == 0)
738 /* replace all LFs with CR-LF in the line */
741 char *newbufp = xmalloc(1 + strlen(bufp) * 2);
743 strcrlf(newbufp, bufp, strlen(bufp));
747 /* ship out the text line */
750 n = fwrite(bufp, 1, strlen(bufp), sinkfp);
756 error(0, errno, "writing message text");
760 signal(SIGCHLD, sigchld);
764 else if (outlevel == O_VERBOSE)
775 /* close the delivery pipe, we'll reopen before next message */
777 signal(SIGCHLD, sigchld);
780 error(0, 0, "MDA exited abnormally or returned nonzero status");
786 /* write message terminator */
787 if (SMTP_eom(sinkfp) != SM_OK)
789 error(0, 0, "SMTP listener refused delivery");
799 kerberos_auth (socket, canonical)
800 /* authenticate to the server host using Kerberos V4 */
801 int socket; /* socket to server host */
802 const char *canonical; /* server name */
808 Key_schedule schedule;
811 ticket = ((KTEXT) (malloc (sizeof (KTEXT_ST))));
812 rem = (krb_sendauth (0L, socket, ticket, "pop",
814 ((char *) (krb_realmofhost (canonical))),
819 ((struct sockaddr_in *) 0),
820 ((struct sockaddr_in *) 0),
825 error(0, 0, "kerberos error %s", (krb_get_err_text (rem)));
830 #endif /* KERBEROS_V4 */
832 int do_protocol(ctl, proto)
833 /* retrieve messages from server using given protocol method table */
834 struct query *ctl; /* parsed options with merged-in defaults */
835 const struct method *proto; /* protocol method table */
842 if (ctl->authenticate == A_KERBEROS)
844 error(0, 0, "Kerberos support not linked.");
847 #endif /* KERBEROS_V4 */
849 /* lacking methods, there are some options that may fail */
852 /* check for unsupported options */
855 "Option --flush is not supported with %s",
859 else if (ctl->fetchall) {
861 "Option --all is not supported with %s",
866 if (!proto->getsizes && ctl->limit)
869 "Option --limit is not supported with %s",
876 tag[0] = '\0'; /* nuke any tag hanging out from previous query */
879 /* set up the server-nonresponse timeout */
880 sigsave = signal(SIGVTALRM, vtalarm_handler);
881 vtalarm(mytimeout = ctl->timeout);
883 if ((js = setjmp(restart)) == 1)
886 "timeout after %d seconds waiting for %s.",
887 ctl->timeout, ctl->servernames->id);
892 /* error message printed at point of longjmp */
897 char buf [POPBUFSIZE+1];
898 int *msgsizes, len, num, count, new, deletions = 0;
901 /* open a socket to the mail server */
902 if ((sockfp = sockopen(ctl->servernames->id,
903 ctl->port ? ctl->port : protocol->port)) == NULL)
905 error(0, errno, "connecting to host");
911 if (ctl->authenticate == A_KERBEROS)
913 ok = kerberos_auth(fileno(sockfp), ctl->canonical_name);
916 vtalarm(ctl->timeout);
918 #endif /* KERBEROS_V4 */
920 /* accept greeting message from mail server */
921 ok = (protocol->parse_response)(sockfp, buf);
924 vtalarm(ctl->timeout);
926 /* try to get authorized to fetch mail */
927 shroud = ctl->password;
928 ok = (protocol->getauth)(sockfp, ctl, buf);
929 shroud = (char *)NULL;
934 vtalarm(ctl->timeout);
936 /* compute number of messages and number of new messages waiting */
937 ok = (protocol->getrange)(sockfp, ctl, &count, &new);
940 vtalarm(ctl->timeout);
942 /* show user how many messages we downloaded */
943 if (outlevel > O_SILENT)
945 error(0, 0, "No mail from %s@%s",
947 ctl->servernames->id);
950 if (new != -1 && (count - new) > 0)
951 error(0, 0, "%d message%s (%d seen) from %s@%s.",
952 count, count > 1 ? "s" : "", count-new,
954 ctl->servernames->id);
956 error(0, 0, "%d message%s from %s@%s.", count, count > 1 ? "s" : "",
958 ctl->servernames->id);
961 /* we may need to get sizes in order to check message limits */
962 msgsizes = (int *)NULL;
963 if (!ctl->fetchall && proto->getsizes && ctl->limit)
965 msgsizes = (int *)alloca(sizeof(int) * count);
967 ok = (proto->getsizes)(sockfp, count, msgsizes);
970 vtalarm(ctl->timeout);
976 if (new == -1 || ctl->fetchall)
978 ok = ((new > 0) ? PS_SUCCESS : PS_NOMAIL);
984 * What forces this code is that in POP3 and IMAP2BIS you can't
985 * fetch a message without having it marked `seen'. In IMAP4,
986 * on the other hand, you can (peek_capable is set to convey
989 * The result of being unable to peek is that if there's
990 * any kind of transient error (DNS lookup failure, or
991 * sendmail refusing delivery due to process-table limits)
992 * the message will be marked "seen" on the server without
993 * having been delivered. This is not a big problem if
994 * fetchmail is running in foreground, because the user
995 * will see a "skipped" message when it next runs and get
998 * But in daemon mode this leads to the message being silently
999 * ignored forever. This is not acceptable.
1001 * We compensate for this by checking the error count from the
1002 * previous pass and forcing all messages to be considered new
1005 int force_retrieval = !peek_capable && (ctl->errcount > 0);
1009 /* read, forward, and delete messages */
1010 for (num = 1; num <= count; num++)
1012 int toolarge = msgsizes && (msgsizes[num-1] > ctl->limit);
1013 int fetch_it = ctl->fetchall ||
1014 (!toolarge && (force_retrieval || !(protocol->is_old && (protocol->is_old)(sockfp,ctl,num))));
1016 /* we may want to reject this message if it's old */
1019 if (outlevel > O_SILENT)
1021 fprintf(stderr, "skipping message %d", num);
1023 fprintf(stderr, " (oversized, %d bytes)", msgsizes[num-1]);
1028 /* request a message */
1029 ok = (protocol->fetch)(sockfp, num, &len);
1032 vtalarm(ctl->timeout);
1034 if (outlevel > O_SILENT)
1036 fprintf(stderr, "reading message %d", num);
1038 fprintf(stderr, " (%d bytes)", len);
1039 if (outlevel == O_VERBOSE)
1040 fputc('\n', stderr);
1045 /* read the message and ship it to the output sink */
1046 ok = gen_readmsg(sockfp,
1048 protocol->delimited,
1052 vtalarm(ctl->timeout);
1054 /* tell the server we got it OK and resynchronize */
1055 if (protocol->trail)
1057 ok = (protocol->trail)(sockfp, ctl, num);
1060 vtalarm(ctl->timeout);
1065 * At this point in flow of control, either we've bombed
1066 * on a protocol error or had delivery refused by the SMTP
1067 * server (unlikely -- I've never seen it) or we've seen
1068 * `accepted for delivery' and the message is shipped.
1069 * It's safe to mark the message seen and delete it on the
1073 /* maybe we delete this message now? */
1074 if (protocol->delete
1075 && (fetch_it ? !ctl->keep : ctl->flush))
1078 if (outlevel > O_SILENT)
1079 fprintf(stderr, " flushed\n");
1080 ok = (protocol->delete)(sockfp, ctl, num);
1083 vtalarm(ctl->timeout);
1084 delete_str(&ctl->newsaved, num);
1086 else if (outlevel > O_SILENT)
1087 fprintf(stderr, " not flushed\n");
1090 /* remove all messages flagged for deletion */
1091 if (protocol->expunge_cmd && deletions > 0)
1093 ok = gen_transact(sockfp, protocol->expunge_cmd);
1096 vtalarm(ctl->timeout);
1099 ok = gen_transact(sockfp, protocol->exit_cmd);
1107 ok = gen_transact(sockfp, protocol->exit_cmd);
1116 vtalarm(ctl->timeout);
1117 if (ok != 0 && ok != PS_SOCKET)
1118 gen_transact(sockfp, protocol->exit_cmd);
1129 msg = "authorization";
1132 msg = "missing or bad RFC822 header";
1138 msg = "client/server synchronization";
1141 msg = "client/server protocol";
1144 msg = "SMTP transaction";
1147 error(0, 0, "undefined");
1150 if (ok==PS_SOCKET || ok==PS_AUTHFAIL || ok==PS_SYNTAX || ok==PS_IOERR
1151 || ok==PS_ERROR || ok==PS_PROTOCOL || ok==PS_SMTP)
1152 error(0, 0, "%s error while talking to %s", msg, ctl->servernames->id);
1155 signal(SIGVTALRM, sigsave);
1159 #if defined(HAVE_STDARG_H)
1160 void gen_send(FILE *sockfp, char *fmt, ... )
1161 /* assemble command in printf(3) style and send to the server */
1163 void gen_send(sockfp, fmt, va_alist)
1164 /* assemble command in printf(3) style and send to the server */
1165 FILE *sockfp; /* socket to which server is connected */
1166 const char *fmt; /* printf-style format */
1170 char buf [POPBUFSIZE+1];
1173 if (protocol->tagged)
1174 (void) sprintf(buf, "%s ", GENSYM);
1178 #if defined(HAVE_STDARG_H)
1183 vsprintf(buf + strlen(buf), fmt, ap);
1186 strcat(buf, "\r\n");
1189 if (outlevel == O_VERBOSE)
1193 if (shroud && (cp = strstr(buf, shroud)))
1194 memset(cp, '*', strlen(shroud));
1195 buf[strlen(buf)-1] = '\0';
1196 error(0, 0, "%s> %s", protocol->name, buf);
1200 #if defined(HAVE_STDARG_H)
1201 int gen_transact(FILE *sockfp, char *fmt, ... )
1202 /* assemble command in printf(3) style, send to server, accept a response */
1204 int gen_transact(sockfp, fmt, va_alist)
1205 /* assemble command in printf(3) style, send to server, accept a response */
1206 FILE *sockfp; /* socket to which server is connected */
1207 const char *fmt; /* printf-style format */
1212 char buf [POPBUFSIZE+1];
1215 if (protocol->tagged)
1216 (void) sprintf(buf, "%s ", GENSYM);
1220 #if defined(HAVE_STDARG_H)
1225 vsprintf(buf + strlen(buf), fmt, ap);
1228 strcat(buf, "\r\n");
1230 if (outlevel == O_VERBOSE)
1234 if (shroud && (cp = strstr(buf, shroud)))
1235 memset(cp, '*', strlen(shroud));
1236 buf[strlen(buf)-1] = '\0';
1237 error(0, 0, "%s> %s", protocol->name, buf);
1240 /* we presume this does its own response echoing */
1241 ok = (protocol->parse_response)(sockfp, buf);
1247 /* driver.c ends here */