X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=fetchmail.c;h=d720b04539172120dc902918a801dde91143f249;hb=910d5a2f852edb8c4e54c0e875da6a90385ab790;hp=2523f2bc48b1c7e103470da1414f39b6ed053dcf;hpb=6478e0c9185d2f37eb5efa95d0d726d77b2afb70;p=~andy%2Ffetchmail diff --git a/fetchmail.c b/fetchmail.c index 2523f2bc..d720b045 100644 --- a/fetchmail.c +++ b/fetchmail.c @@ -6,18 +6,12 @@ #include "config.h" #include -#if defined(STDC_HEADERS) #include -#endif -#if defined(HAVE_UNISTD_H) #include -#endif #include #include #include -#if defined(HAVE_SYSLOG) #include -#endif #include #ifdef __FreeBSD__ #include @@ -25,24 +19,20 @@ #include #include #include -#ifdef HAVE_SETRLIMIT #include -#endif /* HAVE_SETRLIMIT */ #ifdef HAVE_SOCKS #include /* SOCKSinit() */ #endif /* HAVE_SOCKS */ -#ifdef HAVE_LANGINFO_H #include -#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() */ @@ -84,8 +74,14 @@ static int activecount; /* count number of active entries */ 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 */ @@ -108,8 +104,8 @@ static void dropprivs(void) } #endif -#if defined(HAVE_SETLOCALE) && defined(ENABLE_NLS) && defined(HAVE_STRFTIME) #include +#if defined(ENABLE_NLS) /** returns timestamp in current locale, * and resets LC_TIME locale to POSIX. */ static char *timestamp (void) @@ -127,7 +123,7 @@ 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; @@ -137,8 +133,8 @@ static void printcopyright(FILE *fp) { 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 Sunil Shetye\n" + "Copyright (C) 2005 - 2013 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" @@ -151,10 +147,287 @@ static void printcopyright(FILE *fp) { 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; @@ -198,7 +471,6 @@ int main(int argc, char **argv) #define IDFILE_NAME ".fetchids" run.idfile = prependdir (IDFILE_NAME, fmhome); - outlevel = O_NORMAL; /* @@ -222,7 +494,7 @@ int main(int argc, char **argv) { 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); @@ -272,15 +544,12 @@ int main(int argc, char **argv) #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 */ ".\n"; printf(GT_("This is fetchmail release %s"), VERSION); fputs(features, stdout); @@ -304,21 +573,50 @@ int main(int argc, char **argv) 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 (run.logfile) { + /* nodetach -> turn off logfile option */ + if (nodetach) { + if (outlevel >= O_NORMAL) { fprintf(stderr, GT_("The nodetach option is in effect, ignoring logfile option.\n")); } + xfree(run.logfile); + } + +#if 0 + /* not in daemon mode -> turn off logfile option */ + if (0 == run.poll_interval) { + if (outlevel >= O_NORMAL) { fprintf(stderr, GT_("Not running in daemon mode, ignoring logfile option.\n")); } + xfree(run.logfile); + } +#endif + + /* log file not writable -> turn off logfile option */ + if (run.logfile && 0 != access(run.logfile, F_OK)) { + if (outlevel >= O_NORMAL) { fprintf(stderr, GT_("Logfile \"%s\" does not exist, ignoring logfile option.\n"), run.logfile); } + xfree(run.logfile); + } + + /* log file not writable -> turn off logfile option */ + if (run.logfile && 0 != access(run.logfile, W_OK)) { + fprintf(stderr, GT_("Logfile \"%s\" is not writable, aborting.\n"), run.logfile); + xfree(run.logfile); + exit(PS_UNDEFINED); + } } -#if defined(HAVE_SYSLOG) /* logging should be set up early in case we were restarted from exec */ if (run.use_syslog) { openlog(program_name, LOG_PID, LOG_MAIL); - report_init(-1); + /* precedence: logfile (if effective) overrides syslog. */ + if (run.logfile) { + syslog(LOG_ERR, GT_("syslog and logfile options are both set, ignoring syslog, and logging to %s"), run.logfile); + run.use_syslog = 0; + report_init((run.poll_interval == 0 || nodetach) && !run.logfile); /* when changing this, change copy below, too */ + } else { + report_init(-1); + } } else -#endif - report_init((run.poll_interval == 0 || nodetach) && !run.logfile); + report_init((run.poll_interval == 0 || nodetach) && !run.logfile); /* when changing this, change copy above, too */ #ifdef POP3_ENABLE /* initialize UID handling */ @@ -335,7 +633,6 @@ int main(int argc, char **argv) /* 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 @@ -348,7 +645,6 @@ int main(int argc, char **argv) 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. */ @@ -494,17 +790,23 @@ int main(int argc, char **argv) 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 %ld awakened.\n"), - (long)pid); + if (outlevel > O_SILENT) + fprintf(stderr, + GT_("fetchmail: background fetchmail at %ld awakened.\n"), + (long)pid); return(0); } else @@ -593,14 +895,12 @@ int main(int argc, char **argv) else { /* not in daemon mode */ - if (run.logfile && !nodetach && access(run.logfile, F_OK) == 0) - { + if (run.logfile) + { 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")); } } @@ -635,6 +935,11 @@ int main(int argc, char **argv) * leaks... */ struct stat rcstat; +#ifdef HAVE_LIBPWMD + time_t now; + + time(&now); +#endif if (strcmp(rcfile, "-") == 0) { /* do nothing */ @@ -644,7 +949,15 @@ int main(int argc, char **argv) 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); @@ -737,6 +1050,19 @@ int main(int argc, char **argv) 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)) @@ -805,6 +1131,12 @@ int main(int argc, char **argv) } } +#ifdef HAVE_LIBPWMD + if (pwm) { + pwmd_close(pwm); + pwm = NULL; + } +#endif /* close connections cleanly */ terminate_poll(0); @@ -928,7 +1260,6 @@ static void optmerge(struct query *h2, struct query *h1, int force) FLAG_MERGE(server.skip); FLAG_MERGE(server.dns); FLAG_MERGE(server.checkalias); - FLAG_MERGE(server.uidl); FLAG_MERGE(server.principal); #ifdef CAN_MONITOR @@ -941,6 +1272,7 @@ static void optmerge(struct query *h2, struct query *h1, int force) FLAG_MERGE(server.plugout); FLAG_MERGE(server.tracepolls); FLAG_MERGE(server.badheader); + FLAG_MERGE(server.retrieveerror); FLAG_MERGE(wildcard); FLAG_MERGE(remotename); @@ -1050,8 +1382,36 @@ static int load_params(int argc, char **argv, int optind) 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++) @@ -1072,6 +1432,26 @@ static int load_params(int argc, char **argv, int 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) @@ -1082,8 +1462,31 @@ static int load_params(int argc, char **argv, int optind) * 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; } @@ -1159,7 +1562,6 @@ static int load_params(int argc, char **argv, int optind) 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); @@ -1219,7 +1621,6 @@ static int load_params(int argc, char **argv, int optind) 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); @@ -1235,12 +1636,6 @@ static int load_params(int argc, char **argv, int optind) } #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")); @@ -1274,14 +1669,6 @@ static int load_params(int argc, char **argv, int optind) 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" @@ -1312,13 +1699,6 @@ static int load_params(int argc, char **argv, int optind) 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) { @@ -1367,7 +1747,7 @@ static int load_params(int argc, char **argv, int optind) return(implicitmode); } -static RETSIGTYPE terminate_poll(int sig) +static void terminate_poll(int sig) /* to be executed at the end of a poll cycle */ { @@ -1385,7 +1765,7 @@ static RETSIGTYPE terminate_poll(int sig) #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; @@ -1407,9 +1787,6 @@ static RETSIGTYPE terminate_run(int sig) if (ctl->password) memset(ctl->password, '\0', strlen(ctl->password)); -#if !defined(HAVE_ATEXIT) - fm_lock_release(); -#endif if (activecount == 0) exit(PS_NOMAIL); @@ -1464,8 +1841,6 @@ static int query_host(struct query *ctl) ctl->server.protocol = P_AUTO; break; case P_POP3: - case P_APOP: - case P_RPOP: #ifdef POP3_ENABLE do { st = doPOP3(ctl); @@ -1522,6 +1897,13 @@ static int query_host(struct query *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 */ @@ -1534,10 +1916,8 @@ static void dump_params (struct runctl *runp, 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) @@ -1583,22 +1963,14 @@ static void dump_params (struct runctl *runp, 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 @@ -1607,8 +1979,6 @@ static void dump_params (struct runctl *runp, 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) @@ -1634,15 +2004,17 @@ static void dump_params (struct runctl *runp, 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); @@ -1923,20 +2295,15 @@ static void dump_params (struct runctl *runp, 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); } } @@ -1955,6 +2322,19 @@ static void dump_params (struct runctl *runp, 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"), visbuf(ctl->properties));