#include "smtp.h"
#include "netrc.h"
#include "i18n.h"
+#include "lock.h"
+
+/* need these (and sys/types.h) for res_init() */
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
#ifndef ENETUNREACH
#define ENETUNREACH 128 /* Interactive doesn't know this */
static void printcopyright(FILE *fp) {
fprintf(fp, GT_("Copyright (C) 2002, 2003 Eric S. Raymond\n"
- "Copyright (C) 2004 Matthias Andree, Eric S. Raymond, Rob F. Funk, Graham Wilson\n"
- "Copyright (C) 2005 Matthias Andree, Sunil Shetye\n"
- "Copyright (C) 2006 Matthias Andree\n"));
+ "Copyright (C) 2004 Matthias Andree, Eric S. Raymond, Robert M. Funk, Graham Wilson\n"
+ "Copyright (C) 2005 - 2006 Sunil Shetye\n"
+ "Copyright (C) 2005 - 2009 Matthias Andree\n"
+ ));
fprintf(fp, GT_("Fetchmail comes with ABSOLUTELY NO WARRANTY. This is free software, and you\n"
"are welcome to redistribute it under certain conditions. For details,\n"
"please see the file COPYING in the source or documentation directory.\n"));
* call near the beginning of the polling loop for details). We want
* to be sure the lock gets nuked on any error exit, basically.
*/
- lock_dispose();
+ fm_lock_dispose();
#ifdef HAVE_GETCWD
/* save the current directory */
"-IMAP"
#endif /* IMAP_ENABLE */
#ifdef GSSAPI
- "+IMAP-GSS"
+ "+GSS"
#endif /* GSSAPI */
#ifdef RPA_ENABLE
"+RPA"
#ifdef ENABLE_NLS
"+NLS"
#endif /* ENABLE_NLS */
+#ifdef KERBEROS_V4
+ "+KRB4"
+#endif /* KERBEROS_V4 */
+#ifdef KERBEROS_V5
+ "+KRB5"
+#endif /* KERBEROS_V5 */
+#ifndef HAVE_RES_SEARCH
+ "-DNS"
+#endif
".\n";
printf(GT_("This is fetchmail release %s"), VERSION);
fputs(features, stdout);
fflush(stdout);
/* this is an attempt to help remote debugging */
- system("uname -a");
+ if (system("uname -a")) { /* NOOP to quench GCC complaint */ }
}
/* avoid parsing the config file if all we're doing is killing a daemon */
if (!quitonly)
implicitmode = load_params(argc, argv, optind);
+ /* precedence: logfile (if effective) overrides syslog. */
+ if (run.logfile && run.poll_interval && !nodetach) {
+ run.use_syslog = 0;
+ }
+
#if defined(HAVE_SYSLOG)
/* logging should be set up early in case we were restarted from exec */
if (run.use_syslog)
#endif
report_init((run.poll_interval == 0 || nodetach) && !run.logfile);
+#ifdef POP3_ENABLE
+ /* initialize UID handling */
+ {
+ int st;
+
+ if (!versioninfo && (st = prc_filecheck(run.idfile, !versioninfo)) != 0)
+ exit(st);
+ else
+ initialize_saved_lists(querylist, run.idfile);
+ }
+#endif /* POP3_ENABLE */
+
/* construct the lockfile */
- lock_setup();
+ fm_lock_setup(&run);
#ifdef HAVE_SETRLIMIT
/*
}
}
+ free_netrc(netrc_list);
+ netrc_list = 0;
+
/* perhaps we just want to check options? */
if (versioninfo)
{
}
/* check for another fetchmail running concurrently */
- pid = lock_state();
+ pid = fm_lock_state();
bkgd = (pid < 0);
pid = bkgd ? -pid : pid;
}
else if (getpid() == pid)
/* this test enables re-execing on a changed rcfile */
- lock_assert();
+ fm_lock_assert();
else if (argc > 1)
{
fprintf(stderr,
const char* password_prompt = GT_("Enter password for %s@%s: ");
size_t pplen = strlen(password_prompt) + strlen(ctl->remotename) + strlen(ctl->server.pollname) + 1;
- tmpbuf = xmalloc(pplen);
+ tmpbuf = (char *)xmalloc(pplen);
snprintf(tmpbuf, pplen, password_prompt,
ctl->remotename, ctl->server.pollname);
ctl->password = xstrdup((char *)fm_getpassword(tmpbuf));
/* avoid zombies from plugins */
deal_with_sigchld();
+ /* Fix up log destination - if the if() is true, the precedence rule
+ * above hasn't killed off the syslog option, because the logfile
+ * option is ineffective (because we're not detached or not in
+ * deamon mode), so kill it for the benefit of other parts of the
+ * code. */
+ if (run.logfile && run.use_syslog)
+ run.logfile = 0;
+
/*
* Maybe time to go to demon mode...
*/
if (run.poll_interval)
{
- if (!nodetach)
- daemonize(run.logfile, terminate_run);
+ if (!nodetach) {
+ int rc;
+
+ rc = daemonize(run.logfile);
+ if (rc) {
+ report(stderr, GT_("fetchmail: Cannot detach into background. Aborting.\n"));
+ exit(rc);
+ }
+ }
report(stdout, GT_("starting fetchmail %s daemon \n"), VERSION);
/*
}
else
{
+ /* not in daemon mode */
if (run.logfile && !nodetach && access(run.logfile, F_OK) == 0)
{
if (!freopen(run.logfile, "a", stdout))
report(stderr, GT_("could not open %s to append logs to \n"), run.logfile);
if (!freopen(run.logfile, "a", stderr))
report(stdout, GT_("could not open %s to append logs to \n"), run.logfile);
+ if (run.use_syslog)
+ report(stdout, GT_("fetchmail: Warning: syslog and logfile are set. Check both for logs!\n"));
}
}
set_signal_handler(SIGINT, terminate_run);
set_signal_handler(SIGTERM, terminate_run);
set_signal_handler(SIGALRM, terminate_run);
- set_signal_handler(SIGPIPE, terminate_run);
+ set_signal_handler(SIGPIPE, SIG_IGN);
set_signal_handler(SIGQUIT, terminate_run);
/* here's the exclusion lock */
- lock_or_die();
+ fm_lock_or_die();
+
+ if (check_only && outlevel >= O_VERBOSE) {
+ report(stdout, GT_("--check mode enabled, not fetching mail\n"));
+ }
/*
* Query all hosts. If there's only one, the error return will
*/
struct stat rcstat;
- if (stat(rcfile, &rcstat) == -1)
- {
+ if (strcmp(rcfile, "-") == 0) {
+ /* do nothing */
+ } else if (stat(rcfile, &rcstat) == -1) {
if (errno != ENOENT)
report(stderr,
GT_("couldn't time-check %s (error %d)\n"),
report(stderr, GT_("attempt to re-exec fetchmail failed\n"));
}
-#if defined(HAVE_RES_SEARCH) && defined(USE_TCPIP_FOR_DNS)
- /*
- * This was an efficiency hack that backfired. The theory
- * was that using TCP/IP for DNS queries would get us better
- * reliability and shave off some per-UDP-packet costs.
- * Unfortunately it interacted badly with diald, which effectively
- * filters out DNS queries over TCP/IP for reasons having to do
- * with some obscure Linux kernel problem involving bootstrapping of
- * dynamically-addressed links. I don't understand this mess
- * and don't want to, so it's "See ya!" to this hack.
- */
- sethostent(TRUE); /* use TCP/IP for mailserver queries */
-#endif /* HAVE_RES_SEARCH */
+#ifdef HAVE_RES_SEARCH
+ /* Boldly assume that we also have res_init() if we have
+ * res_search(), and call res_init() to re-read the resolv.conf
+ * file, so that we can pick up changes to that file that are
+ * written by dhpccd, dhclient, pppd, openvpn and similar. */
+
+ /* NOTE: This assumes that /etc/resolv.conf is written
+ * atomically (i. e. a temporary file is written, flushed and
+ * then renamed into place). To fix Debian Bug#389270. */
+
+ /* NOTE: If this leaks memory or doesn't re-read
+ * /etc/resolv.conf, we're in trouble. The res_init() interface
+ * is only lightly documented :-( */
+ res_init();
+#endif
activecount = 0;
batchcount = 0;
}
}
-#if defined(HAVE_RES_SEARCH) && defined(USE_TCPIP_FOR_DNS)
- endhostent(); /* release TCP/IP connection to nameserver */
-#endif /* HAVE_RES_SEARCH */
-
/* close connections cleanly */
terminate_poll(0);
exit(PS_AUTHFAIL);
}
- if (outlevel > O_SILENT)
- report(stdout,
- GT_("sleeping at %s\n"), timestamp());
+ if ((outlevel > O_SILENT && !run.use_syslog && isatty(1))
+ || outlevel > O_NORMAL)
+ report(stdout,
+ GT_("sleeping at %s for %d seconds\n"), timestamp(), run.poll_interval);
/*
* With this simple hack, we make it possible for a foreground
* for people who think all system daemons wake up on SIGHUP.
*/
set_signal_handler(SIGUSR1, donothing);
- if (getuid() != ROOT_UID)
+ if (getuid() == ROOT_UID)
set_signal_handler(SIGHUP, donothing);
/*
ctl->wedged = FALSE;
}
- if (outlevel > O_SILENT)
+ if ((outlevel > O_SILENT && !run.use_syslog && isatty(1))
+ || outlevel > O_NORMAL)
report(stdout, GT_("awakened at %s\n"), timestamp());
}
- } while
- (run.poll_interval);
+ } while (run.poll_interval);
if (outlevel >= O_VERBOSE)
report(stdout, GT_("normal termination, status %d\n"),
FLAG_MERGE(sslproto);
FLAG_MERGE(sslcertck);
FLAG_MERGE(sslcertpath);
+ FLAG_MERGE(sslcommonname);
FLAG_MERGE(sslfingerprint);
#endif
FLAG_MERGE(expunge);
char *p;
run.bouncemail = TRUE;
+ run.softbounce = TRUE; /* treat permanent errors as temporary */
run.spambounce = FALSE; /* don't bounce back to innocent bystanders */
memset(&def_opts, '\0', sizeof(struct query));
def_opts.remotename = user;
def_opts.listener = SMTP_MODE;
def_opts.fetchsizelimit = 100;
- def_opts.fastuidl = 10;
+ def_opts.fastuidl = 4;
/* get the location of rcfile */
rcfiledir[0] = 0;
p = strrchr (rcfile, '/');
- if (p && (p - rcfile) < sizeof (rcfiledir)) {
+ if (p && (size_t)(p - rcfile) < sizeof (rcfiledir)) {
*p = 0; /* replace '/' by '0' */
strlcpy (rcfiledir, rcfile, sizeof(rcfiledir));
*p = '/'; /* restore '/' */
/* note the parse time, so we can pick up on modifications */
parsetime = 0; /* foil compiler warnings */
- if (stat(rcfile, &rcstat) != -1)
+ if (strcmp(rcfile, "-") == 0 || stat(rcfile, &rcstat) != -1)
parsetime = rcstat.st_mtime;
else if (errno != ENOENT)
report(stderr, GT_("couldn't time-check the run-control file\n"));
run.logfile = cmd_run.logfile;
if (cmd_run.idfile)
run.idfile = cmd_run.idfile;
+ if (cmd_run.pidfile)
+ run.pidfile = cmd_run.pidfile;
/* do this before the keep/fetchall test below, otherwise -d0 may fail */
if (cmd_run.poll_interval >= 0)
run.poll_interval = cmd_run.poll_interval;
run.postmaster = cmd_run.postmaster;
if (cmd_run.bouncemail)
run.bouncemail = cmd_run.bouncemail;
+ if (cmd_run.softbounce)
+ run.softbounce = cmd_run.softbounce;
/* check and daemon options are not compatible */
if (check_only && run.poll_interval)
flag = FALSE;\
else\
flag = (dflt)
- /* one global gets treated specially */
- DEFAULT(run.showdots, run.poll_interval==0 || nodetach);
/* merge in wired defaults, do sanity checks and prepare internal fields */
for (ctl = querylist; ctl; ctl = ctl->next)
}
#endif /* SSL_ENABLE */
#undef DEFAULT
+#ifndef KERBEROS_V4
+ if (ctl->server.authenticate == A_KERBEROS_V4) {
+ report(stderr, GT_("KERBEROS v4 support is configured, but not compiled in.\n"));
+ exit(PS_SYNTAX);
+ }
+#endif
+#ifndef KERBEROS_V5
+ if (ctl->server.authenticate == A_KERBEROS_V5) {
+ report(stderr, GT_("KERBEROS v5 support is configured, but not compiled in.\n"));
+ exit(PS_SYNTAX);
+ }
+#endif
+#ifndef GSSAPI
+ if (ctl->server.authenticate == A_GSSAPI) {
+ report(stderr, GT_("GSSAPI support is configured, but not compiled in.\n"));
+ exit(PS_SYNTAX);
+ }
+#endif
/*
* Make sure we have a nonempty host list to forward to.
{
char *cp;
- if (!(cp = strrchr((char *)idp->id, '/')) ||
- ++cp, (0 == strcmp(cp, SMTP_PORT))
- || servport(cp) == SMTP_PORT_NUM)
+ if (!(cp = strrchr(idp->id, '/'))
+ || (0 == strcmp(cp + 1, SMTP_PORT))
+ || servport(cp + 1) == SMTP_PORT_NUM)
{
(void) fprintf(stderr,
GT_("%s configuration invalid, LMTP can't use default SMTP port\n"),
* "I beg to you, have mercy on the we[a]k minds like myself."
* wrote Pehr Anderson. Your petition is granted.
*/
- if (ctl->fetchall && ctl->keep && run.poll_interval && !nodetach && !configdump)
+ if (ctl->fetchall && ctl->keep && (run.poll_interval || ctl->idle) && !nodetach && !configdump)
{
(void) fprintf(stderr,
- GT_("Both fetchall and keep on in daemon mode is a mistake!\n"));
+ GT_("Both fetchall and keep on in daemon or idle mode is a mistake!\n"));
}
}
}
-#ifdef POP3_ENABLE
- /* initialize UID handling */
- if (!versioninfo && (st = prc_filecheck(run.idfile, !versioninfo)) != 0)
- exit(st);
- else
- initialize_saved_lists(querylist, run.idfile);
-#endif /* POP3_ENABLE */
-
/*
* If the user didn't set a last-resort user to get misaddressed
* multidrop mail, set an appropriate default here.
static int query_host(struct query *ctl)
/* perform fetch transaction with single host */
{
- int i, st = 0;
+ size_t i;
+ int st = 0;
/*
* If we're syslogging the progress messages are automatically timestamped.
else if (outlevel >= O_VERBOSE)
printf(GT_("Fetchmail will direct error mail to the sender.\n"));
+ if (!runp->softbounce)
+ printf(GT_("Fetchmail will treat permanent errors as permanent (drop messsages).\n"));
+ else if (outlevel >= O_VERBOSE)
+ printf(GT_("Fetchmail will treat permanent errors as temporary (keep messages).\n"));
+
for (ctl = querylist; ctl; ctl = ctl->next)
{
if (!ctl->active || (implicit && ctl->server.skip))
if (ctl->sslcertpath != NULL)
printf(GT_(" SSL trusted certificate directory: %s\n"), ctl->sslcertpath);
}
+ if (ctl->sslcommonname != NULL)
+ printf(GT_(" SSL server CommonName: %s\n"), ctl->sslcommonname);
if (ctl->sslfingerprint != NULL)
printf(GT_(" SSL key fingerprint (checked against the server key): %s\n"), ctl->sslfingerprint);
#endif
printf(GT_(" Selected mailboxes are:"));
for (idp = ctl->mailboxes; idp; idp = idp->next)
- printf(" %s", (char *)idp->id);
+ printf(" %s", idp->id);
printf("\n");
}
printf(ctl->fetchall
printf(GT_(" Domains for which mail will be fetched are:"));
for (idp = ctl->domainlist; idp; idp = idp->next)
{
- printf(" %s", (char *)idp->id);
+ printf(" %s", idp->id);
if (!idp->val.status.mark)
printf(GT_(" (default)"));
}
ctl->listener);
for (idp = ctl->smtphunt; idp; idp = idp->next)
{
- printf(" %s", (char *)idp->id);
+ printf(" %s", idp->id);
if (!idp->val.status.mark)
printf(GT_(" (default)"));
}
{
for (idp = ctl->localnames; idp; idp = idp->next)
if (idp->val.id2)
- printf("\t%s -> %s\n", (char *)idp->id, (char *)idp->val.id2);
+ printf("\t%s -> %s\n", idp->id, idp->val.id2);
else
- printf("\t%s\n", (char *)idp->id);
+ printf("\t%s\n", idp->id);
if (ctl->wildcard)
fputs("\t*\n", stdout);
}
printf(GT_(" Predeclared mailserver aliases:"));
for (idp = ctl->server.akalist; idp; idp = idp->next)
- printf(" %s", (char *)idp->id);
+ printf(" %s", idp->id);
putchar('\n');
}
if (ctl->server.localdomains)
printf(GT_(" Local domains:"));
for (idp = ctl->server.localdomains; idp; idp = idp->next)
- printf(" %s", (char *)idp->id);
+ printf(" %s", idp->id);
putchar('\n');
}
}
printf(GT_(" %d UIDs saved.\n"), count);
if (outlevel >= O_VERBOSE)
for (idp = ctl->oldsaved; idp; idp = idp->next)
- printf("\t%s\n", (char *)idp->id);
+ printf("\t%s\n", idp->id);
}
}