aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS26
-rw-r--r--fetchmail.c24
-rw-r--r--fetchmail.man7
-rw-r--r--options.c63
4 files changed, 92 insertions, 28 deletions
diff --git a/NEWS b/NEWS
index c8225328..5bbe62b4 100644
--- a/NEWS
+++ b/NEWS
@@ -10,6 +10,24 @@
fetchmail-4.4.8 ():
* Removed fetchall side-effect kluge, now that we knowe how to make TOP work
with qpopper 2.3+.
+* Several fixes for command-line processing from Gunther Leber:
+ - in fetchmail.c
+ * set tmpbuf to NULL after freeing the buffer (so this will hopefully
+ cause a coredump, when tmpbuf is used somewhere else)
+ * when makeing sure we have a nonempty host list to forward to, I
+ added "localhost" for non ETRN protocols. This should relieve the
+ situation for people, who do neither have a static ip-address
+ (hostname) assigned and neither bother to set up a dummy-interface
+ for their hostname. I think this feature was already in fetchmail
+ in an older version. We lost this, when we changed the code that it
+ would work with ETRN. My fix here works for both ETRN and non ETRN.
+ - fixed reversed dumping of mimedecode option
+ - in options.c
+ * changed char buf[...] to *buf + xmalloc to avoid buffer overuns and
+ possible resulting (and annoying) coredumps
+ * in parsecmdline(): replaced atoi by xatoi which uses strtol and
+ better validity checks for input numbers. This fix only works on
+ ANSI-C systems; old systems still use atoi.
fetchmail-4.4.7 (Sat May 23 08:26:58 EDT 1998):
* FEATURE FREEZE IS NOW IN EFFECT! No new features until after 4.5.0.
@@ -116,29 +134,21 @@ There are 269 people on fetchmail-friends and 144 on fetchmail-announce.
fetchmail-4.3.7 (Tue Feb 17 21:30:26 EST 1998)
* Fixed a minor bug in the IMAP re-polling logic.
* Nicholas Pitre's extensive changes to multidrop:
-
- Seek for the true sender of a mail which is not necessarily in the
From: header. (see comments in the code for more explicit details).
This one is particularly important with list distributions...
-
- Respect the Resent-To/-Cc/-Bcc precedence over the To/Cc/Bcc headers
for recipient delivery. So avoid resending a message to a person who
just resent a mail to some other addresses.
-
- Fix a bug in find_server_names() wich caused recipient addresses to
figure twice in the recipient address list.
-
- Modified parse_received() to let full adress from the Received header to
pass through so local domains can be used (now has same policy as in
the find_server_names() function).
-
- Fixed memory leaks from readheaders().
-
- Made some strcmp() be strcasecmp() as it should be because it didn't
work correctly in some cases.
-
- Modified reply_hack() to meet the needs of above modifications.
-
Thomas says these changes have been tested for two weeks in a production
multidrop environment. I tested them for another week in mine.
* Doug Muth's runfetchmail version 1.1.
diff --git a/fetchmail.c b/fetchmail.c
index ddfdb309..5e3e28ac 100644
--- a/fetchmail.c
+++ b/fetchmail.c
@@ -373,6 +373,7 @@ int main (int argc, char **argv)
/* we don't need tmpbuf anymore */
free(tmpbuf);
+ tmpbuf = NULL; /* firewall code */
/*
* Maybe time to go to demon mode...
@@ -755,7 +756,15 @@ static int load_params(int argc, char **argv, int optind)
/* make sure we have a nonempty host list to forward to */
if (!ctl->smtphunt)
+ {
save_str(&ctl->smtphunt, fetchmailhost, FALSE);
+ /* for non ETRN try to deliver mails to localhost if
+ * fetchmailhost fails
+ */
+ if (ctl->server.protocol != P_ETRN) {
+ save_str(&ctl->smtphunt, "localhost", FALSE);
+ }
+ }
/* keep lusers from shooting themselves in the foot :-) */
if (run.poll_interval && ctl->limit)
@@ -1131,10 +1140,10 @@ void dump_params (struct runctl *runp, struct query *querylist, flag implicit)
ctl->forcecr ? "en" : "dis",
ctl->forcecr ? "on" : "off");
printf(" Interpretation of Content-Transfer-Encoding is %sabled (pass8bits %s).\n",
- ctl->pass8bits ? "dis" : "en",
+ ctl->pass8bits ? "en" : "dis",
ctl->pass8bits ? "on" : "off");
printf(" MIME decoding is %sabled (mimedecode %s).\n",
- ctl->mimedecode ? "dis" : "en",
+ ctl->mimedecode ? "en" : "dis",
ctl->mimedecode ? "on" : "off");
printf(" Nonempty Status lines will be %s (dropstatus %s)\n",
ctl->dropstatus ? "discarded" : "kept",
@@ -1166,12 +1175,11 @@ void dump_params (struct runctl *runp, struct query *querylist, flag implicit)
printf(" Messages will be SMTP-forwarded to:");
for (idp = ctl->smtphunt; idp; idp = idp->next)
- if (ctl->server.protocol != P_ETRN || idp->val.status.mark)
- {
- printf(" %s", idp->id);
- if (!idp->val.status.mark)
- printf(" (default)");
- }
+ {
+ printf(" %s", idp->id);
+ if (!idp->val.status.mark)
+ printf(" (default)");
+ }
printf("\n");
if (ctl->smtpaddress)
printf(" Host part of MAIL FROM line will be %s\n",
diff --git a/fetchmail.man b/fetchmail.man
index 7c10341c..383ecc89 100644
--- a/fetchmail.man
+++ b/fetchmail.man
@@ -207,9 +207,10 @@ Specify a hunt list of hosts to forward mail to (one or more
hostnames, comma-separated). In ETRN mode, set the host that the
mailserver is asked to ship mail to. Hosts are tried in list order;
the first one that is up becomes the forwarding or ETRN target for the
-current run. Each hostname may have a '/'-delimited suffix specifying
-a port or service to forward to; the default is 25 (or "smtp" under
-IPv6).
+current run. In all modes except ETRN, `localhost' is added to the
+end of the list as an invisible default. Each hostname may have a
+'/'-delimited suffix specifying a port or service to forward to; the
+default is 25 (or "smtp" under IPv6).
.TP
.B \-D domain, --smtpaddress domain
(Keyword: smtpaddress)
diff --git a/options.c b/options.c
index 3a7465c9..92d24b24 100644
--- a/options.c
+++ b/options.c
@@ -9,8 +9,10 @@
#include <stdio.h>
#include <pwd.h>
#include <string.h>
+#include <errno.h>
#if defined(STDC_HEADERS)
#include <stdlib.h>
+#include <limits.h>
#endif
#include "getopt.h"
@@ -122,6 +124,45 @@ static const struct option longoptions[] = {
{(char *) 0, no_argument, (int *) 0, 0 }
};
+static int xatoi(char *s, int *errflagptr)
+/* do safe conversion from string to number */
+{
+#if defined (__STDC__)
+ /* parse and convert numbers, but also check for invalid characters in
+ * numbers
+ */
+
+ char *endptr;
+ long value;
+
+ errno = 0;
+
+ value = strtol(s, &endptr, 0);
+
+ /* any invalid chars in string? */
+ if ( (endptr == s) || (*endptr != '\0') ) {
+ (void) fprintf(stderr, "String '%s' is not a valid number string.\n", s);
+ (*errflagptr)++;
+ return 0;
+ }
+
+ /* is the range valid? */
+ if ( (((value == LONG_MAX) || (value == LONG_MIN)) && (errno == ERANGE)) ||
+ (value > INT_MAX) || (value < INT_MIN)) {
+
+ (void) fprintf(stderr, "Value of string '%s' is %s than %d.\n", s,
+ (value < 0) ? "smaller": "larger",
+ (value < 0) ? INT_MIN : INT_MAX);
+ (*errflagptr)++;
+ return 0;
+ }
+
+ return (int) value; /* shut up, I know what I'm doing */
+#else
+ return atoi(s);
+#endif
+}
+
int parsecmdline (argc, argv, rctl, ctl)
/* parse and validate the command line options */
int argc; /* argument count */
@@ -141,7 +182,7 @@ struct query *ctl; /* option record to be initialized */
int ocount = 0; /* count of destinations specified */
int errflag = 0; /* TRUE when a syntax error is detected */
int option_index;
- char buf[BUFSIZ], *cp;
+ char *buf, *cp;
rctl->poll_interval = -1;
@@ -171,7 +212,7 @@ struct query *ctl; /* option record to be initialized */
break;
case 'd':
case LA_DAEMON:
- rctl->poll_interval = atoi(optarg);
+ rctl->poll_interval = xatoi(optarg, &errflag);
break;
case 'N':
case LA_NODETACH:
@@ -245,7 +286,7 @@ struct query *ctl; /* option record to be initialized */
#if INET6
ctl->server.service = optarg;
#else /* INET6 */
- ctl->server.port = atoi(optarg);
+ ctl->server.port = xatoi(optarg, &errflag);
#endif /* INET6 */
break;
case 'A':
@@ -269,7 +310,7 @@ struct query *ctl; /* option record to be initialized */
break;
case 't':
case LA_TIMEOUT:
- ctl->server.timeout = atoi(optarg);
+ ctl->server.timeout = xatoi(optarg, &errflag);
if (ctl->server.timeout == 0)
ctl->server.timeout = -1;
break;
@@ -308,20 +349,23 @@ struct query *ctl; /* option record to be initialized */
break;
case 'l':
case LA_LIMIT:
- c = atoi(optarg);
+ c = xatoi(optarg, &errflag);
ctl->limit = NUM_VALUE(c);
break;
case 'r':
case LA_FOLDER:
+ buf = xmalloc(strlen(optarg));
strcpy(buf, optarg);
cp = strtok(buf, ",");
do {
save_str(&ctl->mailboxes, cp, 0);
} while
((cp = strtok((char *)NULL, ",")));
+ free(buf);
break;
case 'S':
case LA_SMTPHOST:
+ buf = xmalloc(strlen(optarg));
strcpy(buf, optarg);
cp = strtok(buf, ",");
do {
@@ -329,6 +373,7 @@ struct query *ctl; /* option record to be initialized */
} while
((cp = strtok((char *)NULL, ",")));
ocount++;
+ free(buf);
break;
case 'D':
case LA_SMTPADDR:
@@ -336,21 +381,21 @@ struct query *ctl; /* option record to be initialized */
break;
case 'Z':
case LA_ANTISPAM:
- c = atoi(optarg);
+ c = xatoi(optarg, &errflag);
ctl->antispam = NUM_VALUE(c);
case 'b':
case LA_BATCHLIMIT:
- c = atoi(optarg);
+ c = xatoi(optarg, &errflag);
ctl->batchlimit = NUM_VALUE(c);
break;
case 'B':
case LA_FETCHLIMIT:
- c = atoi(optarg);
+ c = xatoi(optarg, &errflag);
ctl->fetchlimit = NUM_VALUE(c);
break;
case 'e':
case LA_EXPUNGE:
- c = atoi(optarg);
+ c = xatoi(optarg, &errflag);
ctl->expunge = NUM_VALUE(c);
break;
case 'm':