#if defined(HAVE_ALLOCA_H)
#include <alloca.h>
#endif
+#if defined(HAVE_SYS_ITIMER_H)
+#include <sys/itimer.h>
+#endif
#include <sys/time.h>
#include <signal.h>
extern char *strstr(); /* needed on sysV68 R3V7.1. */
-int batchlimit; /* how often to tear down the delivery connection */
int fetchlimit; /* how often to tear down the server connection */
int batchcount; /* count of messages sent in current batch */
int peek_capable; /* can we peek for better error recovery? */
return(TRUE);
else if (strcmp(name, ctl->server.canonical_name) == 0)
return(TRUE);
- else if (ctl->server.no_dns)
+ else if (!ctl->server.dns)
return(FALSE);
/*
"nameserver failure while looking for `%s' during poll of %s.",
name, ctl->server.names->id);
ctl->errcount++;
- longjmp(restart, 2); /* try again next poll cycle */
break;
}
"nameserver failure while looking for `%s' during poll of %s.",
name, ctl->server.names->id);
ctl->errcount++;
- longjmp(restart, 2); /* try again next poll cycle */
break;
}
}
}
char *parse_received(struct query *ctl, char *bufp)
-/* try to extract */
+/* try to extract real addressee from the Received line */
{
char *ok;
static char rbuf[HOSTLEN + USERNAMELEN + 4];
char *sp, *tp;
/* extract space-delimited token after "by " */
+ for (sp = ok + 3; isspace(*sp); sp++)
+ continue;
tp = rbuf;
- for (sp = ok + 3; !isspace(*sp); sp++)
+ for (; !isspace(*sp); sp++)
*tp++ = *sp;
*tp = '\0';
static FILE *smtp_open(struct query *ctl)
/* try to open a socket to the appropriate SMTP server for this query */
{
- struct query *lead;
-
- lead = ctl->lead_smtp; /* go to the SMTP leader for this query */
+ struct idlist *idp;
/* maybe it's time to close the socket in order to force delivery */
- if (batchlimit && lead->smtp_sockfp && batchcount++ == batchlimit)
+ if (ctl->batchlimit && ctl->smtp_sockfp && batchcount++ == ctl->batchlimit)
{
- fclose(lead->smtp_sockfp);
- lead->smtp_sockfp = (FILE *)NULL;
+ fclose(ctl->smtp_sockfp);
+ ctl->smtp_sockfp = (FILE *)NULL;
batchcount = 0;
}
- /*
- * RFC 1123 requires that the domain name in HELO address is a
- * "valid principal domain name" for the client host. We
- * violate this with malice aforethought in order to make the
- * Received headers and logging look right.
- *
- * In fact this code relies on the RFC1123 requirement that the
- * SMTP listener must accept messages even if verification of the
- * HELO name fails (RFC1123 section 5.2.5, paragraph 2).
- */
-
- /* if no socket to this host is already set up, try to open ESMTP */
- if (lead->smtp_sockfp == (FILE *)NULL)
+ /* run down the SMTP hunt list looking for a server that's up */
+ for (idp = ctl->smtphunt; idp; idp = idp->next)
{
- if ((lead->smtp_sockfp = SockOpen(lead->smtphost, SMTP_PORT)) == (FILE *)NULL)
- return((FILE *)NULL);
- else if (SMTP_ok(lead->smtp_sockfp) != SM_OK
- || SMTP_ehlo(lead->smtp_sockfp,
- ctl->server.names->id,
- &lead->server.esmtp_options) != SM_OK)
+
+ /*
+ * RFC 1123 requires that the domain name in HELO address is a
+ * "valid principal domain name" for the client host. We
+ * violate this with malice aforethought in order to make the
+ * Received headers and logging look right.
+ *
+ * In fact this code relies on the RFC1123 requirement that the
+ * SMTP listener must accept messages even if verification of the
+ * HELO name fails (RFC1123 section 5.2.5, paragraph 2).
+ */
+
+ /* if no socket to this host is already set up, try to open ESMTP */
+ if (ctl->smtp_sockfp == (FILE *)NULL)
{
- /*
- * RFC 1869 warns that some listeners hang up on a failed EHLO,
- * so it's safest not to assume the socket will still be good.
- */
- fclose(lead->smtp_sockfp);
- lead->smtp_sockfp = (FILE *)NULL;
+ if ((ctl->smtp_sockfp = SockOpen(idp->id,SMTP_PORT))==(FILE *)NULL)
+ return((FILE *)NULL);
+ else if (SMTP_ok(ctl->smtp_sockfp) != SM_OK
+ || SMTP_ehlo(ctl->smtp_sockfp,
+ ctl->server.names->id,
+ &ctl->server.esmtp_options) != SM_OK)
+ {
+ /*
+ * RFC 1869 warns that some listeners hang up on a failed EHLO,
+ * so it's safest not to assume the socket will still be good.
+ */
+ fclose(ctl->smtp_sockfp);
+ ctl->smtp_sockfp = (FILE *)NULL;
+ }
+ else
+ {
+ ctl->smtphost = idp->id;
+ break;
+ }
}
- }
- /* if opening for ESMTP failed, try SMTP */
- if (lead->smtp_sockfp == (FILE *)NULL)
- {
- if ((lead->smtp_sockfp = SockOpen(lead->smtphost, SMTP_PORT)) == (FILE *)NULL)
- return((FILE *)NULL);
- else if (SMTP_ok(lead->smtp_sockfp) != SM_OK
- || SMTP_helo(lead->smtp_sockfp, ctl->server.names->id) != SM_OK)
+ /* if opening for ESMTP failed, try SMTP */
+ if (ctl->smtp_sockfp == (FILE *)NULL)
{
- fclose(lead->smtp_sockfp);
- lead->smtp_sockfp = (FILE *)NULL;
+ if ((ctl->smtp_sockfp = SockOpen(idp->id,SMTP_PORT))==(FILE *)NULL)
+ return((FILE *)NULL);
+ else if (SMTP_ok(ctl->smtp_sockfp) != SM_OK
+ || SMTP_helo(ctl->smtp_sockfp, ctl->server.names->id) != SM_OK)
+ {
+ fclose(ctl->smtp_sockfp);
+ ctl->smtp_sockfp = (FILE *)NULL;
+ }
+ else
+ {
+ ctl->smtphost = idp->id;
+ break;
+ }
}
}
- return(lead->smtp_sockfp);
+ return(ctl->smtp_sockfp);
}
static int gen_readmsg(sockfp, len, delimited, ctl, realname)
{
char buf [MSGBUFSIZE+1];
int from_offs, to_offs, cc_offs, bcc_offs, ctt_offs, env_offs;
- char *headers, *received_for;
- int n, oldlen, ch, sizeticker, delete_ok;
+ char *headers, *received_for, *return_path;
+ int n, oldlen, ch, sizeticker, delete_ok, remaining;
FILE *sinkfp;
RETSIGTYPE (*sigchld)();
#ifdef HAVE_GETHOSTBYNAME
#ifdef HAVE_RES_SEARCH
int no_local_matches = FALSE;
#endif /* HAVE_RES_SEARCH */
+ int olderrs;
sizeticker = 0;
delete_ok = TRUE;
+ remaining = len;
+ olderrs = ctl->errcount;
/* read message headers */
- headers = received_for = NULL;
+ headers = received_for = return_path = NULL;
from_offs = to_offs = cc_offs = bcc_offs = ctt_offs = env_offs = -1;
oldlen = 0;
for (;;)
{
- char *bufp, *line;
+ char *line;
line = xmalloc(sizeof(buf));
line[0] = '\0';
/* leave extra room for reply_hack to play with */
line = realloc(line, strlen(line) + strlen(buf) + HOSTLEN + 1);
strcat(line, buf);
+ if (line[0] == '\r' && line[1] == '\n')
+ break;
} while
/* we may need to grab RFC822 continuations */
((ch = SockPeek(sockfp)) == ' ' || ch == '\t');
/* write the message size dots */
- if ((n = strlen(line)) > 0)
+ n = strlen(line);
+ if ((outlevel > O_SILENT && outlevel < O_VERBOSE) && n > 0)
{
sizeticker += n;
while (sizeticker >= SIZETICKER)
{
- if (outlevel > O_SILENT)
- error_build(".");
+ error_build(".");
sizeticker -= SIZETICKER;
}
}
- len -= n;
+ remaining -= n;
/* check for end of headers; don't save terminating line */
if (line[0] == '\r' && line[1] == '\n')
break;
}
- if (!ctl->no_rewrite)
+
+ /*
+ * OK, this is messy. If we're forwarding by SMTP, it's the
+ * SMTP-receiver's job (according to RFC821, page 22, section
+ * 4.1.1) to generate a Return-Path line on final delivery.
+ * The trouble is, we've already got one because the
+ * mailserver's SMTP thought *it* was responsible for final
+ * delivery.
+ *
+ * Stash away the contents of Return-Path for use in generating
+ * MAIL FROM later on, then prevent the header from being saved
+ * with the others. In effect, we strip it off here.
+ *
+ * If the SMTP server conforms to the standards, and fetchmail gets the
+ * envelope sender from the Return-Path, the new Return-Path should be
+ * exactly the same as the original one.
+ */
+ if (!ctl->mda && !strncasecmp("Return-Path:", line, 12))
+ {
+ return_path = xstrdup(nxtaddr(line));
+ continue;
+ }
+
+ if (ctl->rewrite)
reply_hack(line, realname);
- bufp = line;
if (!headers)
{
- oldlen = strlen(bufp);
+ oldlen = strlen(line);
headers = xmalloc(oldlen + 1);
- (void) strcpy(headers, bufp);
- bufp = headers;
+ (void) strcpy(headers, line);
+ free(line);
+ line = headers;
}
else
{
int newlen;
- newlen = oldlen + strlen(bufp);
+ newlen = oldlen + strlen(line);
headers = realloc(headers, newlen + 1);
if (headers == NULL)
return(PS_IOERR);
- strcpy(headers + oldlen, bufp);
- bufp = headers + oldlen;
+ strcpy(headers + oldlen, line);
+ free(line);
+ line = headers + oldlen;
oldlen = newlen;
}
- free(line);
- if (from_offs == -1 && !strncasecmp("From:", bufp, 5))
- from_offs = (bufp - headers);
- else if (from_offs == -1 && !strncasecmp("Resent-From:", bufp, 12))
- from_offs = (bufp - headers);
- else if (from_offs == -1 && !strncasecmp("Apparently-From:", bufp, 16))
- from_offs = (bufp - headers);
+ if (from_offs == -1 && !strncasecmp("From:", line, 5))
+ from_offs = (line - headers);
+ else if (from_offs == -1 && !strncasecmp("Resent-From:", line, 12))
+ from_offs = (line - headers);
+ else if (from_offs == -1 && !strncasecmp("Apparently-From:", line, 16))
+ from_offs = (line - headers);
- else if (!strncasecmp("To:", bufp, 3))
- to_offs = (bufp - headers);
+ else if (!strncasecmp("To:", line, 3))
+ to_offs = (line - headers);
- else if (env_offs == -1 && !strncasecmp(ctl->server.envelope,
- bufp,
+ else if (ctl->server.envelope != STRING_DISABLED && env_offs == -1
+ && !strncasecmp(ctl->server.envelope,
+ line,
strlen(ctl->server.envelope)))
- env_offs = (bufp - headers);
+ env_offs = (line - headers);
- else if (!strncasecmp("Cc:", bufp, 3))
- cc_offs = (bufp - headers);
+ else if (!strncasecmp("Cc:", line, 3))
+ cc_offs = (line - headers);
- else if (!strncasecmp("Bcc:", bufp, 4))
- bcc_offs = (bufp - headers);
+ else if (!strncasecmp("Bcc:", line, 4))
+ bcc_offs = (line - headers);
- else if (!strncasecmp("Content-Transfer-Encoding:", bufp, 26))
- ctt_offs = (bufp - headers);
+ else if (!strncasecmp("Content-Transfer-Encoding:", line, 26))
+ ctt_offs = (line - headers);
#ifdef HAVE_RES_SEARCH
- else if (MULTIDROP(ctl) && !strncasecmp("Received:", bufp, 9))
- received_for = parse_received(ctl, bufp);
+ else if (ctl->server.envelope != STRING_DISABLED && MULTIDROP(ctl) && !received_for && !strncasecmp("Received:", line, 9))
+ received_for = parse_received(ctl, line);
#endif /* HAVE_RES_SEARCH */
}
+ /*
+ * Hack time. If the first line of the message was blank, with no headers
+ * (this happens occasionally due to bad gatewaying software) cons up
+ * a set of fake headers.
+ *
+ * If you modify the fake header template below, be sure you don't
+ * make either From or To address @-less, otherwise the reply_hack
+ * logic will do bad things.
+ */
+ if (headers == (char *)NULL)
+ {
+ sprintf(buf,
+ "From: <FETCHMAIL-DAEMON@%s>\r\nTo: %s@localhost\r\nSubject: Headerless mail from %s's mailbox on %s\r\n",
+ fetchmailhost, user, ctl->remotename, realname);
+ headers = xstrdup(buf);
+ }
+
/*
* We can now process message headers before reading the text.
* In fact we have to, as this will tell us where to forward to.
#endif /* HAVE_RES_SEARCH */
save_str(&xmit_names, -1, ctl->localnames->id);
- /* time to address the message */
- if (ctl->mda) /* we have a declared MDA */
+
+ /*
+ * Time to either address the message or decide we can't deliver it yet.
+ */
+ if (ctl->errcount > olderrs) /* there were DNS errors above */
+ {
+ delete_ok = FALSE;
+ sinkfp = (FILE *)NULL;
+ if (outlevel == O_VERBOSE)
+ error(0,0, "forwarding and deletion suppressed due to DNS errors");
+ }
+ else if (ctl->mda) /* we have a declared MDA */
{
int length = 0;
char *names, *cmd;
if (!ctl->mda && ((sinkfp = smtp_open(ctl)) == NULL))
{
free_str_list(&xmit_names);
- error(0, 0, "SMTP connect failed");
+ error(0, 0, "SMTP connect to %s failed", ctl->smtphost);
+ if (return_path)
+ free(return_path);
return(PS_SMTP);
}
sprintf(options + strlen(options), " SIZE=%d", len);
/*
- * Try to get the SMTP listener to take the header
- * From address as MAIL FROM (this makes the logging
- * nicer). If it won't, fall back on the calling-user
- * ID. This won't affect replies, which use the header
- * From address anyway.
+ * If there is a Return-Path address on the message, this was
+ * almost certainly the MAIL FROM address given the originating
+ * sendmail. This is the best thing to use for logging the
+ * message origin (it sets up the right behavior for bounces and
+ * mailing lists). Otherwise, take the From address.
+ *
+ * Try to get the SMTP listener to take the Return-Path or
+ * From address as MAIL FROM . If it won't, fall back on the
+ * calling-user ID. This won't affect replies, which use the
+ * header From address anyway.
*
* RFC 1123 requires that the domain name part of the
* MAIL FROM address be "canonicalized", that is a
* is if rewrite is on). RFC 1123 is silent on whether
* a nonexistent hostname part is considered canonical.
*
- * This is a potential problem if the MTAs further
- * upstream didn't pass canonicalized From lines, *and*
- * the local SMTP listener insists on them.
+ * This is a potential problem if the MTAs further upstream
+ * didn't pass canonicalized From/Return-Path lines, *and* the
+ * local SMTP listener insists on them.
*/
- if (from_offs == -1 || !(ap = nxtaddr(headers + from_offs)))
+ ap = (char *)NULL;
+ if (return_path)
+ ap = return_path;
+ else if (from_offs == -1 || !(ap = nxtaddr(headers + from_offs)))
ap = user;
if (SMTP_from(sinkfp, ap, options) != SM_OK)
{
error(0, 0, "SMTP error: %s", smtp_response);
/*
- * There'a one problem with this flow of control;
+ * There's one problem with this flow of control;
* there's no way to avoid reading the whole message
* off the server, even if the MAIL FROM response
* tells us that it's just to be discarded. We could
if (SMTP_from(sinkfp, user, options) != SM_OK)
{
error(0,0,"SMTP error: %s", smtp_response);
+ if (return_path)
+ free(return_path);
return(PS_SMTP); /* should never happen */
}
}
{
error(0, 0,
"can't even send to calling user!");
+ if (return_path)
+ free(return_path);
return(PS_SMTP);
}
SMTP_data(sinkfp);
skiptext:;
+ if (return_path)
+ free(return_path);
}
- /* write all the headers */
- if (ctl->mda)
- n = fwrite(headers, 1, oldlen, sinkfp);
- else if (sinkfp)
- n = SockWrite(headers, 1, oldlen, sinkfp);
+ /* we may need to strip carriage returns */
+ if (ctl->stripcr)
+ {
+ char *sp, *tp;
+
+ for (sp = tp = headers; *sp; sp++)
+ if (*sp != '\r')
+ *tp++ = *sp;
+ *tp = '\0';
+
+ }
- if (n < 0)
+ /* write all the headers */
+ if (sinkfp)
{
- free(headers);
- headers = NULL;
- error(0, errno, "writing RFC822 headers");
if (ctl->mda)
+ n = fwrite(headers, 1, strlen(headers), sinkfp);
+ else
+ n = SockWrite(headers, 1, strlen(headers), sinkfp);
+
+ if (n < 0)
{
- pclose(sinkfp);
- signal(SIGCHLD, sigchld);
+ free(headers);
+ headers = NULL;
+ error(0, errno, "writing RFC822 headers");
+ if (ctl->mda)
+ {
+ pclose(sinkfp);
+ signal(SIGCHLD, sigchld);
+ }
+ return(PS_IOERR);
}
- return(PS_IOERR);
+ else if (outlevel == O_VERBOSE)
+ fputs("#", stderr);
}
- else if (outlevel == O_VERBOSE)
- fputs("#", stderr);
free(headers);
headers = NULL;
strcat(errmsg, "\n");
+ /* we may need to strip carriage returns */
+ if (ctl->stripcr)
+ {
+ char *sp, *tp;
+
+ for (sp = tp = errmsg; *sp; sp++)
+ if (*sp != '\r')
+ *tp++ = *sp;
+ *tp = '\0';
+ }
+
/* ship out the error line */
- if (ctl->mda)
- fwrite(errmsg, 1, strlen(errmsg), sinkfp);
- else if (sinkfp)
- SockWrite(errmsg, 1, strlen(errmsg), sinkfp);
+ if (sinkfp)
+ {
+ if (ctl->mda)
+ fwrite(errmsg, 1, strlen(errmsg), sinkfp);
+ else
+ SockWrite(errmsg, 1, strlen(errmsg), sinkfp);
+ }
}
free_str_list(&xmit_names);
/* issue the delimiter line */
- if (ctl->mda)
- fputs("\r\n", sinkfp);
- else if (sinkfp)
- SockWrite("\r\n", 1, 2, sinkfp);
+ if (sinkfp)
+ {
+ if (ctl->mda)
+ fputc('\n', sinkfp);
+ else
+ SockWrite("\r\n", 1, 2, sinkfp);
+ }
/*
* Body processing starts here
*/
/* pass through the text lines */
- while (delimited || len > 0)
+ while (delimited || remaining > 0)
{
if (!SockGets(buf, sizeof(buf)-1, sockfp))
return(PS_SOCKET);
sizeticker -= SIZETICKER;
}
}
- len -= n;
+ remaining -= n;
/* check for end of message */
if (delimited && *buf == '.')
if (buf[1] == '\r' && buf[2] == '\n')
break;
- /* SMTP byte-stuffing */
- if (*buf == '.')
- if (ctl->mda)
- fputs(".", sinkfp);
- else if (sinkfp)
- SockWrite(buf, 1, 1, sinkfp);
-
/* ship out the text line */
- if (ctl->mda)
- n = fwrite(buf, 1, strlen(buf), sinkfp);
- else if (sinkfp)
- n = SockWrite(buf, 1, strlen(buf), sinkfp);
-
- if (n < 0)
+ if (sinkfp)
{
- error(0, errno, "writing message text");
+ /* SMTP byte-stuffing */
+ if (*buf == '.')
+ if (ctl->mda)
+ fputs(".", sinkfp);
+ else
+ SockWrite(buf, 1, 1, sinkfp);
+
+ /* we may need to strip carriage returns */
+ if (ctl->stripcr)
+ {
+ char *sp, *tp;
+
+ for (sp = tp = buf; *sp; sp++)
+ if (*sp != '\r')
+ *tp++ = *sp;
+ *tp = '\0';
+ }
+
+ /* ship the text line */
if (ctl->mda)
+ n = fwrite(buf, 1, strlen(buf), sinkfp);
+ else if (sinkfp)
+ n = SockWrite(buf, 1, strlen(buf), sinkfp);
+
+ if (n < 0)
{
- pclose(sinkfp);
- signal(SIGCHLD, sigchld);
+ error(0, errno, "writing message text");
+ if (ctl->mda)
+ {
+ pclose(sinkfp);
+ signal(SIGCHLD, sigchld);
+ }
+ return(PS_IOERR);
}
- return(PS_IOERR);
+ else if (outlevel == O_VERBOSE)
+ fputc('*', stderr);
}
- else if (outlevel == O_VERBOSE)
- fputc('*', stderr);
}
/*
if (SMTP_eom(sinkfp) != SM_OK)
{
error(0, 0, "SMTP listener refused delivery");
+ ctl->errcount++;
return(PS_TRANSIENT);
}
}
ctl->server.timeout, ctl->server.names->id);
ok = PS_ERROR;
}
- else if (js == 2)
- {
- /* error message printed at point of longjmp */
- ok = PS_ERROR;
- }
else
{
char buf [POPBUFSIZE+1];
#ifndef EHOSTUNREACH
#define EHOSTUNREACH (-1)
#endif
- if (errno != EHOSTUNREACH)
+ if (outlevel == O_VERBOSE || errno != EHOSTUNREACH)
error(0, errno, "connecting to host");
ok = PS_SOCKET;
goto closeUp;
}
#ifdef KERBEROS_V4
- if (ctl->authenticate == A_KERBEROS)
+ if (ctl->server.authenticate == A_KERBEROS)
{
ok = kerberos_auth(fileno(sockfp), ctl->server.canonical_name);
if (ok != 0)
strcpy(realname, ctl->server.names->id);
/* try to get authorized to fetch mail */
- shroud = ctl->password;
- ok = (protocol->getauth)(sockfp, ctl, buf);
- shroud = (char *)NULL;
- if (ok == PS_ERROR)
- ok = PS_AUTHFAIL;
- if (ok != 0)
+ if (protocol->getauth)
{
- error(0, 0, "Authorization failure on %s@%s",
- ctl->remotename,
- realname);
- goto cleanUp;
+ shroud = ctl->password;
+ ok = (protocol->getauth)(sockfp, ctl, buf);
+ shroud = (char *)NULL;
+ if (ok == PS_ERROR)
+ ok = PS_AUTHFAIL;
+ if (ok != 0)
+ {
+ error(0, 0, "Authorization failure on %s@%s",
+ ctl->remotename,
+ realname);
+ goto cleanUp;
+ }
+ vtalarm(ctl->server.timeout);
}
- vtalarm(ctl->server.timeout);
/* compute number of messages and number of new messages waiting */
ok = (protocol->getrange)(sockfp, ctl, &count, &new);
/* show user how many messages we downloaded */
if (outlevel > O_SILENT)
- if (count == 0)
- error(0, 0, "No mail from %s@%s",
+ if (count == -1) /* only used for ETRN */
+ error(0, 0, "Polling %s@%s",
+ ctl->remotename,
+ realname);
+ else if (count == 0)
+ error(0, 0, "No mail at %s@%s",
ctl->remotename,
realname);
else
{
if (new != -1 && (count - new) > 0)
- error(0, 0, "%d message%s (%d seen) from %s@%s.",
+ error(0, 0, "%d message%s (%d seen) at %s@%s.",
count, count > 1 ? "s" : "", count-new,
ctl->remotename,
realname);
else
- error(0, 0, "%d message%s from %s@%s.", count, count > 1 ? "s" : "",
+ error(0, 0, "%d message%s at %s@%s.",
+ count, count > 1 ? "s" : "",
ctl->remotename,
realname);
}
}
else if (count > 0)
{
+ int force_retrieval, fetches;
+
/*
* What forces this code is that in POP3 and IMAP2BIS you can't
* fetch a message without having it marked `seen'. In IMAP4,
* previous pass and forcing all messages to be considered new
* if it's nonzero.
*/
- int force_retrieval = !peek_capable && (ctl->errcount > 0);
+ force_retrieval = !peek_capable && (ctl->errcount > 0);
- ctl->errcount = 0;
+ ctl->errcount = fetches = 0;
/* read, forward, and delete messages */
for (num = 1; num <= count; num++)
goto cleanUp;
vtalarm(ctl->server.timeout);
}
+
+ fetches++;
}
/*
error_complete(0, 0, " not flushed");
/* perhaps this as many as we're ready to handle */
- if (ctl->fetchlimit && ctl->fetchlimit <= num)
+ if (ctl->fetchlimit && ctl->fetchlimit <= fetches)
break;
}
{
char *cp;
- if (shroud && (cp = strstr(buf, shroud)))
- memset(cp, '*', strlen(shroud));
- buf[strlen(buf)-1] = '\0';
+ if (shroud && shroud[0] && (cp = strstr(buf, shroud)))
+ {
+ char *sp;
+
+ sp = cp + strlen(shroud);
+ *cp++ = '*';
+ while (*sp)
+ *cp++ = *sp++;
+ *cp = '\0';
+ }
+ buf[strlen(buf)-2] = '\0';
error(0, 0, "%s> %s", protocol->name, buf);
}
}
{
char *cp;
- if (shroud && (cp = strstr(buf, shroud)))
- memset(cp, '*', strlen(shroud));
+ if (shroud && shroud[0] && (cp = strstr(buf, shroud)))
+ {
+ char *sp;
+
+ sp = cp + strlen(shroud);
+ *cp++ = '*';
+ while (*sp)
+ *cp++ = *sp++;
+ *cp = '\0';
+ }
buf[strlen(buf)-1] = '\0';
error(0, 0, "%s> %s", protocol->name, buf);
}
}
/* driver.c ends here */
+