diff -ruN a/configure.ac b/configure.ac
--- a/configure.ac	2007-01-04 15:35:45.000000000 -0500
+++ b/configure.ac	2007-01-21 08:38:53.000000000 -0500
@@ -251,6 +251,22 @@
 AC_MSG_RESULT(root-mode pid file will go in $dir)
 AC_DEFINE_UNQUOTED(PID_DIR, "$dir", directory for PID lock files)
 
+AC_ARG_ENABLE(pwmd,
+	[  --enable-pwmd           enable Password Manager Daemon support],
+	, [enable_pwmd=no])
+
+if test "$enable_pwmd" = "yes"; then
+    PKG_CHECK_EXISTS([libpwmd], have_libpwmd=1,
+		     AC_MSG_ERROR([Could not find libpwmd pkg-config module.]))
+
+
+    PKG_CHECK_MODULES([libpwmd], [libpwmd >= 2.0.0])
+    AM_CONDITIONAL(HAVE_LIBPWMD, true)
+    AC_DEFINE(HAVE_LIBPWMD, 1, [Define if you have libPWMD installed.])
+else
+    AM_CONDITIONAL(HAVE_LIBPWMD, false)
+fi
+
 # We may have a fallback MDA available in case the socket open to the 
 # local SMTP listener fails.  Best to use procmail for this, as we know
 # it won't try delivering through local SMTP and cause a mail loop.
diff -ruN a/fetchmail.c b/fetchmail.c
--- a/fetchmail.c	2006-12-18 19:15:52.000000000 -0500
+++ b/fetchmail.c	2007-01-21 08:35:13.000000000 -0500
@@ -145,6 +145,74 @@
 
 const char *iana_charset;
 
+#ifdef HAVE_LIBPWMD
+static void exit_with_pwmd_error()
+{
+    if (pwmd_ret == PWMD_PERROR) {
+	fprintf(stderr, GT_("pwmd: %s\n"), pwmd_strerror(pwmd_error));
+	exit(PS_AUTHFAIL);
+    }
+    else if (pwmd_ret == PWMD_AGENT_ERROR) {
+	fprintf(stderr, GT_("pwmd: gpg-agent error. Is GPG_AGENT_INFO set? Read gpg-agent(1) for mor info.\n"));
+	exit(PS_AUTHFAIL);
+    }
+    else
+	fprintf(stderr, GT_("pwmd: %s\n"), strerror(pwmd_error));
+
+    exit(PS_UNDEFINED);
+}
+
+static void pwmd_set_agent_strings(const char *filename)
+{
+    /*
+     * Use gpg-agent for password retrieval. Since version 0.3 of pwmd
+     * there is an option to push files into the file cache when the
+     * server starts up. For a daemonized fetchmail, this may be
+     * required because there won't be a way to get the key without a
+     * tty.
+     */
+    if ((pwmd_ret = pwmd_command(pwm, &pwmd_result, &pwmd_error, PWMD_SETOPT,
+		    PWMD_OPTION_USEAGENT, 1)) != PWMD_OK)
+	exit_with_pwmd_error();
+
+    /*
+     * Set the text to be used in the pinentry dialog.
+     */
+    if ((pwmd_ret = pwmd_command(pwm, &pwmd_result, &pwmd_error, PWMD_SETOPT,
+		    PWMD_OPTION_TITLE, 
+		    "Password Manager Daemon: Fetchmail")) != PWMD_OK)
+	exit_with_pwmd_error();
+
+    snprintf(pwmd_buf, sizeof(pwmd_buf), 
+	    "A password is needed to open the file \"%s\". Please\n"
+	    "enter the password below.", filename);
+
+    if ((pwmd_ret = pwmd_command(pwm, &pwmd_result, &pwmd_error, PWMD_SETOPT,
+		    PWMD_OPTION_DESC, pwmd_buf)) != PWMD_OK)
+	exit_with_pwmd_error();
+}
+
+static void pwmd_do_connect(const char *socketname, const char *filename)
+{
+    /*
+     * Try and connect to pwmd.
+     */
+    if ((pwm = pwmd_connect(socketname, &pwmd_error)) == NULL)
+	exit_with_pwmd_error();
+
+    pwmd_set_agent_strings(filename);
+
+    /*
+     * Try and open the file so we can later get account/server credentials. If
+     * the file is not cached on the server, gpg-agent will ask for the
+     * password.
+     */
+    if ((pwmd_ret = pwmd_command(pwm, &pwmd_result, &pwmd_error, PWMD_OPEN,
+		    filename)) != PWMD_OK)
+	exit_with_pwmd_error();
+}
+#endif
+
 int main(int argc, char **argv)
 {
     int bkgd = FALSE;
@@ -275,6 +343,9 @@
 #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);
@@ -987,6 +1058,182 @@
 #undef FLAG_MERGE
 }
 
