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 fetchlimit; /* how often to tear down the server connection */
56 int batchcount; /* count of messages sent in current batch */
57 int peek_capable; /* can we peek for better error recovery? */
59 static const struct method *protocol;
60 static jmp_buf restart;
64 #define GENSYM (sprintf(tag, "a%04d", ++tagnum), tag)
66 static char *shroud; /* string to shroud in debug output, if non-NULL */
67 static int mytimeout; /* value of nonreponse timeout */
69 static int strcrlf(dst, src, count)
70 /* replace LFs with CR-LF; return length of string with replacements */
71 char *dst; /* new string with CR-LFs */
72 char *src; /* original string with LFs */
73 int count; /* length of src */
90 static void vtalarm(int timeleft)
91 /* reset the nonresponse-timeout */
93 struct itimerval ntimeout;
95 ntimeout.it_interval.tv_sec = ntimeout.it_interval.tv_usec = 0;
96 ntimeout.it_value.tv_sec = timeleft;
97 ntimeout.it_value.tv_usec = 0;
98 setitimer(ITIMER_VIRTUAL, &ntimeout, (struct itimerval *)NULL);
101 static void vtalarm_handler (int signal)
102 /* handle server-timeout SIGVTALARM signal */
107 #ifdef HAVE_RES_SEARCH
110 static int is_host_alias(const char *name, struct query *ctl)
111 /* determine whether name is a DNS alias of the hostname */
114 struct mxentry *mxp, *mxrecords;
117 * The first two checks are optimizations that will catch a good
118 * many cases. (1) check against the hostname the user
119 * specified. Odds are good this will either be the mailserver's
120 * FQDN or a suffix of it with the mailserver's domain's default
121 * host name omitted. Then check the rest of the `also known as'
122 * cache accumulated by previous DNS checks. This cache is primed
123 * by the aka list option.
125 * (2) check against the mailserver's FQDN, in case
126 * it's not the same as the declared hostname.
128 * Either of these on a mail address is definitive. Only if the
129 * name doesn't match either is it time to call the bind library.
130 * If this happens odds are good we're looking at an MX name.
132 if (str_in_list(&ctl->lead_server->servernames, name))
134 else if (strcmp(name, ctl->canonical_name) == 0)
138 * We know DNS service was up at the beginning of this poll cycle.
139 * If it's down, our nameserver has crashed. We don't want to try
140 * delivering the current message or anything else from this
141 * mailbox until it's back up.
143 else if ((he = gethostbyname(name)) != (struct hostent *)NULL)
145 if (strcmp(ctl->canonical_name, he->h_name) == 0)
153 case HOST_NOT_FOUND: /* specified host is unknown */
154 case NO_ADDRESS: /* valid, but does not have an IP address */
157 case NO_RECOVERY: /* non-recoverable name server error */
158 case TRY_AGAIN: /* temporary error on authoritative server */
160 if (outlevel != O_SILENT)
161 putchar('\n'); /* terminate the progress message */
163 "nameserver failure while looking for `%s' during poll of %s.",
164 name, ctl->servernames->id);
166 longjmp(restart, 2); /* try again next poll cycle */
171 * We're only here if DNS was OK but the gethostbyname() failed
172 * with a HOST_NOT_FOUND or NO_ADDRESS error.
173 * Search for a name match on MX records pointing to the server.
176 if ((mxrecords = getmxrecords(name)) == (struct mxentry *)NULL)
180 case HOST_NOT_FOUND: /* specified host is unknown */
181 case NO_ADDRESS: /* valid, but does not have an IP address */
185 case NO_RECOVERY: /* non-recoverable name server error */
186 case TRY_AGAIN: /* temporary error on authoritative server */
189 "nameserver failure while looking for `%s' during poll of %s.",
190 name, ctl->servernames->id);
192 longjmp(restart, 2); /* try again next poll cycle */
198 for (mxp = mxrecords; mxp->name; mxp++)
199 if (strcmp(ctl->canonical_name, mxp->name) == 0)
205 /* add this name to relevant server's `also known as' list */
206 save_str(&ctl->lead_server->servernames, -1, name);
210 static void map_name(name, ctl, xmit_names)
211 /* add given name to xmit_names if it matches declared localnames */
212 const char *name; /* name to map */
213 struct query *ctl; /* list of permissible aliases */
214 struct idlist **xmit_names; /* list of recipient names parsed out */
218 lname = idpair_find(&ctl->localnames, name);
219 if (!lname && ctl->wildcard)
222 if (lname != (char *)NULL)
224 if (outlevel == O_VERBOSE)
225 error(0, 0, "mapped %s to local %s", name, lname);
226 save_str(xmit_names, -1, lname);
230 void find_server_names(hdr, ctl, xmit_names)
231 /* parse names out of a RFC822 header into an ID list */
232 const char *hdr; /* RFC822 header in question */
233 struct query *ctl; /* list of permissible aliases */
234 struct idlist **xmit_names; /* list of recipient names parsed out */
236 if (hdr == (char *)NULL)
242 if ((cp = nxtaddr(hdr)) != (char *)NULL)
246 if ((atsign = strchr(cp, '@')))
249 * Address has an @. Check to see if the right-hand part
250 * is an alias or MX equivalent of the mailserver. If it's
251 * not, skip this name. If it is, we'll keep going and try
252 * to find a mapping to a client name.
254 if (!is_host_alias(atsign+1, ctl))
259 map_name(cp, ctl, xmit_names);
261 ((cp = nxtaddr((char *)NULL)) != (char *)NULL);
264 #endif /* HAVE_RES_SEARCH */
266 static FILE *smtp_open(struct query *ctl)
267 /* try to open a socket to the appropriate SMTP server for this query */
269 ctl = ctl->lead_smtp; /* go to the SMTP leader for this query */
271 /* maybe it's time to close the socket in order to force delivery */
272 if (batchlimit && ctl->smtp_sockfp && batchcount++ == batchlimit)
274 fclose(ctl->smtp_sockfp);
275 ctl->smtp_sockfp = (FILE *)NULL;
279 /* if no socket to this host is already set up, try to open one */
280 if (ctl->smtp_sockfp == (FILE *)NULL)
282 if ((ctl->smtp_sockfp = sockopen(ctl->smtphost, SMTP_PORT)) == (FILE *)NULL)
283 return((FILE *)NULL);
284 else if (SMTP_ok(ctl->smtp_sockfp) != SM_OK
285 || SMTP_helo(ctl->smtp_sockfp, ctl->servernames->id) != SM_OK)
287 fclose(ctl->smtp_sockfp);
288 ctl->smtp_sockfp = (FILE *)NULL;
292 return(ctl->smtp_sockfp);
295 static int SockGets(char *buf, int len, FILE *sockfp)
296 /* get a LF-terminated line, removing \r characters */
302 if ((*buf = fgetc(sockfp)) == EOF)
308 if (*buf != '\r') /* remove all CRs */
315 static int gen_readmsg (sockfp, len, delimited, ctl)
316 /* read message content and ship to SMTP or MDA */
317 FILE *sockfp; /* to which the server is connected */
318 long len; /* length of message */
319 int delimited; /* does the protocol use a message delimiter? */
320 struct query *ctl; /* query control record */
322 char buf [MSGBUFSIZE+1];
323 char *bufp, *headers, *fromhdr,*tohdr,*cchdr,*bcchdr,*received_for,*envto;
325 int inheaders,lines,sizeticker;
327 RETSIGTYPE (*sigchld)();
328 #ifdef HAVE_GETHOSTBYNAME
329 char rbuf[HOSTLEN + USERNAMELEN + 4];
330 #endif /* HAVE_GETHOSTBYNAME */
332 /* read the message content from the server */
334 headers = fromhdr = tohdr = cchdr = bcchdr = received_for = envto = NULL;
338 while (delimited || len > 0)
340 if ((n = SockGets(buf,sizeof(buf),sockfp)) < 0)
342 vtalarm(ctl->timeout);
344 /* write the message size dots */
348 while (sizeticker >= SIZETICKER)
350 if (outlevel > O_SILENT)
352 sizeticker -= SIZETICKER;
357 if (buf[0] == '\0' || buf[0] == '\r' || buf[0] == '\n')
359 if (delimited && *bufp == '.') {
362 break; /* end of message */
369 reply_hack(bufp, ctl->servernames->id);
373 oldlen = strlen(bufp);
374 headers = xmalloc(oldlen + 1);
375 (void) strcpy(headers, bufp);
383 * We deal with RFC822 continuation lines here.
384 * Replace previous '\n' with '\r' so nxtaddr
385 * and reply_hack will be able to see past it.
386 * (We know this is safe because SocketGets stripped
387 * out all carriage returns in the read loop above
388 * and we haven't reintroduced any since then.)
389 * We'll undo this before writing the header.
391 if (isspace(bufp[0]))
392 headers[oldlen-1] = '\r';
394 newlen = oldlen + strlen(bufp);
395 headers = realloc(headers, newlen + 1);
398 strcpy(headers + oldlen, bufp);
399 bufp = headers + oldlen;
403 if (!strncasecmp("From:", bufp, 5))
405 else if (!fromhdr && !strncasecmp("Resent-From:", bufp, 12))
407 else if (!fromhdr && !strncasecmp("Apparently-From:", bufp, 16))
409 else if (!strncasecmp("To:", bufp, 3))
411 else if (!strncasecmp("Apparently-To:", bufp, 14))
413 else if (!strncasecmp(ctl->envelope, bufp, 14))
415 else if (!strncasecmp("Cc:", bufp, 3))
417 else if (!strncasecmp("Bcc:", bufp, 4))
419 #ifdef HAVE_RES_SEARCH
420 else if (MULTIDROP(ctl) && !strncasecmp("Received:", bufp, 9))
425 * Try to extract the real envelope addressee. We look here
426 * specifically for the mailserver's Received line.
427 * Note: this will only work for sendmail, or an MTA that
428 * shares sendmail's convention for embedding the envelope
429 * address in the Received line. Sendmail itself only
430 * does this when the mail has a single recipient.
432 if ((ok = strstr(bufp, "by ")) == (char *)NULL)
438 /* extract space-delimited token after "by " */
440 for (sp = ok + 3; !isspace(*sp); sp++)
445 * If it's a DNS name of the mail server, look for the
446 * recipient name after a following "for". Otherwise
449 if (is_host_alias(rbuf, ctl))
450 ok = strstr(sp, "for ");
463 while (*sp && *sp != '>' && *sp != '@' && *sp != ';')
468 /* uh oh -- whitespace here can't be right! */
477 received_for = alloca(strlen(rbuf)+1);
478 strcpy(received_for, rbuf);
479 if (outlevel == O_VERBOSE)
481 "found Received address `%s'",
485 #endif /* HAVE_RES_SEARCH */
489 else if (headers) /* OK, we're at end of headers now */
492 struct idlist *idp, *xmit_names;
493 int good_addresses, bad_addresses;
494 #ifdef HAVE_RES_SEARCH
495 int no_local_matches = FALSE;
496 #endif /* HAVE_RES_SEARCH */
498 /* cons up a list of local recipients */
499 xmit_names = (struct idlist *)NULL;
500 bad_addresses = good_addresses = 0;
501 #ifdef HAVE_RES_SEARCH
502 /* is this a multidrop box? */
505 if (envto) /* We have the actual envelope addressee */
506 find_server_names(envto, ctl, &xmit_names);
507 else if (received_for)
509 * We have the Received for addressee.
510 * It has to be a mailserver address, or we
511 * wouldn't have got here.
513 map_name(received_for, ctl, &xmit_names);
517 * We haven't extracted the envelope address.
518 * So check all the header addresses.
520 find_server_names(tohdr, ctl, &xmit_names);
521 find_server_names(cchdr, ctl, &xmit_names);
522 find_server_names(bcchdr, ctl, &xmit_names);
526 no_local_matches = TRUE;
527 save_str(&xmit_names, -1, user);
528 if (outlevel == O_VERBOSE)
530 "no local matches, forwarding to %s",
534 else /* it's a single-drop box, use first localname */
535 #endif /* HAVE_RES_SEARCH */
536 save_str(&xmit_names, -1, ctl->localnames->id);
538 /* time to address the message */
539 if (ctl->mda[0]) /* we have a declared MDA */
545 * We go through this in order to be able to handle very
546 * long lists of users and (re)implement %s.
548 for (idp = xmit_names; idp; idp = idp->next)
549 length += (strlen(idp->id) + 1);
550 names = (char *)alloca(length);
552 for (idp = xmit_names; idp; idp = idp->next)
554 strcat(names, idp->id);
557 cmd = (char *)alloca(strlen(ctl->mda) + length);
558 sprintf(cmd, ctl->mda, names);
559 if (outlevel == O_VERBOSE)
560 error(0, 0, "about to deliver with: %s", cmd);
564 * Arrange to run with user's permissions if we're root.
565 * This will initialize the ownership of any files the
566 * MDA creates properly. (The seteuid call is available
567 * under all BSDs and Linux)
570 #endif /* HAVE_SETEUID */
572 sinkfp = popen(cmd, "w");
575 /* this will fail quietly if we didn't start as root */
577 #endif /* HAVE_SETEUID */
581 error(0, 0, "MDA open failed");
585 sigchld = signal(SIGCHLD, SIG_DFL);
591 /* build a connection to the SMTP listener */
592 if (ctl->mda[0] == '\0' && ((sinkfp = smtp_open(ctl)) == NULL))
594 free_str_list(&xmit_names);
595 error(0, 0, "SMTP connect failed");
600 * Try to get the SMTP listener to take the header
601 * From address as MAIL FROM (this makes the logging
602 * nicer). If it won't, fall back on the calling-user
603 * ID. This won't affect replies, which use the header
604 * From address anyway.
606 if (!fromhdr || !(ap = nxtaddr(fromhdr)))
608 if (SMTP_from(sinkfp, user) != SM_OK)
609 return(PS_SMTP); /* should never happen */
611 else if (SMTP_from(sinkfp, ap) != SM_OK)
612 if (smtp_response == 571)
615 * SMTP listener explicitly refuses to deliver
616 * mail coming from this address, probably due
617 * to an anti-spam domain exclusion. Respect
620 sinkfp = (FILE *)NULL;
623 else if (SMTP_from(sinkfp, user) != SM_OK)
624 return(PS_SMTP); /* should never happen */
626 /* now list the recipient addressees */
627 for (idp = xmit_names; idp; idp = idp->next)
628 if (SMTP_rcpt(sinkfp, idp->id) == SM_OK)
635 "SMTP listener doesn't like recipient address `%s'", idp->id);
637 if (!good_addresses && SMTP_rcpt(sinkfp, user) != SM_OK)
640 "can't even send to calling user!");
644 /* tell it we're ready to send data */
650 /* change continuation markers back to regular newlines */
651 for (cp = headers; cp < headers + oldlen; cp++)
655 /* replace all LFs with CR-LF before sending to the SMTP server */
658 char *newheaders = xmalloc(1 + oldlen * 2);
660 oldlen = strcrlf(newheaders, headers, oldlen);
662 headers = newheaders;
665 /* write all the headers */
668 n = fwrite(headers, 1, oldlen, sinkfp);
674 error(0, errno, "writing RFC822 headers");
678 signal(SIGCHLD, sigchld);
682 else if (outlevel == O_VERBOSE)
687 /* write error notifications */
688 #ifdef HAVE_RES_SEARCH
689 if (no_local_matches || bad_addresses)
692 #endif /* HAVE_RES_SEARCH */
695 char errhd[USERNAMELEN + POPBUFSIZE], *errmsg;
698 (void) strcpy(errhd, "X-Fetchmail-Warning: ");
699 #ifdef HAVE_RES_SEARCH
700 if (no_local_matches)
702 strcat(errhd, "no recipient addresses matched declared local names");
706 #endif /* HAVE_RES_SEARCH */
710 strcat(errhd, "SMTP listener rejected local recipient addresses: ");
711 errlen = strlen(errhd);
712 for (idp = xmit_names; idp; idp = idp->next)
714 errlen += strlen(idp->id) + 2;
716 errmsg = alloca(errlen+3);
717 (void) strcpy(errmsg, errhd);
718 for (idp = xmit_names; idp; idp = idp->next)
721 strcat(errmsg, idp->id);
723 strcat(errmsg, ", ");
727 strcat(errmsg, "\n");
730 fputs(errmsg, sinkfp);
733 free_str_list(&xmit_names);
736 /* SMTP byte-stuffing */
737 if (*bufp == '.' && ctl->mda[0] == 0)
741 /* replace all LFs with CR-LF in the line */
744 char *newbufp = xmalloc(1 + strlen(bufp) * 2);
746 strcrlf(newbufp, bufp, strlen(bufp));
750 /* ship out the text line */
753 n = fwrite(bufp, 1, strlen(bufp), sinkfp);
759 error(0, errno, "writing message text");
763 signal(SIGCHLD, sigchld);
767 else if (outlevel == O_VERBOSE)
778 /* close the delivery pipe, we'll reopen before next message */
780 signal(SIGCHLD, sigchld);
783 error(0, 0, "MDA exited abnormally or returned nonzero status");
789 /* write message terminator */
790 if (SMTP_eom(sinkfp) != SM_OK)
792 error(0, 0, "SMTP listener refused delivery");
802 kerberos_auth (socket, canonical)
803 /* authenticate to the server host using Kerberos V4 */
804 int socket; /* socket to server host */
805 const char *canonical; /* server name */
811 Key_schedule schedule;
814 ticket = ((KTEXT) (malloc (sizeof (KTEXT_ST))));
815 rem = (krb_sendauth (0L, socket, ticket, "pop",
817 ((char *) (krb_realmofhost (canonical))),
822 ((struct sockaddr_in *) 0),
823 ((struct sockaddr_in *) 0),
828 error(0, 0, "kerberos error %s", (krb_get_err_text (rem)));
833 #endif /* KERBEROS_V4 */
835 int do_protocol(ctl, proto)
836 /* retrieve messages from server using given protocol method table */
837 struct query *ctl; /* parsed options with merged-in defaults */
838 const struct method *proto; /* protocol method table */
845 if (ctl->authenticate == A_KERBEROS)
847 error(0, 0, "Kerberos support not linked.");
850 #endif /* KERBEROS_V4 */
852 /* lacking methods, there are some options that may fail */
855 /* check for unsupported options */
858 "Option --flush is not supported with %s",
862 else if (ctl->fetchall) {
864 "Option --all is not supported with %s",
869 if (!proto->getsizes && ctl->limit)
872 "Option --limit is not supported with %s",
879 tag[0] = '\0'; /* nuke any tag hanging out from previous query */
882 /* set up the server-nonresponse timeout */
883 sigsave = signal(SIGVTALRM, vtalarm_handler);
884 vtalarm(mytimeout = ctl->timeout);
886 if ((js = setjmp(restart)) == 1)
889 "timeout after %d seconds waiting for %s.",
890 ctl->timeout, ctl->servernames->id);
895 /* error message printed at point of longjmp */
900 char buf [POPBUFSIZE+1];
901 int *msgsizes, len, num, count, new, deletions = 0;
904 /* open a socket to the mail server */
905 if ((sockfp = sockopen(ctl->servernames->id,
906 ctl->port ? ctl->port : protocol->port)) == NULL)
908 error(0, errno, "connecting to host");
914 if (ctl->authenticate == A_KERBEROS)
916 ok = kerberos_auth(fileno(sockfp), ctl->canonical_name);
919 vtalarm(ctl->timeout);
921 #endif /* KERBEROS_V4 */
923 /* accept greeting message from mail server */
924 ok = (protocol->parse_response)(sockfp, buf);
927 vtalarm(ctl->timeout);
929 /* try to get authorized to fetch mail */
930 shroud = ctl->password;
931 ok = (protocol->getauth)(sockfp, ctl, buf);
932 shroud = (char *)NULL;
937 vtalarm(ctl->timeout);
939 /* compute number of messages and number of new messages waiting */
940 ok = (protocol->getrange)(sockfp, ctl, &count, &new);
943 vtalarm(ctl->timeout);
945 /* show user how many messages we downloaded */
946 if (outlevel > O_SILENT)
948 error(0, 0, "No mail from %s@%s",
950 ctl->servernames->id);
953 if (new != -1 && (count - new) > 0)
954 error(0, 0, "%d message%s (%d seen) from %s@%s.",
955 count, count > 1 ? "s" : "", count-new,
957 ctl->servernames->id);
959 error(0, 0, "%d message%s from %s@%s.", count, count > 1 ? "s" : "",
961 ctl->servernames->id);
964 /* we may need to get sizes in order to check message limits */
965 msgsizes = (int *)NULL;
966 if (!ctl->fetchall && proto->getsizes && ctl->limit)
968 msgsizes = (int *)alloca(sizeof(int) * count);
970 ok = (proto->getsizes)(sockfp, count, msgsizes);
973 vtalarm(ctl->timeout);
979 if (new == -1 || ctl->fetchall)
981 ok = ((new > 0) ? PS_SUCCESS : PS_NOMAIL);
987 * What forces this code is that in POP3 and IMAP2BIS you can't
988 * fetch a message without having it marked `seen'. In IMAP4,
989 * on the other hand, you can (peek_capable is set to convey
992 * The result of being unable to peek is that if there's
993 * any kind of transient error (DNS lookup failure, or
994 * sendmail refusing delivery due to process-table limits)
995 * the message will be marked "seen" on the server without
996 * having been delivered. This is not a big problem if
997 * fetchmail is running in foreground, because the user
998 * will see a "skipped" message when it next runs and get
1001 * But in daemon mode this leads to the message being silently
1002 * ignored forever. This is not acceptable.
1004 * We compensate for this by checking the error count from the
1005 * previous pass and forcing all messages to be considered new
1008 int force_retrieval = !peek_capable && (ctl->errcount > 0);
1012 /* read, forward, and delete messages */
1013 for (num = 1; num <= count; num++)
1015 int toolarge = msgsizes && (msgsizes[num-1] > ctl->limit);
1016 int fetch_it = ctl->fetchall ||
1017 (!toolarge && (force_retrieval || !(protocol->is_old && (protocol->is_old)(sockfp,ctl,num))));
1019 /* we may want to reject this message if it's old */
1022 if (outlevel > O_SILENT)
1024 fprintf(stderr, "skipping message %d", num);
1026 fprintf(stderr, " (oversized, %d bytes)", msgsizes[num-1]);
1031 /* request a message */
1032 ok = (protocol->fetch)(sockfp, num, &len);
1035 vtalarm(ctl->timeout);
1037 if (outlevel > O_SILENT)
1039 fprintf(stderr, "reading message %d", num);
1041 fprintf(stderr, " (%d bytes)", len);
1042 if (outlevel == O_VERBOSE)
1043 fputc('\n', stderr);
1048 /* read the message and ship it to the output sink */
1049 ok = gen_readmsg(sockfp,
1051 protocol->delimited,
1055 vtalarm(ctl->timeout);
1057 /* tell the server we got it OK and resynchronize */
1058 if (protocol->trail)
1060 ok = (protocol->trail)(sockfp, ctl, num);
1063 vtalarm(ctl->timeout);
1068 * At this point in flow of control, either we've bombed
1069 * on a protocol error or had delivery refused by the SMTP
1070 * server (unlikely -- I've never seen it) or we've seen
1071 * `accepted for delivery' and the message is shipped.
1072 * It's safe to mark the message seen and delete it on the
1076 /* maybe we delete this message now? */
1077 if (protocol->delete
1078 && (fetch_it ? !ctl->keep : ctl->flush))
1081 if (outlevel > O_SILENT)
1082 fprintf(stderr, " flushed\n");
1083 ok = (protocol->delete)(sockfp, ctl, num);
1086 vtalarm(ctl->timeout);
1087 delete_str(&ctl->newsaved, num);
1089 else if (outlevel > O_SILENT)
1090 fprintf(stderr, " not flushed\n");
1092 /* perhaps this as many as we're ready to handle */
1093 if (ctl->fetchlimit && ctl->fetchlimit <= num)
1097 /* remove all messages flagged for deletion */
1098 if (protocol->expunge_cmd && deletions > 0)
1100 ok = gen_transact(sockfp, protocol->expunge_cmd);
1103 vtalarm(ctl->timeout);
1106 ok = gen_transact(sockfp, protocol->exit_cmd);
1114 ok = gen_transact(sockfp, protocol->exit_cmd);
1123 vtalarm(ctl->timeout);
1124 if (ok != 0 && ok != PS_SOCKET)
1125 gen_transact(sockfp, protocol->exit_cmd);
1136 msg = "authorization";
1139 msg = "missing or bad RFC822 header";
1145 msg = "client/server synchronization";
1148 msg = "client/server protocol";
1151 msg = "SMTP transaction";
1154 error(0, 0, "undefined");
1157 if (ok==PS_SOCKET || ok==PS_AUTHFAIL || ok==PS_SYNTAX || ok==PS_IOERR
1158 || ok==PS_ERROR || ok==PS_PROTOCOL || ok==PS_SMTP)
1159 error(0, 0, "%s error while talking to %s", msg, ctl->servernames->id);
1162 signal(SIGVTALRM, sigsave);
1166 #if defined(HAVE_STDARG_H)
1167 void gen_send(FILE *sockfp, char *fmt, ... )
1168 /* assemble command in printf(3) style and send to the server */
1170 void gen_send(sockfp, fmt, va_alist)
1171 /* assemble command in printf(3) style and send to the server */
1172 FILE *sockfp; /* socket to which server is connected */
1173 const char *fmt; /* printf-style format */
1177 char buf [POPBUFSIZE+1];
1180 if (protocol->tagged)
1181 (void) sprintf(buf, "%s ", GENSYM);
1185 #if defined(HAVE_STDARG_H)
1190 vsprintf(buf + strlen(buf), fmt, ap);
1193 strcat(buf, "\r\n");
1196 if (outlevel == O_VERBOSE)
1200 if (shroud && (cp = strstr(buf, shroud)))
1201 memset(cp, '*', strlen(shroud));
1202 buf[strlen(buf)-1] = '\0';
1203 error(0, 0, "%s> %s", protocol->name, buf);
1207 #if defined(HAVE_STDARG_H)
1208 int gen_transact(FILE *sockfp, char *fmt, ... )
1209 /* assemble command in printf(3) style, send to server, accept a response */
1211 int gen_transact(sockfp, fmt, va_alist)
1212 /* assemble command in printf(3) style, send to server, accept a response */
1213 FILE *sockfp; /* socket to which server is connected */
1214 const char *fmt; /* printf-style format */
1219 char buf [POPBUFSIZE+1];
1222 if (protocol->tagged)
1223 (void) sprintf(buf, "%s ", GENSYM);
1227 #if defined(HAVE_STDARG_H)
1232 vsprintf(buf + strlen(buf), fmt, ap);
1235 strcat(buf, "\r\n");
1237 if (outlevel == O_VERBOSE)
1241 if (shroud && (cp = strstr(buf, shroud)))
1242 memset(cp, '*', strlen(shroud));
1243 buf[strlen(buf)-1] = '\0';
1244 error(0, 0, "%s> %s", protocol->name, buf);
1247 /* we presume this does its own response echoing */
1248 ok = (protocol->parse_response)(sockfp, buf);
1254 /* driver.c ends here */