#include <netdb.h>
#endif /* HAVE_GETHOSTBYNAME */
-#ifdef SUNOS
-#include <stdlib.h>
-#endif
-
#include "fetchmail.h"
#include "tunable.h"
#include "smtp.h"
#define DROPDEAD 6 /* maximum bad socket opens */
+#ifndef ENETUNREACH
+#define ENETUNREACH 128 /* Interactive doesn't know this */
+#endif /* ENETUNREACH */
+
/* prototypes for internal functions */
static int load_params(int, char **, int);
static void dump_params (struct query *);
char *idfile; /* UID list file */
flag versioninfo; /* emit only version info */
char *user; /* the name of the invoking user */
+char *home;
char *fetchmailhost; /* the name of the host running fetchmail */
char *program_name; /* the name to prefix error messages with */
RETSIGTYPE donothing(sig) int sig; {signal(sig, donothing); lastsig = sig;}
-#ifdef HAVE_ATEXIT
-static void unlockit(void)
-#else /* use on_exit(), e.g. on SunOS */
+#ifdef HAVE_ON_EXIT
static void unlockit(int n, void *p)
+#else
+static void unlockit(void)
#endif
/* must-do actions for exit (but we can't count on being able to do malloc) */
{
{
int st, bkgd = FALSE;
int parsestatus, implicitmode = FALSE;
- struct passwd *pw;
struct query *ctl;
FILE *lockfp;
netrc_entry *netrc_list;
setvbuf(stdout, NULL, _IOLBF, POPBUFSIZE);
if (versioninfo)
+ {
printf("This is fetchmail release %s\n", RELEASE_ID);
+ /* this is an attempt to help remote debugging */
+ system("uname -a");
+ }
+
/* avoid parsing the config file if all we're doing is killing a daemon */
if (!quitmode)
implicitmode = load_params(argc, argv, optind);
/* set up to do lock protocol */
if (!getuid())
- strcpy(tmpbuf, "/var/run/fetchmail.pid");
+ sprintf(tmpbuf, "%s/fetchmail.pid", PID_DIR);
else {
strcpy(tmpbuf, home);
strcat(tmpbuf, "/.fetchmail");
else
{
/* look up the host and account in the .netrc file. */
- netrc_entry *p = search_netrc(netrc_list,ctl->server.names->id);
+ netrc_entry *p = search_netrc(netrc_list,ctl->server.pollname);
while (p && strcmp(p->account, ctl->remotename))
p = search_netrc(p->next, ctl->remotename);
if (ctl->server.protocol != P_ETRN && ctl->server.protocol != P_IMAP_K4 && !ctl->password)
{
(void) sprintf(tmpbuf, "Enter password for %s@%s: ",
- ctl->remotename, ctl->server.names->id);
+ ctl->remotename, ctl->server.pollname);
ctl->password = xstrdup((char *)getpassword(tmpbuf));
}
}
#ifdef HAVE_ATEXIT
atexit(unlockit);
-#else
+#endif
+#ifdef HAVE_ON_EXIT
on_exit(unlockit, (char *)NULL);
#endif
}
{
if (ctl->active && !(implicitmode && ctl->server.skip))
{
+ /* check skip interval first so that it counts all polls */
+ if (poll_interval && ctl->server.interval)
+ {
+ if (ctl->server.poll_count++ % ctl->server.interval)
+ {
+ if (outlevel == O_VERBOSE)
+ fprintf(stderr,
+ "fetchmail: interval not reached, not querying %s\n",
+ ctl->server.pollname);
+ continue;
+ }
+ }
+
#ifdef linux
/* interface_approve() does its own error logging */
if (!interface_approve(&ctl->server))
continue;
#endif /* linux */
- /*
- * How we compute the true mailhost name to pass to the
- * listener doesn't affect behavior on RFC1123- violating
- * listener that check for name match; we're going to lose
- * on those anyway because we can never give them a name
- * that matches the local machine fetchmail is running on.
- * What it will affect is the listener's logging.
- *
- * If we have the mailserver's canonical FQDN that is clearly
- * the right thing to log. If we don't life is more complicated.
- * The problem is there are two clashing cases:
- *
- * (1) The poll name is a label. In that case we want the
- * log to show the via or true mailserver name.
- *
- * (2) The poll name is the true one, the via name is localhost.
- * This is going to be typical for ssh-using configurations.
- *
- * We're going to assume the via name is true unless it's
- * localhost.
- */
- if (ctl->server.via && strcmp(ctl->server.via, "localhost"))
- ctl->server.truename = xstrdup(ctl->server.via);
- else
- ctl->server.truename = xstrdup(ctl->server.names->id);
-
#ifdef HAVE_GETHOSTBYNAME
/*
- * This functions partly as an optimization and partly
- * as a probe to make sure our nameserver is still up.
- * The multidrop case (especially) needs it.
+ * This functions partly as a probe to make sure our
+ * nameserver is still up. The multidrop case
+ * (especially) needs it.
*/
if (ctl->server.preauthenticate==A_KERBEROS_V4 || MULTIDROP(ctl))
{
/* compute the canonical name of the host */
errno = 0;
- namerec = gethostbyname(ctl->server.truename);
+ namerec = gethostbyname(ctl->server.queryname);
if (namerec == (struct hostent *)NULL)
{
error(0, errno,
"skipping %s poll, ",
- ctl->server.names->id);
+ ctl->server.pollname);
if (errno)
{
if (errno == ENETUNREACH)
querystatus = query_host(ctl);
- if (querystatus == PS_SUCCESS)
+ if (querystatus == PS_SUCCESS) {
successes++;
-
- if (!check_only)
- update_str_lists(ctl);
+ if (!check_only)
+ update_str_lists(ctl);
+ }
#ifdef linux
if (ctl->server.monitor)
{
{
int implicitmode, st;
struct passwd *pw;
- struct query def_opts, *ctl, *mp;
+ struct query def_opts, *ctl;
memset(&def_opts, '\0', sizeof(struct query));
def_opts.smtp_socket = -1;
def_opts.server.protocol = P_AUTO;
def_opts.server.timeout = CLIENT_TIMEOUT;
def_opts.remotename = user;
- save_str(&def_opts.smtphunt, -1, fetchmailhost);
+ save_str(&def_opts.smtphunt, TRUE, fetchmailhost);
+ save_str(&def_opts.smtphunt, FALSE, "localhost");
/* this builds the host list */
if (prc_parse_file(rcfile, !versioninfo) != 0)
* record from command line and defaults
*/
for (ctl = querylist; ctl; ctl = ctl->next)
- if (str_in_list(&ctl->server.names, argv[optind]))
+ if (!strcmp(ctl->server.pollname, argv[optind])
+ || str_in_list(&ctl->server.akalist, argv[optind]))
goto foundit;
ctl = hostalloc(&cmd_opts);
- save_str(&ctl->server.names, -1, argv[optind]);
+ ctl->server.pollname = xstrdup(argv[optind]);
foundit:
ctl->active = TRUE;
}
/* if there's a defaults record, merge it and lose it */
- if (querylist && strcmp(querylist->server.names->id, "defaults") == 0)
+ if (querylist && strcmp(querylist->server.pollname, "defaults") == 0)
{
for (ctl = querylist->next; ctl; ctl = ctl->next)
optmerge(ctl, querylist);
/* don't allow a defaults record after the first */
for (ctl = querylist; ctl; ctl = ctl->next)
- if (ctl != querylist && strcmp(ctl->server.names->id, "defaults") == 0)
+ if (ctl != querylist && strcmp(ctl->server.pollname, "defaults") == 0)
exit(PS_SYNTAX);
/* merge in wired defaults, do sanity checks and prepare internal fields */
DEFAULT(ctl->server.uidl, FALSE);
#undef DEFAULT
- /* plug in the semi-standard way of indicating a mail address */
- if (ctl->server.envelope == (char *)NULL)
- ctl->server.envelope = "X-Envelope-To:";
+ /*
+ *
+ * Compute the true name of the mailserver host.
+ * There are two clashing cases here:
+ *
+ * (1) The poll name is a label, possibly on one of several
+ * poll configurations for the same host. In this case
+ * the `via' option will be present and give the true name.
+ *
+ * (2) The poll name is the true one, the via name is
+ * localhost. This is going to be typical for ssh-using
+ * configurations.
+ *
+ * We're going to assume the via name is true unless it's
+ * localhost.
+ *
+ * Each poll cycle, if we've got DNS, we'll try to canonicalize
+ * the name. This will function as a probe to ensure the
+ * host's nameserver is up.
+ */
+ if (ctl->server.via && strcmp(ctl->server.via, "localhost"))
+ ctl->server.queryname = xstrdup(ctl->server.via);
+ else
+ ctl->server.queryname = xstrdup(ctl->server.pollname);
+ ctl->server.truename = xstrdup(ctl->server.queryname);
/* if no folders were specified, set up the null one as default */
if (!ctl->mailboxes)
{
(void) fprintf(stderr,
"%s configuration invalid, port number cannot be negative",
- ctl->server.names->id);
+ ctl->server.pollname);
exit(PS_SYNTAX);
}
if (ctl->server.protocol == P_RPOP && ctl->server.port >= 1024)
{
(void) fprintf(stderr,
"%s configuration invalid, RPOP requires a privileged port",
- ctl->server.names->id);
+ ctl->server.pollname);
exit(PS_SYNTAX);
}
}
{
struct query *ctl;
- /*
- * Craig Metz, the RFC1938 one-time-password guy, points out:
- * "Remember that most kernels don't zero pages before handing them to the
- * next process and many kernels share pages between user and kernel space.
- * You'd be very surprised what you can find from a short program to do a
- * malloc() and then dump the contents of the pages you got. By zeroing
- * the secrets at end of run (earlier if you can), you make sure the next
- * guy can't get the password/pass phrase."
- *
- * Right you are, Craig!
- */
- for (ctl = querylist; ctl; ctl = ctl->next)
- if (ctl->password)
- memset(ctl->password, '\0', strlen(ctl->password));
-
/*
* Sending SMTP QUIT on signal is theoretically nice, but led to a
* subtle bug. If fetchmail was terminated by signal while it was
if (!check_only)
write_saved_lists(querylist, idfile);
+ /*
+ * Craig Metz, the RFC1938 one-time-password guy, points out:
+ * "Remember that most kernels don't zero pages before handing them to the
+ * next process and many kernels share pages between user and kernel space.
+ * You'd be very surprised what you can find from a short program to do a
+ * malloc() and then dump the contents of the pages you got. By zeroing
+ * the secrets at end of run (earlier if you can), you make sure the next
+ * guy can't get the password/pass phrase."
+ *
+ * Right you are, Craig!
+ */
+ for (ctl = querylist; ctl; ctl = ctl->next)
+ if (ctl->password)
+ memset(ctl->password, '\0', strlen(ctl->password));
+
+#if !defined(HAVE_ATEXIT) && !defined(HAVE_ON_EXIT)
+ unlockit();
+#endif
+
exit(successes ? PS_SUCCESS : querystatus);
}
{
int i, st;
- if (poll_interval && ctl->server.interval)
- {
- if (ctl->server.poll_count++ % ctl->server.interval)
- {
- if (outlevel == O_VERBOSE)
- fprintf(stderr,
- "fetchmail: interval not reached, not querying %s\n",
- ctl->server.names->id);
- return PS_NOMAIL;
- }
- }
-
if (outlevel == O_VERBOSE)
{
time_t now;
time(&now);
fprintf(stderr, "fetchmail: %s querying %s (protocol %s) at %s",
RELEASE_ID,
- ctl->server.names->id, showproto(ctl->server.protocol), ctime(&now));
+ ctl->server.pollname, showproto(ctl->server.protocol), ctime(&now));
}
switch (ctl->server.protocol) {
case P_AUTO:
for (i = 0; i < sizeof(autoprobe)/sizeof(autoprobe[0]); i++)
{
ctl->server.protocol = autoprobe[i];
- if ((st = query_host(ctl)) == PS_SUCCESS || st == PS_NOMAIL || st == PS_AUTHFAIL || st == PS_LOCKBUSY)
+ if ((st = query_host(ctl)) == PS_SUCCESS || st == PS_NOMAIL || st == PS_AUTHFAIL || st == PS_LOCKBUSY || st == PS_SMTP)
break;
}
ctl->server.protocol = P_AUTO;
/* display query parameters in English */
{
printf("Options for retrieving from %s@%s:\n",
- ctl->remotename, visbuf(ctl->server.names->id));
+ ctl->remotename, visbuf(ctl->server.pollname));
if (ctl->server.via)
printf(" Mail will be retrieved via %s\n", ctl->server.via);
ctl->server.interval);
if (ctl->server.truename)
printf(" True name of server is %s.\n", ctl->server.truename);
- if (ctl->server.names->next)
+ if (ctl->server.akalist)
{
struct idlist *idp;
printf(" Predeclared mailserver aliases:");
- for (idp = ctl->server.names->next; idp; idp = idp->next)
+ for (idp = ctl->server.akalist; idp; idp = idp->next)
printf(" %s", idp->id);
putchar('\n');
}
printf("\n");
}
if (ctl->preconnect)
- printf(" Server connection will be preinitialized with '%s.'\n", visbuf(ctl->preconnect));
+ printf(" Server connection will be brought up with '%s.'\n",
+ visbuf(ctl->preconnect));
+ else if (outlevel == O_VERBOSE)
+ printf(" No pre-connection command.\n");
+ if (ctl->postconnect)
+ printf(" Server connection will be taken down with '%s.'\n",
+ visbuf(ctl->postconnect));
else if (outlevel == O_VERBOSE)
- printf(" No preinitialization command.\n");
+ printf(" No post-connection command.\n");
if (!ctl->localnames)
printf(" No localnames declared for this host.\n");
else