+#ifdef HAVE_LIBPWMD
+static char *protocol_to_service(int protocol)
+{
+    switch (protocol) {
+#ifdef POP2_ENABLE
+	case P_POP2:
+	    return "POP2";
+#endif
+#ifdef POP3_ENABLE
+	case P_POP3:
+	    return "POP3";
+#endif
+#ifdef IMAP_ENABLE
+	case P_IMAP:
+	    return "IMAP";
+#endif
+	case P_APOP:
+	    return "APOP";
+	case P_RPOP:
+	    return "RPOP";
+	case P_ETRN:
+	    return "ETRN";
+	case P_ODMR:
+	    return "ODMR";
+	default:
+	    return NULL;
+    }
+
+    return NULL;
+}
+
+static int pwmd_get_details(const char *pwmd_account, int protocol,
+	struct query *ctl)
+{
+    char *prot = protocol_to_service(protocol);
+    char *p;
+
+    /*
+     * Get the hostname for this protocol. Element path must be
+     * account->[protocol]->hostname.
+     */
+    snprintf(pwmd_buf, sizeof(pwmd_buf), 
+	    "GET %s\t%s\thostname\n", pwmd_account, prot);
+
+    if ((pwmd_ret = pwmd_command(pwm, &pwmd_result, &pwmd_error,
+		    PWMD_COMMAND, pwmd_buf)) != PWMD_OK) {
+	if (pwmd_ret == PWMD_PERROR && pwmd_error == EPWMD_ELEMENT_NOT_FOUND) {
+	    fprintf(stderr, GT_("%s (hostname): %s\n"), pwmd_account,
+		    pwmd_strerror(pwmd_error));
+	    exit(PS_SYNTAX);
+	}
+	else
+	    exit_with_pwmd_error();
+    }
+
+    ctl->server.pollname = xstrdup(pwmd_account);
+    ctl->server.via = xstrdup(pwmd_result);
+    memset(pwmd_result, 0, strlen(pwmd_result));
+    free(pwmd_result);
+
+    /*
+     * Server port. Element path must be account->[protocol]->port. Should be
+     * required because the element path wouldn't exist with out it. But
+     * maybe not because fetchmail trys standard ports if not specified. This
+     * may be a security risk. Might be better to have 'ssl' required.
+     */
+    snprintf(pwmd_buf, sizeof(pwmd_buf), "GET %s\t%s\tport\n",
+	    pwmd_account, prot);
+
+    if ((pwmd_ret = pwmd_command(pwm, &pwmd_result, &pwmd_error,
+		    PWMD_COMMAND, pwmd_buf)) != PWMD_OK) {
+	if (pwmd_ret == PWMD_PERROR && pwmd_error == EPWMD_ELEMENT_NOT_FOUND) {
+	    fprintf(stderr, GT_("%s (port): %s\n"), pwmd_account,
+		    pwmd_strerror(pwmd_error));
+	    exit(PS_SYNTAX);
+	}
+	else
+	    exit_with_pwmd_error();
+    }
+
+    p = xstrdup(pwmd_result);
+    ctl->server.service = p;
+    memset(pwmd_result, 0, strlen(pwmd_result));
+    free(pwmd_result);
+
+    /*
+     * Get the remote username. Element must be account->username.
+     */
+    snprintf(pwmd_buf, sizeof(pwmd_buf), "GET %s\tusername\n",
+	    pwmd_account);
+
+    if ((pwmd_ret = pwmd_command(pwm, &pwmd_result, &pwmd_error,
+		    PWMD_COMMAND, pwmd_buf)) != PWMD_OK) {
+	if (pwmd_ret == PWMD_PERROR && pwmd_error == EPWMD_ELEMENT_NOT_FOUND)
+	    fprintf(stderr, GT_("%s (username): %s\n"), pwmd_account,
+		    pwmd_strerror(pwmd_error));
+	else
+	    exit_with_pwmd_error();
+    }
+    else {
+	ctl->remotename = xstrdup(pwmd_result);
+	ctl->server.esmtp_name = xstrdup(ctl->remotename);
+	memset(pwmd_result, 0, strlen(pwmd_result));
+	free(pwmd_result);
+    }
+
+    /*
+     * Get the remote password. Element must be account->password.
+     */
+    snprintf(pwmd_buf, sizeof(pwmd_buf), "GET %s\tpassword\n",
+	    pwmd_account);
+
+    if ((pwmd_ret = pwmd_command(pwm, &pwmd_result, &pwmd_error,
+		    PWMD_COMMAND, pwmd_buf)) != PWMD_OK)
+	if (pwmd_ret == PWMD_PERROR && pwmd_error == EPWMD_ELEMENT_NOT_FOUND)
+	    fprintf(stderr, GT_("%s (password): %s\n"), pwmd_account,
+		    pwmd_strerror(pwmd_error));
+	else
+	    exit_with_pwmd_error();
+    else {
+	ctl->password= xstrdup(pwmd_result);
+	memset(pwmd_result, 0, strlen(pwmd_result));
+	free(pwmd_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.
+     */
+    snprintf(pwmd_buf, sizeof(pwmd_buf), "GET %s\t%s\tssl\n",
+	    pwmd_account, prot);
+
+    if ((pwmd_ret = pwmd_command(pwm, &pwmd_result, &pwmd_error,
+		    PWMD_COMMAND, pwmd_buf)) != PWMD_OK) {
+	if (pwmd_ret == PWMD_PERROR && pwmd_error == EPWMD_ELEMENT_NOT_FOUND)
+	    fprintf(stderr, GT_("%s (ssl): %s\n"), pwmd_account,
+		    pwmd_strerror(pwmd_error));
+	else
+	    exit_with_pwmd_error();
+    }
+    else {
+	p = xstrdup(pwmd_result);
+	ctl->use_ssl = atoi(p);
+	ctl->use_ssl = (ctl->use_ssl >= 1) ? FLAG_TRUE : FLAG_FALSE;
+	memset(pwmd_result, 0, strlen(pwmd_result));
+	free(pwmd_result);
+	free(p);
+    }
+
+    /*
+     * account->[protocol]->sslfingerprint.
+     */
+    snprintf(pwmd_buf, sizeof(pwmd_buf),
+	    "GET %s\t%s\tsslfingerprint\n", pwmd_account, prot);
+
+    if ((pwmd_ret = pwmd_command(pwm, &pwmd_result, &pwmd_error,
+		    PWMD_COMMAND, pwmd_buf)) != PWMD_OK) {
+	if (pwmd_ret == PWMD_PERROR && pwmd_error == EPWMD_ELEMENT_NOT_FOUND)
+	    fprintf(stderr, GT_("%s (sslfingerprint): %s\n"), pwmd_account,
+		    pwmd_strerror(pwmd_error));
+	else
+	    exit_with_pwmd_error();
+    }
+    else {
+	p = xstrdup(pwmd_result);
+	ctl->sslfingerprint = p;
+	memset(pwmd_result, 0, strlen(pwmd_result));
+	free(pwmd_result);
+    }
+#endif
+
+    return 0;
+}
+#endif
+
 /** Load configuration files.
  * \return - true if no servers found on the command line
  *         - false if servers found on the command line */
@@ -1044,8 +1291,30 @@
 
     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) {
+		    fprintf(stderr, GT_("fetchmail: %s configuration invalid, pwmd_file requires a protocol specification\n"),
+			    ctl->server.pollname);
+		    exit(PS_SYNTAX);
+		}
+
+		pwmd_do_connect(ctl->pwmd_socket, ctl->pwmd_file);
+		pwmd_get_details(ctl->server.pollname, 
+			ctl->server.protocol, ctl);
+		pwmd_close(pwm);
+	    }
+	}
+#else
 	for (ctl = querylist; ctl; ctl = ctl->next)
 	    ctl->active = !ctl->server.skip;
