#define GENSYM (sprintf(tag, "a%04d", ++tagnum), tag)
static char *shroud; /* string to shroud in debug output, if non-NULL */
+static int mytimeout; /* value of nonreponse timeout */
static int strcrlf(dst, src, count)
/* replace LFs with CR-LF; return length of string with replacements */
return len;
}
-static void alarm_handler (int signal)
-/* handle server-timeout signal */
+static void vtalarm(timeleft)
+/* reset the nonresponse-timeout */
+int timeleft;
+{
+ struct itimerval ntimeout;
+
+ ntimeout.it_interval.tv_sec = ntimeout.it_interval.tv_sec = 0;
+ ntimeout.it_value.tv_sec = timeleft;
+ ntimeout.it_value.tv_usec = 0;
+ setitimer(ITIMER_VIRTUAL, &ntimeout, (struct itimerval *)NULL);
+}
+
+static void vtalarm_handler (int signal)
+/* handle server-timeout SIGVTALARM signal */
{
longjmp(restart, 1);
}
state = 5;
else if (isspace(*from))
state = 2;
- else if (*from == ',')
- tokencount = 0;
break;
case 2: /* found a token boundary -- reset without copying */
strcpy(buf, "@");
strcat(buf, host);
buf += strlen(buf);
+ tokencount = 0;
state = 1;
}
/* a single local name alone on the line */
- else if (*from == '\n' && tokencount == 0)
+ else if (*from == '\n' && tokencount == 1)
{
strcpy(buf, "@");
strcat(buf, host);
if ((cp = nxtaddr(hdr)) != (char *)NULL)
do {
- char *atsign = strchr(cp, '@');
+ char *atsign;
- if (atsign)
- if (ctl->norewrite)
+ if ((atsign = strchr(cp, '@')))
+ {
+ /*
+ * Address has an @. Check to see if the right-hand part
+ * is an alias or MX equivalent of the mailserver. If it's
+ * not, skip this name. If it is, we'll keep going and try
+ * to find a mapping to a client name.
+ */
+ if (!is_host_alias(atsign+1, ctl))
continue;
- else
- {
- if (!is_host_alias(atsign+1, ctl))
- continue;
- atsign[0] = '\0';
- }
+ atsign[0] = '\0';
+ }
+
lname = idpair_find(&ctl->localnames, cp);
if (lname != (char *)NULL)
{
}
#endif /* HAVE_GETHOSTBYNAME */
-static int smtp_open(ctl)
+static FILE *smtp_open(ctl)
/* try to open a socket to the appropriate SMTP server for this query */
struct query *ctl;
{
ctl = ctl->leader; /* go to the SMTP leader for this query */
/* if no socket to this host is already set up, try to open one */
- if (ctl->smtp_socket == -1)
+ if (ctl->smtp_sockfp == (FILE *)NULL)
{
- if ((ctl->smtp_socket = Socket(ctl->smtphost, SMTP_PORT)) == -1)
- return(-1);
- else if (SMTP_ok(ctl->smtp_socket, NULL) != SM_OK
- || SMTP_helo(ctl->smtp_socket, ctl->servername) != SM_OK)
+ if ((ctl->smtp_sockfp = Socket(ctl->smtphost, SMTP_PORT)) == (FILE *)NULL)
+ return((FILE *)NULL);
+ else if (SMTP_ok(ctl->smtp_sockfp, NULL) != SM_OK
+ || SMTP_helo(ctl->smtp_sockfp, ctl->servername) != SM_OK)
{
- close(ctl->smtp_socket);
- ctl->smtp_socket = -1;
+ fclose(ctl->smtp_sockfp);
+ ctl->smtp_sockfp = (FILE *)NULL;
}
}
- return(ctl->smtp_socket);
+ return(ctl->smtp_sockfp);
}
-static int gen_readmsg (socket, len, delimited, ctl)
+static int gen_readmsg (sockfp, len, delimited, ctl)
/* read message content and ship to SMTP or MDA */
-int socket; /* to which the server is connected */
+FILE *sockfp; /* to which the server is connected */
long len; /* length of message */
int delimited; /* does the protocol use a message delimiter? */
struct query *ctl; /* query control record */
char *bufp, *headers, *fromhdr, *tohdr, *cchdr, *bcchdr;
int n, oldlen, mboxfd;
int inheaders,lines,sizeticker;
+ FILE *sinkfp;
/* read the message content from the server */
inheaders = 1;
oldlen = 0;
while (delimited || len > 0)
{
- if ((n = SockGets(socket,buf,sizeof(buf))) < 0)
+ if ((n = SockGets(buf,sizeof(buf),sockfp)) < 0)
return(PS_SOCKET);
+ vtalarm(ctl->timeout);
/* write the message size dots */
if (n > 0)
*/
for (idp = xmit_names; idp; idp = idp->next)
nlocals++;
- sp = sargv = (char **)alloca(ctl->mda_argcount+nlocals+2);
+ sp = sargv = (char **)alloca(sizeof(char **) * ctl->mda_argcount+nlocals+2);
for (i = 0; i < ctl->mda_argcount; i++)
*sp++ = ctl->mda_argv[i];
for (idp = xmit_names; idp; idp = idp->next)
}
else
{
- if (ctl->mda[0] == '\0' && ((mboxfd = smtp_open(ctl)) < 0))
+ if (ctl->mda[0] == '\0' && ((sinkfp = smtp_open(ctl)) < 0))
{
free_uid_list(&xmit_names);
fprintf(stderr, "fetchmail: SMTP connect failed\n");
return(PS_SMTP);
}
- if (SMTP_from(mboxfd, nxtaddr(fromhdr)) != SM_OK)
+ if (SMTP_from(sinkfp, nxtaddr(fromhdr)) != SM_OK)
{
fprintf(stderr, "fetchmail: SMTP listener is confused\n");
return(PS_SMTP);
}
for (idp = xmit_names; idp; idp = idp->next)
- if (SMTP_rcpt(mboxfd, idp->id) != SM_OK)
+ if (SMTP_rcpt(sinkfp, idp->id) != SM_OK)
{
fprintf(stderr, "fetchmail: SMTP listener is upset\n");
return(PS_SMTP);
}
- SMTP_data(mboxfd);
+ SMTP_data(sinkfp);
if (outlevel == O_VERBOSE)
fputs("SMTP> ", stderr);
}
free_uid_list(&xmit_names);
/* change continuation markers back to regular newlines */
- for (cp = headers; cp < headers + oldlen; cp++)
+ for (cp = headers; cp < headers + oldlen; cp++)
if (*cp == '\r')
*cp = '\n';
+ headers[oldlen++] = '\0';
/* replace all LFs with CR-LF before sending to the SMTP server */
if (!ctl->mda[0])
free(headers);
headers = newheaders;
}
- if (write(mboxfd,headers,oldlen) < 0)
+
+ /* write all the headers */
+ if (ctl->mda[0])
+ n = write(mboxfd,headers,oldlen);
+ else
+ n = SockWrite(headers, oldlen, sinkfp);
+
+ if (n < 0)
{
free(headers);
headers = NULL;
/* SMTP byte-stuffing */
if (*bufp == '.' && ctl->mda[0] == 0)
- write(mboxfd, ".", 1);
+ SockWrite(".", 1, sinkfp);
- /* write this line to the file after replacing all LFs with CR-LF */
+ /* replace all LFs with CR-LF in the line */
if (!ctl->mda[0])
{
char *newbufp = malloc(1 + strlen(bufp) * 2);
strcrlf(newbufp, bufp, strlen(bufp));
bufp = newbufp;
}
- n = write(mboxfd,bufp,strlen(bufp));
+
+ /* ship out the text line */
+ if (ctl->mda[0])
+ n = write(mboxfd,bufp,strlen(bufp));
+ else
+ n = SockWrite(bufp, strlen(bufp), sinkfp);
+
if (!ctl->mda[0])
free(bufp);
if (n < 0)
else
{
/* write message terminator */
- if (SMTP_eom(mboxfd) != SM_OK)
+ if (SMTP_eom(sinkfp) != SM_OK)
{
fputs("fetchmail: SMTP listener refused delivery\n", stderr);
return(PS_SMTP);
tag[0] = '\0'; /* nuke any tag hanging out from previous query */
ok = 0;
+ /* set up the server-nonresponse timeout */
+ sigsave = signal(SIGVTALRM, vtalarm_handler);
+ vtalarm(mytimeout = ctl->timeout);
+
if (setjmp(restart) == 1)
fprintf(stderr,
"fetchmail: timeout after %d seconds waiting for %s.\n",
else
{
char buf [POPBUFSIZE+1];
- int *msgsizes, socket, len, num, count, new, deletions = 0;
-
- /* set up the server-nonresponse timeout */
- sigsave = signal(SIGALRM, alarm_handler);
- alarm(ctl->timeout);
+ int *msgsizes, len, num, count, new, deletions = 0;
+ FILE *sockfp;
/* open a socket to the mail server */
- if ((socket = Socket(ctl->servername,
+ if ((sockfp = Socket(ctl->servername,
ctl->port ? ctl->port : protocol->port))<0)
{
perror("fetchmail, connecting to host");
#ifdef KERBEROS_V4
if (ctl->authenticate == A_KERBEROS)
{
- ok = (kerberos_auth (socket, ctl->canonical_name));
- if (ok != 0)
+ ok = (kerberos_auth (fileno(sockfp), ctl->canonical_name));
+ vtalarm(ctl->timeout);
+ if (ok != 0)
goto cleanUp;
}
#endif /* KERBEROS_V4 */
/* accept greeting message from mail server */
- ok = (protocol->parse_response)(socket, buf);
+ ok = (protocol->parse_response)(sockfp, buf);
+ vtalarm(ctl->timeout);
if (ok != 0)
goto cleanUp;
/* try to get authorized to fetch mail */
shroud = ctl->password;
- ok = (protocol->getauth)(socket, ctl, buf);
+ ok = (protocol->getauth)(sockfp, ctl, buf);
+ vtalarm(ctl->timeout);
shroud = (char *)NULL;
if (ok == PS_ERROR)
ok = PS_AUTHFAIL;
goto cleanUp;
/* compute number of messages and number of new messages waiting */
- if ((protocol->getrange)(socket, ctl, &count, &new) != 0)
+ if ((protocol->getrange)(sockfp, ctl, &count, &new) != 0)
goto cleanUp;
+ vtalarm(ctl->timeout);
/* show user how many messages we downloaded */
if (outlevel > O_SILENT)
{
msgsizes = (int *)alloca(sizeof(int) * count);
- if ((ok = (proto->getsizes)(socket, count, msgsizes)) != 0)
+ if ((ok = (proto->getsizes)(sockfp, count, msgsizes)) != 0)
return(PS_ERROR);
}
{
int toolarge = msgsizes && msgsizes[num-1]>ctl->limit;
int fetch_it = ctl->fetchall ||
- (!(protocol->is_old && (protocol->is_old)(socket,ctl,num)) && !toolarge);
+ (!(protocol->is_old && (protocol->is_old)(sockfp,ctl,num)) && !toolarge);
/* we may want to reject this message if it's old */
if (!fetch_it)
else
{
/* request a message */
- (protocol->fetch)(socket, num, &len);
+ (protocol->fetch)(sockfp, num, &len);
+ vtalarm(ctl->timeout);
if (outlevel > O_SILENT)
{
}
/* read the message and ship it to the output sink */
- ok = gen_readmsg(socket,
+ ok = gen_readmsg(sockfp,
len,
protocol->delimited,
ctl);
+ vtalarm(ctl->timeout);
if (ok != 0)
goto cleanUp;
/* tell the server we got it OK and resynchronize */
if (protocol->trail)
- (protocol->trail)(socket, ctl, num);
+ (protocol->trail)(sockfp, ctl, num);
}
/*
deletions++;
if (outlevel > O_SILENT)
fprintf(stderr, " flushed\n");
- ok = (protocol->delete)(socket, ctl, num);
+ ok = (protocol->delete)(sockfp, ctl, num);
+ vtalarm(ctl->timeout);
if (ok != 0)
goto cleanUp;
}
/* remove all messages flagged for deletion */
if (protocol->expunge_cmd && deletions > 0)
{
- ok = gen_transact(socket, protocol->expunge_cmd);
+ ok = gen_transact(sockfp, protocol->expunge_cmd);
if (ok != 0)
goto cleanUp;
}
- ok = gen_transact(socket, protocol->exit_cmd);
+ ok = gen_transact(sockfp, protocol->exit_cmd);
if (ok == 0)
ok = PS_SUCCESS;
- close(socket);
+ fclose(sockfp);
goto closeUp;
}
else {
- ok = gen_transact(socket, protocol->exit_cmd);
+ ok = gen_transact(sockfp, protocol->exit_cmd);
if (ok == 0)
ok = PS_NOMAIL;
- close(socket);
+ fclose(sockfp);
goto closeUp;
}
cleanUp:
if (ok != 0 && ok != PS_SOCKET)
{
- gen_transact(socket, protocol->exit_cmd);
- close(socket);
+ gen_transact(sockfp, protocol->exit_cmd);
+ fclose(sockfp);
}
}
- alarm(0);
- signal(SIGALRM, sigsave);
+ signal(SIGVTALRM, sigsave);
closeUp:
return(ok);
}
-void smtp_close(mboxfd)
-/* close the current SMTP connection */
-int mboxfd;
-{
- if (mboxfd != -1)
- {
- close(mboxfd);
- }
-}
#if defined(HAVE_STDARG_H)
-void gen_send(int socket, char *fmt, ... )
+void gen_send(FILE *sockfp, char *fmt, ... )
/* assemble command in printf(3) style and send to the server */
{
#else
-void gen_send(socket, fmt, va_alist)
+void gen_send(sockfp, fmt, va_alist)
/* assemble command in printf(3) style and send to the server */
-int socket; /* socket to which server is connected */
+FILE *sockfp; /* socket to which server is connected */
const char *fmt; /* printf-style format */
va_dcl {
#endif
vsprintf(buf + strlen(buf), fmt, ap);
va_end(ap);
- SockPuts(socket, buf);
+ strcat(buf, "\r\n");
+ SockWrite(buf, strlen(buf), sockfp);
if (outlevel == O_VERBOSE)
{
if (shroud && (cp = strstr(buf, shroud)))
memset(cp, '*', strlen(shroud));
- fprintf(stderr,"> %s\n", buf);
+ fprintf(stderr,"> %s", buf);
}
}
#if defined(HAVE_STDARG_H)
-int gen_transact(int socket, char *fmt, ... )
+int gen_transact(FILE *sockfp, char *fmt, ... )
/* assemble command in printf(3) style, send to server, accept a response */
{
#else
-int gen_transact(socket, fmt, va_alist)
+int gen_transact(sockfp, fmt, va_alist)
/* assemble command in printf(3) style, send to server, accept a response */
-int socket; /* socket to which server is connected */
+FILE *sockfp; /* socket to which server is connected */
const char *fmt; /* printf-style format */
va_dcl {
#endif
vsprintf(buf + strlen(buf), fmt, ap);
va_end(ap);
- SockPuts(socket, buf);
+ strcat(buf, "\r\n");
+ SockWrite(buf, strlen(buf), sockfp);
if (outlevel == O_VERBOSE)
{
char *cp;
if (shroud && (cp = strstr(buf, shroud)))
memset(cp, '*', strlen(shroud));
- fprintf(stderr,"> %s\n", buf);
+ fprintf(stderr,"> %s", buf);
}
/* we presume this does its own response echoing */
- ok = (protocol->parse_response)(socket, buf);
+ ok = (protocol->parse_response)(sockfp, buf);
+ vtalarm(mytimeout);
return(ok);
}