#include "config.h"
#include <stdio.h>
-#if defined(STDC_HEADERS)
#include <stdlib.h>
-#endif
-#if defined(HAVE_UNISTD_H)
#include <unistd.h>
-#endif
#include <fcntl.h>
#include <string.h>
#include <signal.h>
-#if defined(HAVE_SYSLOG)
#include <syslog.h>
-#endif
#include <pwd.h>
#ifdef __FreeBSD__
#include <grp.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
-#ifdef HAVE_SETRLIMIT
#include <sys/resource.h>
-#endif /* HAVE_SETRLIMIT */
#ifdef HAVE_SOCKS
#include <socks.h> /* SOCKSinit() */
#endif /* HAVE_SOCKS */
-#ifdef HAVE_LANGINFO_H
#include <langinfo.h>
-#endif
#include "fetchmail.h"
#include "socket.h"
#include "tunable.h"
#include "smtp.h"
#include "netrc.h"
-#include "i18n.h"
+#include "gettext.h"
#include "lock.h"
/* need these (and sys/types.h) for res_init() */
char *user; /* the name of the invoking user */
char *home; /* invoking user's home directory */
char *fmhome; /* fetchmail's home directory */
-char *program_name; /* the name to prefix error messages with */
+const char *program_name; /* the name to prefix error messages with */
flag configdump; /* dump control blocks for configurator */
-char *fetchmailhost; /* either `localhost' or the host's FQDN */
+const char *fetchmailhost; /* either `localhost' or the host's FQDN */
static int quitonly; /* if we should quit after killing the running daemon */
static struct runctl cmd_run; /* global options set from command line */
static time_t parsetime; /* time of last parse */
-static RETSIGTYPE terminate_run(int);
-static RETSIGTYPE terminate_poll(int);
+static void terminate_run(int);
+static void terminate_poll(int);
+
+#ifdef HAVE_LIBPWMD
+static pwm_t *pwm; /* the handle */
+static const char *pwmd_socket; /* current socket */
+static const char *pwmd_file; /* current file */
+#endif
#if defined(__FreeBSD__) && defined(__FreeBSD_USE_KVM)
/* drop SGID kmem privileage until we need it */
}
#endif
-#if defined(HAVE_SETLOCALE) && defined(ENABLE_NLS) && defined(HAVE_STRFTIME)
#include <locale.h>
+#if defined(ENABLE_NLS)
/** returns timestamp in current locale,
* and resets LC_TIME locale to POSIX. */
static char *timestamp (void)
#define timestamp rfc822timestamp
#endif
-static RETSIGTYPE donothing(int sig)
+static void donothing(int sig)
{
set_signal_handler(sig, donothing);
lastsig = sig;
static void printcopyright(FILE *fp) {
fprintf(fp, GT_("Copyright (C) 2002, 2003 Eric S. Raymond\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-2007 Matthias Andree\n"
+ "Copyright (C) 2004 Matthias Andree, Eric S. Raymond,\n"
+ " Robert M. Funk, Graham Wilson\n"
+ "Copyright (C) 2005 - 2006, 2010 - 2011 Sunil Shetye\n"
+ "Copyright (C) 2005 - 2011 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"));
+#ifdef SSL_ENABLE
+ /* Do not translate this */
+ fprintf(fp, "This product includes software developed by the OpenSSL Project\nfor use in the OpenSSL Toolkit. (http://www.openssl.org/)\n");
+#endif
}
const char *iana_charset;
+#ifdef HAVE_LIBPWMD
+static void exit_with_pwmd_error(gpg_error_t error)
+{
+ gpg_err_code_t code = gpg_err_code(error);
+
+ report(stderr, GT_("pwmd: error %i: %s\n"), code, pwmd_strerror(error));
+
+ if (pwm) {
+ pwmd_close(pwm);
+ pwm = NULL;
+ }
+
+ /* Don't exit if daemonized. There may be other active accounts. */
+ if (isatty(1))
+ exit(PS_UNDEFINED);
+}
+
+static int do_pwmd_connect(const char *socketname, const char *filename)
+{
+ static int init;
+ gpg_error_t rc;
+ pwmd_socket_t s;
+
+ if (!init) {
+ pwmd_init();
+ init = 1;
+ }
+
+ if (!pwm || (pwm && socketname && !pwmd_socket) ||
+ (pwm && !socketname && pwmd_socket) ||
+ (pwm && socketname && pwmd_socket && strcmp(socketname, pwmd_socket))) {
+ if (pwm)
+ pwmd_close(pwm);
+
+ pwm = pwmd_new("Fetchmail");
+ rc = pwmd_connect_url(pwm, socketname);
+
+ if (rc) {
+ exit_with_pwmd_error(rc);
+ return 1;
+ }
+ }
+
+ if (run.pinentry_timeout > 0) {
+ rc = pwmd_setopt(pwm, PWMD_OPTION_PINENTRY_TIMEOUT,
+ run.pinentry_timeout);
+
+ if (rc) {
+ exit_with_pwmd_error(rc);
+ return 1;
+ }
+ }
+
+ rc = pwmd_socket_type(pwm, &s);
+
+ if (rc) {
+ exit_with_pwmd_error(rc);
+ return 1;
+ }
+
+ if (!pwmd_file || strcmp(filename, pwmd_file)) {
+ if (s == PWMD_SOCKET_SSH)
+ /* use a local pinentry since X11 forwarding is broken. */
+ rc = pwmd_open2(pwm, filename);
+ else
+ rc = pwmd_open(pwm, filename);
+
+ if (rc) {
+ exit_with_pwmd_error(rc);
+ return 1;
+ }
+ }
+
+ /* May be null to use the default of ~/.pwmd/socket. */
+ pwmd_socket = socketname;
+ pwmd_file = filename;
+ return 0;
+}
+
+static int get_pwmd_details(const char *pwmd_account, int protocol,
+ struct query *ctl)
+{
+ const char *prot = showproto(protocol);
+ gpg_error_t error;
+ char *result;
+ char *tmp = xstrdup(pwmd_account);
+ int i;
+
+ for (i = 0; tmp[i]; i++) {
+ if (i && tmp[i] == '^')
+ tmp[i] = '\t';
+ }
+
+ /*
+ * Get the hostname for this protocol. Element path must be
+ * account->[protocol]->hostname.
+ */
+ error = pwmd_command(pwm, &result, "GET %s\t%s\thostname", tmp, prot);
+
+ if (error) {
+ if (gpg_err_code(error) == GPG_ERR_NOT_FOUND) {
+ report(stderr, GT_("pwmd: %s->%s->hostname: %s\n"), pwmd_account, prot, pwmd_strerror(error));
+ pwmd_close(pwm);
+ pwm = NULL;
+
+ if (isatty(1))
+ exit(PS_SYNTAX);
+
+ return 1;
+ }
+ else {
+ exit_with_pwmd_error(error);
+ return 1;
+ }
+ }
+
+ if (ctl->server.pollname != ctl->server.via)
+ xfree(ctl->server.via);
+
+ ctl->server.via = xstrdup(result);
+
+ if (ctl->server.queryname)
+ xfree(ctl->server.queryname);
+
+ ctl->server.queryname = xstrdup(ctl->server.via);
+
+ if (ctl->server.truename)
+ xfree(ctl->server.truename);
+
+ ctl->server.truename = xstrdup(ctl->server.queryname);
+ pwmd_free(result);
+
+ /*
+ * Server port. Fetchmail tries standard ports for known services so it
+ * should be alright if this element isn't found. ctl->server.protocol is
+ * already set. This sets ctl->server.service.
+ */
+ error = pwmd_command(pwm, &result, "GET %s\t%s\tport", tmp, prot);
+
+ if (error) {
+ if (gpg_err_code(error) == GPG_ERR_NOT_FOUND)
+ report(stderr, GT_("pwmd: %s->%s->port: %s\n"), pwmd_account, prot, pwmd_strerror(error));
+ else {
+ exit_with_pwmd_error(error);
+ return 1;
+ }
+ }
+ else {
+ if (ctl->server.service)
+ xfree(ctl->server.service);
+
+ ctl->server.service = xstrdup(result);
+ pwmd_free(result);
+ }
+
+ /*
+ * Get the remote username. Element must be account->username.
+ */
+ error = pwmd_command(pwm, &result, "GET %s\tusername", tmp);
+
+ if (error) {
+ if (gpg_err_code(error) == GPG_ERR_NOT_FOUND) {
+ report(stderr, GT_("pwmd: %s->username: %s\n"), pwmd_account, pwmd_strerror(error));
+
+ if (!isatty(1)) {
+ pwmd_close(pwm);
+ pwm = NULL;
+ return 1;
+ }
+ }
+ else {
+ exit_with_pwmd_error(error);
+ return 1;
+ }
+ }
+ else {
+ if (ctl->remotename)
+ xfree(ctl->remotename);
+
+ if (ctl->server.esmtp_name)
+ xfree(ctl->server.esmtp_name);
+
+ ctl->remotename = xstrdup(result);
+ ctl->server.esmtp_name = xstrdup(result);
+ pwmd_free(result);
+ }
+
+ /*
+ * Get the remote password. Element must be account->password.
+ */
+ error = pwmd_command(pwm, &result, "GET %s\tpassword", tmp);
+
+ if (error) {
+ if (gpg_err_code(error) == GPG_ERR_NOT_FOUND) {
+ report(stderr, GT_("pwmd: %s->password: %s\n"), pwmd_account, pwmd_strerror(error));
+
+ if (!isatty(1)) {
+ pwmd_close(pwm);
+ pwm = NULL;
+ return 1;
+ }
+ }
+ else {
+ exit_with_pwmd_error(error);
+ return 1;
+ }
+ }
+ else {
+ if (ctl->password)
+ xfree(ctl->password);
+
+ ctl->password= xstrdup(result);
+ pwmd_free(result);
+ }
+
+#ifdef SSL_ENABLE
+ /*
+ * If there is a ssl element and set to 1, enable ssl for this account.
+ * Element path must be account->[protocol]->ssl.
+ */
+ error = pwmd_command(pwm, &result, "GET %s\t%s\tssl", tmp, prot);
+
+ if (error) {
+ if (gpg_err_code(error) == GPG_ERR_NOT_FOUND) {
+ report(stderr, GT_("pwmd: %s->%s->ssl: %s\n"), pwmd_account, prot, pwmd_strerror(error));
+
+ if (!isatty(1)) {
+ pwmd_close(pwm);
+ pwm = NULL;
+ return 1;
+ }
+ }
+ else {
+ exit_with_pwmd_error(error);
+ return 1;
+ }
+ }
+ else {
+ ctl->use_ssl = atoi(result) >= 1 ? FLAG_TRUE : FLAG_FALSE;
+ pwmd_free(result);
+ }
+
+ /*
+ * account->[protocol]->sslfingerprint.
+ */
+ error = pwmd_command(pwm, &result, "GET %s\t%s\tsslfingerprint", tmp, prot);
+
+ if (error) {
+ if (gpg_err_code(error) == GPG_ERR_NOT_FOUND) {
+ report(stderr, GT_("pwmd: %s->%s->sslfingerprint: %s\n"), pwmd_account, prot, pwmd_strerror(error));
+
+ if (!isatty(1)) {
+ pwmd_close(pwm);
+ pwm = NULL;
+ return 1;
+ }
+ }
+ else {
+ exit_with_pwmd_error(error);
+ return 1;
+ }
+ }
+ else {
+ if (ctl->sslfingerprint)
+ xfree(ctl->sslfingerprint);
+
+ ctl->sslfingerprint = xstrdup(result);
+ pwmd_free(result);
+ }
+#endif
+
+ xfree(tmp);
+ return 0;
+}
+#endif
+
int main(int argc, char **argv)
{
int bkgd = FALSE;
int implicitmode = FALSE;
+ flag safewithbg = FALSE; /** if parsed options are compatible with a
+ fetchmail copy running in the background */
struct query *ctl;
netrc_entry *netrc_list;
char *netrc_file, *tmpbuf;
#define IDFILE_NAME ".fetchids"
run.idfile = prependdir (IDFILE_NAME, fmhome);
-
+
outlevel = O_NORMAL;
/*
{
int i;
- i = parsecmdline(argc, argv, &cmd_run, &cmd_opts);
+ i = parsecmdline(argc, argv, &cmd_run, &cmd_opts, &safewithbg);
if (i < 0)
exit(PS_SYNTAX);
if (versioninfo)
{
const char *features =
-#ifdef POP2_ENABLE
- "+POP2"
-#endif /* POP2_ENABLE */
#ifndef POP3_ENABLE
"-POP3"
#endif /* POP3_ENABLE */
#ifdef ENABLE_NLS
"+NLS"
#endif /* ENABLE_NLS */
-#ifdef KERBEROS_V4
- "+KRB4"
-#endif /* KERBEROS_V4 */
#ifdef KERBEROS_V5
"+KRB5"
#endif /* KERBEROS_V5 */
+#ifdef HAVE_LIBPWMD
+ "+PWMD"
+#endif /* HAVE_LIBPWMD */
".\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);
-#if defined(HAVE_SYSLOG)
+ /* precedence: logfile (if effective) overrides syslog. */
+ if (run.logfile && run.poll_interval && !nodetach) {
+ run.use_syslog = 0;
+ }
+
/* logging should be set up early in case we were restarted from exec */
if (run.use_syslog)
{
-#if defined(LOG_MAIL)
openlog(program_name, LOG_PID, LOG_MAIL);
-#else
- /* Assume BSD4.2 openlog with two arguments */
- openlog(program_name, LOG_PID);
-#endif
report_init(-1);
}
else
-#endif
report_init((run.poll_interval == 0 || nodetach) && !run.logfile);
#ifdef POP3_ENABLE
/* construct the lockfile */
fm_lock_setup(&run);
-#ifdef HAVE_SETRLIMIT
/*
* Before getting passwords, disable core dumps unless -v -d0 mode is on.
* Core dumps could otherwise contain passwords to be scavenged by a
corelimit.rlim_max = 0;
setrlimit(RLIMIT_CORE, &corelimit);
}
-#endif /* HAVE_SETRLIMIT */
#define NETRC_FILE ".netrc"
/* parse the ~/.netrc file (if present) for future password lookups. */
}
else if (kill(pid, SIGTERM) < 0)
{
- fprintf(stderr,GT_("fetchmail: error killing %s fetchmail at %d; bailing out.\n"),
- bkgd ? GT_("background") : GT_("foreground"), pid);
+ fprintf(stderr,GT_("fetchmail: error killing %s fetchmail at %ld; bailing out.\n"),
+ bkgd ? GT_("background") : GT_("foreground"), (long)pid);
exit(PS_EXCLUDE);
}
else
int maxwait;
if (outlevel > O_SILENT)
- fprintf(stderr,GT_("fetchmail: %s fetchmail at %d killed.\n"),
- bkgd ? GT_("background") : GT_("foreground"), pid);
+ fprintf(stderr,GT_("fetchmail: %s fetchmail at %ld killed.\n"),
+ bkgd ? GT_("background") : GT_("foreground"), (long)pid);
/* We used to nuke the other process's lock here, with
* fm_lock_release(), which is broken. The other process
* needs to clear its lock by itself. */
else if (!implicitmode)
{
fprintf(stderr,
- GT_("fetchmail: can't poll specified hosts with another fetchmail running at %d.\n"),
- pid);
+ GT_("fetchmail: can't poll specified hosts with another fetchmail running at %ld.\n"),
+ (long)pid);
return(PS_EXCLUDE);
}
else if (!bkgd)
{
fprintf(stderr,
- GT_("fetchmail: another foreground fetchmail is running at %d.\n"),
- pid);
+ GT_("fetchmail: another foreground fetchmail is running at %ld.\n"),
+ (long)pid);
return(PS_EXCLUDE);
}
else if (getpid() == pid)
/* this test enables re-execing on a changed rcfile */
fm_lock_assert();
- else if (argc > 1)
+ else if (argc > 1 && !safewithbg)
{
fprintf(stderr,
GT_("fetchmail: can't accept options while a background fetchmail is running.\n"));
+ {
+ int i;
+ fprintf(stderr, "argc = %d, arg list:\n", argc);
+ for (i = 1; i < argc; i++) fprintf(stderr, "arg %d = \"%s\"\n", i, argv[i]);
+ }
return(PS_EXCLUDE);
}
else if (kill(pid, SIGUSR1) == 0)
{
- fprintf(stderr,
- GT_("fetchmail: background fetchmail at %d awakened.\n"),
- pid);
+ if (outlevel > O_SILENT)
+ fprintf(stderr,
+ GT_("fetchmail: background fetchmail at %ld awakened.\n"),
+ (long)pid);
return(0);
}
else
* SIGUSR1/SIGHUP transmission.
*/
fprintf(stderr,
- GT_("fetchmail: elder sibling at %d died mysteriously.\n"),
- pid);
+ GT_("fetchmail: elder sibling at %ld died mysteriously.\n"),
+ (long)pid);
return(PS_UNDEFINED);
}
}
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)
- fprintf(stderr, GT_("fetchmail: Warning: syslog and logfile are set. Check both for logs!\n"));
+ run.logfile = 0;
/*
* Maybe time to go to demon mode...
exit(rc);
}
}
- report(stdout, GT_("starting fetchmail %s daemon \n"), VERSION);
+ report(stdout, GT_("starting fetchmail %s daemon\n"), VERSION);
/*
* We'll set up a handler for these when we're sleeping,
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);
+ 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);
+ 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"));
}
/* here's the exclusion lock */
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
* reflect the status of that transaction.
* leaks...
*/
struct stat rcstat;
+#ifdef HAVE_LIBPWMD
+ time_t now;
+
+ time(&now);
+#endif
if (strcmp(rcfile, "-") == 0) {
/* do nothing */
GT_("couldn't time-check %s (error %d)\n"),
rcfile, errno);
}
+#ifdef HAVE_LIBPWMD
+ /*
+ * isatty() to make sure this is a background process since the
+ * lockfile is removed after each invokation.
+ */
+ else if (!isatty(1) && rcstat.st_mtime > parsetime)
+#else
else if (rcstat.st_mtime > parsetime)
+#endif
{
report(stdout, GT_("restarting fetchmail (%s changed)\n"), rcfile);
dofastuidl = 0; /* this is reset in the driver if required */
+#ifdef HAVE_LIBPWMD
+ /*
+ * At each poll interval, check the pwmd server for
+ * changes in host and auth settings.
+ */
+ if (ctl->pwmd_file) {
+ if (do_pwmd_connect(ctl->pwmd_socket, ctl->pwmd_file))
+ continue;
+
+ if (get_pwmd_details(ctl->server.pollname, ctl->server.protocol, ctl))
+ continue;
+ }
+#endif
querystatus = query_host(ctl);
if (NUM_NONZERO(ctl->fastuidl))
}
}
+#ifdef HAVE_LIBPWMD
+ if (pwm) {
+ pwmd_close(pwm);
+ pwm = NULL;
+ }
+#endif
+
/* close connections cleanly */
terminate_poll(0);
exit(PS_AUTHFAIL);
}
- if (outlevel > O_SILENT)
+ 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);
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(server.skip);
FLAG_MERGE(server.dns);
FLAG_MERGE(server.checkalias);
- FLAG_MERGE(server.uidl);
FLAG_MERGE(server.principal);
#ifdef CAN_MONITOR
FLAG_MERGE(server.plugin);
FLAG_MERGE(server.plugout);
FLAG_MERGE(server.tracepolls);
+ FLAG_MERGE(server.badheader);
+ FLAG_MERGE(server.retrieveerror);
FLAG_MERGE(wildcard);
FLAG_MERGE(remotename);
FLAG_MERGE(sslcert);
FLAG_MERGE(sslproto);
FLAG_MERGE(sslcertck);
+ FLAG_MERGE(sslcertfile);
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.server.protocol = P_AUTO;
def_opts.server.timeout = CLIENT_TIMEOUT;
def_opts.server.esmtp_name = user;
+ def_opts.server.badheader = BHREJECT;
def_opts.warnings = WARNING_INTERVAL;
def_opts.remotename = user;
def_opts.listener = SMTP_MODE;
}
/* note the parse time, so we can pick up on modifications */
- parsetime = 0; /* foil compiler warnings */
- 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"));
+ if (strcmp(rcfile, "-") == 0)
+ parsetime = time(NULL);
+ else {
+ if (stat(rcfile, &rcstat) != -1)
+ parsetime = rcstat.st_mtime;
+ else if (errno != ENOENT)
+ report(stderr, GT_("couldn't time-check the run-control file\n"));
+ }
/* this builds the host list */
if ((st = prc_parse_file(rcfile, !versioninfo)) != 0)
if ((implicitmode = (optind >= argc)))
{
+#ifdef HAVE_LIBPWMD
+ for (ctl = querylist; ctl; ctl = ctl->next) {
+ ctl->active = !ctl->server.skip;
+
+ if (ctl->pwmd_file) {
+ /*
+ * Cannot get an element path without a service.
+ */
+ if (ctl->server.protocol <= 1) {
+ report(stderr, GT_("fetchmail: %s configuration invalid, pwmd_file requires a protocol specification\n"),
+ ctl->server.pollname);
+ pwmd_close(pwm);
+ exit(PS_SYNTAX);
+ }
+
+ if (do_pwmd_connect(ctl->pwmd_socket, ctl->pwmd_file))
+ continue;
+
+ if (get_pwmd_details(ctl->server.pollname, ctl->server.protocol,
+ ctl))
+ continue;
+
+ time(&rcstat.st_mtime);
+ }
+ }
+
+#else
for (ctl = querylist; ctl; ctl = ctl->next)
ctl->active = !ctl->server.skip;
+#endif
}
else
for (; optind < argc; optind++)
fprintf(stderr,GT_("Warning: multiple mentions of host %s in config file\n"),argv[optind]);
ctl->active = TRUE;
predeclared = TRUE;
+
+#ifdef HAVE_LIBPWMD
+ if (ctl->pwmd_file) {
+ /*
+ * Cannot get an element path without a service.
+ */
+ if (ctl->server.protocol <= 1) {
+ report(stderr, GT_("%s configuration invalid, pwmd_file requires a protocol specification\n"),
+ ctl->server.pollname);
+ exit(PS_SYNTAX);
+ }
+
+ fprintf(stderr, "%s(%i): %s\n", __FILE__, __LINE__, __FUNCTION__);
+ if (do_pwmd_connect(ctl->pwmd_socket, ctl->pwmd_file))
+ continue;
+
+ if (get_pwmd_details(ctl->server.pollname,
+ ctl->server.protocol, ctl))
+ continue;
+ }
+#endif
}
if (!predeclared)
* call later on.
*/
ctl = hostalloc((struct query *)NULL);
+
+#ifdef HAVE_LIBPWMD
+ if (cmd_opts.pwmd_file) {
+ /*
+ * Cannot get an element path without a service.
+ */
+ if (cmd_opts.server.protocol == 0 || cmd_opts.server.protocol == 1) {
+ report(stderr, GT_("Option --pwmd-file needs a service (-p) parameter.\n"));
+ exit(PS_SYNTAX);
+ }
+
+ fprintf(stderr, "%s(%i): %s\n", __FILE__, __LINE__, __FUNCTION__);
+ if (do_pwmd_connect(cmd_opts.pwmd_socket, cmd_opts.pwmd_file))
+ continue;
+
+ if (get_pwmd_details(argv[optind], cmd_opts.server.protocol,
+ ctl))
+ continue;
+ }
+ else
+ ctl->server.via =
+ ctl->server.pollname = xstrdup(argv[optind]);
+#else
ctl->server.via =
ctl->server.pollname = xstrdup(argv[optind]);
+#endif
ctl->active = TRUE;
ctl->server.lead_server = (struct hostdata *)NULL;
}
/*
* If there's a defaults record, merge it and lose it.
+ * FIXME: we don't currently free all entries that might be in struct query.
*/
if (querylist && strcmp(querylist->server.pollname, "defaults") == 0)
{
+ struct query *tmpq;
+
for (ctl = querylist->next; ctl; ctl = ctl->next)
optmerge(ctl, querylist, FALSE);
+ tmpq = querylist;
querylist = querylist->next;
+ free(tmpq->server.pollname);
+ free(tmpq);
}
/* don't allow a defaults record after the first */
if (cmd_run.poll_interval >= 0)
run.poll_interval = cmd_run.poll_interval;
if (cmd_run.invisible)
- run.invisible = cmd_run.invisible;
+ run.invisible = (cmd_run.invisible == FLAG_TRUE);
if (cmd_run.showdots)
- run.showdots = cmd_run.showdots;
+ run.showdots = (cmd_run.showdots == FLAG_TRUE);
if (cmd_run.use_syslog)
run.use_syslog = (cmd_run.use_syslog == FLAG_TRUE);
if (cmd_run.postmaster)
run.postmaster = cmd_run.postmaster;
if (cmd_run.bouncemail)
- run.bouncemail = cmd_run.bouncemail;
+ run.bouncemail = (cmd_run.bouncemail == FLAG_TRUE);
+ if (cmd_run.softbounce)
+ run.softbounce = (cmd_run.softbounce == FLAG_TRUE);
/* check and daemon options are not compatible */
if (check_only && run.poll_interval)
for (ctl = querylist; ctl; ctl = ctl->next)
if (ctl->active &&
(ctl->server.protocol==P_ETRN || ctl->server.protocol==P_ODMR
- || ctl->server.authenticate == A_KERBEROS_V4
|| ctl->server.authenticate == A_KERBEROS_V5))
{
fetchmailhost = host_fqdn(1);
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)
DEFAULT(ctl->mimedecode, FALSE);
DEFAULT(ctl->idle, FALSE);
DEFAULT(ctl->server.dns, TRUE);
- DEFAULT(ctl->server.uidl, FALSE);
DEFAULT(ctl->use_ssl, FALSE);
DEFAULT(ctl->sslcertck, FALSE);
DEFAULT(ctl->server.checkalias, FALSE);
}
#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"));
if (!ctl->localnames) /* for local delivery via SMTP */
save_str_pair(&ctl->localnames, user, NULL);
-#ifndef HAVE_RES_SEARCH
- /* can't handle multidrop mailboxes unless we can do DNS lookups */
- if (MULTIDROP(ctl) && ctl->server.dns)
- {
- ctl->server.dns = FALSE;
- report(stderr, GT_("fetchmail: warning: no DNS available to check multidrop fetches from %s\n"), ctl->server.pollname);
- }
-#endif /* !HAVE_RES_SEARCH */
-
/*
* can't handle multidrop mailboxes without "envelope"
* option, this causes truckloads full of support complaints
ctl->server.pollname);
exit(PS_SYNTAX);
}
- if (ctl->server.protocol == P_RPOP && port >= 1024)
- {
- (void) fprintf(stderr,
- GT_("fetchmail: %s configuration invalid, RPOP requires a privileged port\n"),
- ctl->server.pollname);
- exit(PS_SYNTAX);
- }
}
if (ctl->listener == LMTP_MODE)
{
return(implicitmode);
}
-static RETSIGTYPE terminate_poll(int sig)
+static void terminate_poll(int sig)
/* to be executed at the end of a poll cycle */
{
#endif /* POP3_ENABLE */
}
-static RETSIGTYPE terminate_run(int sig)
+static void terminate_run(int sig)
/* to be executed on normal or signal-induced termination */
{
struct query *ctl;
if (ctl->password)
memset(ctl->password, '\0', strlen(ctl->password));
-#if !defined(HAVE_ATEXIT)
- fm_lock_release();
-#endif
-
if (activecount == 0)
exit(PS_NOMAIL);
else
#ifdef POP3_ENABLE
P_POP3,
#endif /* POP3_ENABLE */
-#ifdef POP2_ENABLE
- P_POP2
-#endif /* POP2_ENABLE */
};
static int query_host(struct query *ctl)
}
ctl->server.protocol = P_AUTO;
break;
- case P_POP2:
-#ifdef POP2_ENABLE
- st = doPOP2(ctl);
-#else
- report(stderr, GT_("POP2 support is not configured.\n"));
- st = PS_PROTOCOL;
-#endif /* POP2_ENABLE */
- break;
case P_POP3:
- case P_APOP:
- case P_RPOP:
#ifdef POP3_ENABLE
do {
st = doPOP3(ctl);
return(st);
}
+static int print_id_of(struct uid_db_record *rec, void *unused)
+{
+ (void)unused;
+
+ printf("\t%s\n", rec->id);
+ return 0;
+}
+
static void dump_params (struct runctl *runp,
struct query *querylist, flag implicit)
/* display query parameters in English */
printf(GT_("Logfile is %s\n"), runp->logfile);
if (strcmp(runp->idfile, IDFILE_NAME))
printf(GT_("Idfile is %s\n"), runp->idfile);
-#if defined(HAVE_SYSLOG)
if (runp->use_syslog)
printf(GT_("Progress messages will be logged via syslog\n"));
-#endif
if (runp->invisible)
printf(GT_("Fetchmail will masquerade and will not generate Received\n"));
if (runp->showdots)
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 messages).\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))
printf(GT_(" Password will be prompted for.\n"));
else if (outlevel >= O_VERBOSE)
{
- if (ctl->server.protocol == P_APOP)
- printf(GT_(" APOP secret = \"%s\".\n"),
- visbuf(ctl->password));
- else if (ctl->server.protocol == P_RPOP)
- printf(GT_(" RPOP id = \"%s\".\n"),
- visbuf(ctl->password));
- else
- printf(GT_(" Password = \"%s\".\n"),
- visbuf(ctl->password));
+ printf(GT_(" Password = \"%s\".\n"),
+ visbuf(ctl->password));
}
}
if (ctl->server.protocol == P_POP3
&& ctl->server.service && !strcmp(ctl->server.service, KPOP_PORT)
- && (ctl->server.authenticate == A_KERBEROS_V4 ||
- ctl->server.authenticate == A_KERBEROS_V5))
+ && (ctl->server.authenticate == A_KERBEROS_V5))
printf(GT_(" Protocol is KPOP with Kerberos %s authentication"),
ctl->server.authenticate == A_KERBEROS_V5 ? "V" : "IV");
else
printf(GT_(" (using service %s)"), ctl->server.service);
else if (outlevel >= O_VERBOSE)
printf(GT_(" (using default port)"));
- if (ctl->server.uidl && MAILBOX_PROTOCOL(ctl))
- printf(GT_(" (forcing UIDL use)"));
putchar('.');
putchar('\n');
switch (ctl->server.authenticate)
printf(GT_(" OTP authentication will be forced.\n"));
break;
case A_CRAM_MD5:
- printf(GT_(" CRAM-Md5 authentication will be forced.\n"));
+ printf(GT_(" CRAM-MD5 authentication will be forced.\n"));
break;
case A_GSSAPI:
printf(GT_(" GSSAPI authentication will be forced.\n"));
break;
- case A_KERBEROS_V4:
- printf(GT_(" Kerberos V4 authentication will be forced.\n"));
- break;
case A_KERBEROS_V5:
printf(GT_(" Kerberos V5 authentication will be forced.\n"));
break;
case A_SSH:
printf(GT_(" End-to-end encryption assumed.\n"));
break;
+ case A_APOP:
+ printf(GT_(" APOP authentication will be forced.\n"));
+ break;
+ default:
+ abort();
}
if (ctl->server.principal != (char *) NULL)
printf(GT_(" Mail service principal is: %s\n"), ctl->server.principal);
printf(GT_(" SSL protocol: %s.\n"), ctl->sslproto);
if (ctl->sslcertck) {
printf(GT_(" SSL server certificate checking enabled.\n"));
- if (ctl->sslcertpath != NULL)
- printf(GT_(" SSL trusted certificate directory: %s\n"), ctl->sslcertpath);
}
+ if (ctl->sslcertfile != NULL)
+ printf(GT_(" SSL trusted certificate file: %s\n"), ctl->sslcertfile);
+ 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
if (ctl->server.akalist)
{
- struct idlist *idp;
-
printf(GT_(" Predeclared mailserver aliases:"));
for (idp = ctl->server.akalist; idp; idp = idp->next)
printf(" %s", idp->id);
putchar('\n');
}
+
if (ctl->server.localdomains)
{
- struct idlist *idp;
-
printf(GT_(" Local domains:"));
for (idp = ctl->server.localdomains; idp; idp = idp->next)
printf(" %s", idp->id);
else if (outlevel >= O_VERBOSE)
printf(GT_(" No plugout command specified.\n"));
- if (ctl->server.protocol > P_POP2 && MAILBOX_PROTOCOL(ctl))
+ if (MAILBOX_PROTOCOL(ctl))
{
- if (!ctl->oldsaved)
+ int count;
+
+ if (!(count = uid_db_n_records(&ctl->oldsaved)))
printf(GT_(" No UIDs saved from this host.\n"));
else
{
- struct idlist *idp;
- int count = 0;
-
- for (idp = ctl->oldsaved; idp; idp = idp->next)
- ++count;
-
printf(GT_(" %d UIDs saved.\n"), count);
- if (outlevel >= O_VERBOSE)
- for (idp = ctl->oldsaved; idp; idp = idp->next)
- printf("\t%s\n", idp->id);
+ traverse_uid_db(&ctl->oldsaved, print_id_of, NULL);
}
}
if (ctl->server.tracepolls)
printf(GT_(" Poll trace information will be added to the Received header.\n"));
else if (outlevel >= O_VERBOSE)
- printf(GT_(" No poll trace information will be added to the Received header.\n.\n"));
+ printf(GT_(" No poll trace information will be added to the Received header.\n"));
+
+ switch (ctl->server.badheader) {
+ case BHREJECT:
+ if (outlevel >= O_VERBOSE)
+ printf(GT_(" Messages with bad headers will be rejected.\n"));
+ break;
+ case BHACCEPT:
+ printf(GT_(" Messages with bad headers will be passed on.\n"));
+ break;
+ }
+
+ switch (ctl->server.retrieveerror) {
+ case RE_ABORT:
+ if (outlevel >= O_VERBOSE)
+ printf(GT_(" Messages with fetch body errors will cause the session to abort.\n"));
+ break;
+ case RE_CONTINUE:
+ printf(GT_(" Messages with fetch body errors will be skipped, the session will continue.\n"));
+ break;
+ case RE_MARKSEEN:
+ printf(GT_(" Messages with fetch body errors will be marked seen, the session will continue.\n"));
+ break;
+ }
if (ctl->properties)
printf(GT_(" Pass-through properties \"%s\".\n"),