+#endif
     }
     else
 	for (; optind < argc; optind++) 
@@ -1066,6 +1335,24 @@
 			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) {
+			    fprintf(stderr, GT_("fetchmail: %s configuration invalid, pwmd_file requires a protocol specification\n"),
+				   ctl->server.pollname);
+			    exit(PS_SYNTAX);
+			}
+
+			pwmd_do_connect(ctl->pwmd_socket, ctl->pwmd_file);
+			pwmd_get_details(ctl->server.pollname, 
+				ctl->server.protocol, ctl);
+			pwmd_close(pwm);
+		    }
+#endif
 		}
 
 	    if (!predeclared)
@@ -1076,8 +1363,29 @@
 		 * call later on.
 		 */
 		ctl = hostalloc((struct query *)NULL);
-		ctl->server.via =
-		    ctl->server.pollname = xstrdup(argv[optind]);
+
+#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) {
+			fprintf(stderr, GT_("Option --pwmd-file needs a service (-p) parameter.\n"));
+			exit(PS_SYNTAX);
+		    }
+
+		    pwmd_do_connect(cmd_opts.pwmd_socket, cmd_opts.pwmd_file);
+		    pwmd_get_details(argv[optind], cmd_opts.server.protocol,
+			    ctl);
+		    pwmd_close(pwm);
+		}
+		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;
 	    }
