#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 */
}
#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;
fprintf(fp, GT_("Copyright (C) 2002, 2003 Eric S. Raymond\n"
"Copyright (C) 2004 Matthias Andree, Eric S. Raymond,\n"
" Robert M. Funk, Graham Wilson\n"
- "Copyright (C) 2005 - 2006, 2010 Sunil Shetye\n"
- "Copyright (C) 2005 - 2010 Matthias Andree\n"
+ "Copyright (C) 2005 - 2012 Matthias Andree, Sunil Shetye\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;
{
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 */
-#ifndef HAVE_RES_SEARCH
- "-DNS"
-#endif
#ifdef HAVE_LIBPWMD
"+PWMD"
#endif /* HAVE_LIBPWMD */
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)
{
-#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);
}
}
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);
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)
ctl->server.via =
ctl->server.pollname = xstrdup(argv[optind]);
#else
- ctl->server.via =
- ctl->server.pollname = xstrdup(argv[optind]);
+ 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;
+ 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);
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)
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)
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"),