diff -ruN a/fetchmail.h b/fetchmail.h
--- a/fetchmail.h	2006-12-15 19:42:14.000000000 -0500
+++ b/fetchmail.h	2007-01-21 08:35:13.000000000 -0500
@@ -39,6 +39,10 @@
 #  include "trio/trio.h"
 #endif
 
+#ifdef HAVE_LIBPWMD
+#include <libpwmd.h>
+#endif
+
 /* We need this for strstr */
 #if !defined(HAVE_STRSTR) && !defined(strstr)
 char *strstr(const char *, const char *);
@@ -313,6 +317,11 @@
     char *password;		/* remote password to use */
     struct idlist *mailboxes;	/* list of mailboxes to check */
 
+#ifdef HAVE_LIBPWMD
+    char *pwmd_socket;		/* socket to connect to */
+    char *pwmd_file;		/* file to open on the server */
+#endif
+
     /* per-forwarding-target data */
     struct idlist *smtphunt;	/* list of SMTP hosts to try forwarding to */
     struct idlist *domainlist;	/* domainlist to fetch from */
@@ -455,6 +464,13 @@
 extern char *sdps_envfrom;
 extern char *sdps_envto;
 #endif /* SDPS_ENABLE */
+#ifdef HAVE_LIBPWMD
+pwm_t *pwm;			/* the handle */
+char *pwmd_result;		/* server result */
+int pwmd_error;			/* protocol or errno */
+int pwmd_ret;			/* return value from pwmd_command() */
+char pwmd_buf[LINE_MAX];	/* element copy buffer */
+#endif
 
 extern const char *iana_charset;	/* IANA assigned charset name */
 
diff -ruN a/Makefile.am b/Makefile.am
--- a/Makefile.am	2007-01-05 16:27:52.000000000 -0500
+++ b/Makefile.am	2007-01-21 08:35:13.000000000 -0500
@@ -18,6 +18,11 @@
 pys=			fetchmailconf.py
 pym=			fetchmailconf.man
 
+if HAVE_LIBPWMD
+CFLAGS += @libpwmd_CFLAGS@
+LDFLAGS += @libpwmd_LIBS@
+endif
+
 if HAVE_PYTHON
 nodist_bin_SCRIPTS=	fetchmailconf
 python_PYTHON=		$(pys)
diff -ruN a/options.c b/options.c
--- a/options.c	2006-08-14 19:04:02.000000000 -0400
+++ b/options.c	2007-01-21 08:35:13.000000000 -0500
@@ -53,12 +53,21 @@
     LA_IDLE
 };
 
+#ifdef HAVE_LIBPWMD
+static const char *shortoptions = 
+	"C:G:?Vcsvd:NqL:f:i:p:UP:A:t:E:Q:u:akKFnl:r:S:Z:b:B:e:m:I:M:yw:D:";
+#else
 /* options still left: CgGhHjJoORTWxXYz */
 static const char *shortoptions = 
 	"?Vcsvd:NqL:f:i:p:UP:A:t:E:Q:u:akKFnl:r:S:Z:b:B:e:m:I:M:yw:D:";
+#endif
 
 static const struct option longoptions[] = {
 /* this can be const because all flag fields are 0 and will never get set */
+#ifdef HAVE_LIBPWMD
+  {"pwmd-socket",      required_argument,         (int *) 0, 'C' },
+  {"pwmd-file",        required_argument,         (int *) 0, 'G' },
+#endif
   {"help",	no_argument,	   (int *) 0, '?' },
   {"version",	no_argument,	   (int *) 0, 'V' },
   {"check",	no_argument,	   (int *) 0, 'c' },
@@ -248,6 +257,14 @@
 			    longoptions, &option_index)) != -1)
     {
 	switch (c) {
+#ifdef HAVE_LIBPWMD
+	case 'C':
+	    ctl->pwmd_socket = prependdir(optarg, currentwd);
+	    break;
+	case 'G':
+	    ctl->pwmd_file = xstrdup(optarg);
+	    break;
+#endif
 	case 'V':
 	    versioninfo = TRUE;
 	    break;
@@ -618,6 +635,11 @@
 	P(GT_("      --plugout     specify external command to open smtp connection\n"));
 
 	P(GT_("  -p, --protocol    specify retrieval protocol (see man page)\n"));
+#ifdef HAVE_LIBPWMD
+        P(GT_("  -C, --pwmd-socket pwmd socket path (~/.pwmd/socket)\n"));
+        P(GT_("  -G, --pwmd-file   filename to use on the pwmd server\n"));
+#endif
+ 
 	P(GT_("  -U, --uidl        force the use of UIDLs (pop3 only)\n"));
 	P(GT_("      --port        TCP port to connect to (obsolete, use --service)\n"));
 	P(GT_("  -P, --service     TCP service to connect to (can be numeric TCP port)\n"));
diff -ruN a/rcfile_l.l b/rcfile_l.l
--- a/rcfile_l.l	2006-08-14 19:04:02.000000000 -0400
+++ b/rcfile_l.l	2007-01-21 08:35:13.000000000 -0500
@@ -114,6 +114,8 @@
 
 
 user(name)?	{SETSTATE(NAME); return USERNAME; }
+pwmd_socket	{ return PWMD_SOCKET; }
+pwmd_file	{ return PWMD_FILE; }
 <INITIAL,NAME>pass(word)?	{SETSTATE(NAME); return PASSWORD; }
 folder(s)? 	{ return FOLDER; }
 smtp(host)?	{ return SMTPHOST; }
diff -ruN a/rcfile_y.y b/rcfile_y.y
--- a/rcfile_y.y	2006-12-08 07:09:09.000000000 -0500
+++ b/rcfile_y.y	2007-01-21 08:44:03.000000000 -0500
@@ -63,7 +63,7 @@
 
 %token DEFAULTS POLL SKIP VIA AKA LOCALDOMAINS PROTOCOL
 %token AUTHENTICATE TIMEOUT KPOP SDPS ENVELOPE QVIRTUAL
-%token USERNAME PASSWORD FOLDER SMTPHOST FETCHDOMAINS MDA BSMTP LMTP
+%token PWMD_SOCKET PWMD_FILE USERNAME PASSWORD FOLDER SMTPHOST FETCHDOMAINS MDA BSMTP LMTP
 %token SMTPADDRESS SMTPNAME SPAMRESPONSE PRECONNECT POSTCONNECT LIMIT WARNINGS
 %token INTERFACE MONITOR PLUGIN PLUGOUT
 %token IS HERE THERE TO MAP WILDCARD
@@ -243,6 +243,20 @@
 userdef		: USERNAME STRING	{current.remotename = xstrdup($2);}
 		| USERNAME mapping_list HERE
 		| USERNAME STRING THERE	{current.remotename = xstrdup($2);}
+		| PWMD_SOCKET STRING	{
+#ifdef HAVE_LIBPWMD
+		    current.pwmd_socket = xstrdup($2);
+#else
+		    yyerror(GT_("pwmd not enabled"));
+#endif 
+					}
+		| PWMD_FILE STRING	{
+#ifdef HAVE_LIBPWMD
+		    current.pwmd_file = xstrdup($2);
+#else
+		    yyerror(GT_("pwmd not enabled"));
+#endif 
+					}
 		;
 
 user0opts	: /* EMPTY */
diff -ruN a/README.pwmd b/README.pwmd
--- a/README.pwmd	1969-12-31 19:00:00.000000000 -0500
+++ b/README.pwmd	2007-01-21 08:35:13.000000000 -0500
@@ -0,0 +1,33 @@
+When compiled with pwmd (Password Manager Daemon) support (--enable-pwmd),
+fetchmail can retrieve server details from pwmd. Two new configuration
+parameters are added: pwmd_socket, to specify the socket to connect to, and
+pwmd_file (required) which specifies the filename on the server to open.
+
+The data that fetchmail will use is stored in an encrypted XML file and has
+the following structure:
+
+    <account name="pollname">
+	<username>		- Optional (--username/username)
+	<password>		- Optional (--password/password)
+	<protocol>		- POP3/IMAP/etc.
+	    <hostname>		- Required (servername/via)
+	    <port>		- Required (--service/protocol)
+	    <ssl>		- Optional (--ssl/ssl)
+	    <sslfingerprint>	- Optional (--sslfingerprint/sslfingerprint)
+	</protocol>
+    </account>
+
+A minimal fetchmailrc might look like this:
+
+poll isp proto POP3:
+    pwmd_file default
+
+Or from the command line:
+    fetchmail -f fetchmailrc isp
+    fetchmail --pwmd-file somefile -p POP3 isp
+
+The password to open the encrypted data file is either cached on the server
+(the file has been opened before), or gotten from gpg-agent(1).
+
+Ben Kibbey <bjk@luxsci.net>
+http://bjk.sourceforge.net/pwmd/.
