diff --git a/src/common/username.c b/src/common/username.c
index ee5ef1c..ac9a898 100644
*** a/src/common/username.c
--- b/src/common/username.c
*************** get_user_name(char **errstr)
*** 58,64 ****
  
  	if (!GetUserName(username, &len))
  	{
! 		*errstr = psprintf(_("user name lookup failure: %s"), strerror(errno));
  		return NULL;
  	}
  
--- 58,65 ----
  
  	if (!GetUserName(username, &len))
  	{
! 		*errstr = psprintf(_("user name lookup failure: error code %lu"),
! 						   GetLastError());
  		return NULL;
  	}
  
diff --git a/src/include/port.h b/src/include/port.h
index 1d53e4e..26d7fcd 100644
*** a/src/include/port.h
--- b/src/include/port.h
*************** extern void srandom(unsigned int seed);
*** 433,439 ****
  /* thread.h */
  extern char *pqStrerror(int errnum, char *strerrbuf, size_t buflen);
  
! #if !defined(WIN32) || defined(__CYGWIN__)
  extern int pqGetpwuid(uid_t uid, struct passwd * resultbuf, char *buffer,
  		   size_t buflen, struct passwd ** result);
  #endif
--- 433,439 ----
  /* thread.h */
  extern char *pqStrerror(int errnum, char *strerrbuf, size_t buflen);
  
! #ifndef WIN32
  extern int pqGetpwuid(uid_t uid, struct passwd * resultbuf, char *buffer,
  		   size_t buflen, struct passwd ** result);
  #endif
diff --git a/src/interfaces/libpq/fe-auth.c b/src/interfaces/libpq/fe-auth.c
index 179793e..5a6a1e4 100644
*** a/src/interfaces/libpq/fe-auth.c
--- b/src/interfaces/libpq/fe-auth.c
*************** pg_fe_sendauth(AuthRequest areq, PGconn 
*** 714,735 ****
  /*
   * pg_fe_getauthname
   *
!  * Returns a pointer to dynamic space containing whatever name the user
!  * has authenticated to the system.  If there is an error, return NULL.
   */
  char *
! pg_fe_getauthname(void)
  {
  	const char *name = NULL;
- 	char	   *authn;
  
  #ifdef WIN32
! 	char		username[128];
  	DWORD		namesize = sizeof(username) - 1;
  #else
  	char		pwdbuf[BUFSIZ];
  	struct passwd pwdstr;
  	struct passwd *pw = NULL;
  #endif
  
  	/*
--- 714,738 ----
  /*
   * pg_fe_getauthname
   *
!  * Returns a pointer to malloc'd space containing whatever name the user
!  * has authenticated to the system.  If there is an error, return NULL,
!  * and put a suitable error message in *errorMessage if that's not NULL.
   */
  char *
! pg_fe_getauthname(PQExpBuffer errorMessage)
  {
+ 	char	   *result = NULL;
  	const char *name = NULL;
  
  #ifdef WIN32
! 	char		username[256];
  	DWORD		namesize = sizeof(username) - 1;
  #else
+ 	uid_t		user_id = geteuid();
  	char		pwdbuf[BUFSIZ];
  	struct passwd pwdstr;
  	struct passwd *pw = NULL;
+ 	int			pwerr;
  #endif
  
  	/*
*************** pg_fe_getauthname(void)
*** 741,764 ****
  	 */
  	pglock_thread();
  
- 	/*
- 	 * We document PQconndefaults() to return NULL for a memory allocation
- 	 * failure.  We don't have an API to return a user name lookup failure, so
- 	 * we just assume it always succeeds.
- 	 */
  #ifdef WIN32
  	if (GetUserName(username, &namesize))
  		name = username;
  #else
! 	if (pqGetpwuid(geteuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pw) == 0)
  		name = pw->pw_name;
  #endif
  
! 	authn = name ? strdup(name) : NULL;
  
  	pgunlock_thread();
  
! 	return authn;
  }
  
  
--- 744,785 ----
  	 */
  	pglock_thread();
  
  #ifdef WIN32
  	if (GetUserName(username, &namesize))
  		name = username;
+ 	else if (errorMessage)
+ 		printfPQExpBuffer(errorMessage,
+ 				 libpq_gettext("user name lookup failure: error code %lu\n"),
+ 						  GetLastError());
  #else
! 	pwerr = pqGetpwuid(user_id, &pwdstr, pwdbuf, sizeof(pwdbuf), &pw);
! 	if (pw != NULL)
  		name = pw->pw_name;
+ 	else if (errorMessage)
+ 	{
+ 		if (pwerr != 0)
+ 			printfPQExpBuffer(errorMessage,
+ 				   libpq_gettext("could not look up local user ID %d: %s\n"),
+ 							  (int) user_id,
+ 							  pqStrerror(pwerr, pwdbuf, sizeof(pwdbuf)));
+ 		else
+ 			printfPQExpBuffer(errorMessage,
+ 					 libpq_gettext("local user with ID %d does not exist\n"),
+ 							  (int) user_id);
+ 	}
  #endif
  
! 	if (name)
! 	{
! 		result = strdup(name);
! 		if (result == NULL && errorMessage)
! 			printfPQExpBuffer(errorMessage,
! 							  libpq_gettext("out of memory\n"));
! 	}
  
  	pgunlock_thread();
  
! 	return result;
  }
  
  
diff --git a/src/interfaces/libpq/fe-auth.h b/src/interfaces/libpq/fe-auth.h
index 59b6c16..8d35767 100644
*** a/src/interfaces/libpq/fe-auth.h
--- b/src/interfaces/libpq/fe-auth.h
***************
*** 19,24 ****
  
  
  extern int	pg_fe_sendauth(AuthRequest areq, PGconn *conn);
! extern char *pg_fe_getauthname(void);
  
  #endif   /* FE_AUTH_H */
--- 19,24 ----
  
  
  extern int	pg_fe_sendauth(AuthRequest areq, PGconn *conn);
! extern char *pg_fe_getauthname(PQExpBuffer errorMessage);
  
  #endif   /* FE_AUTH_H */
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index b2f556c..25961b1 100644
*** a/src/interfaces/libpq/fe-connect.c
--- b/src/interfaces/libpq/fe-connect.c
*************** static bool
*** 765,774 ****
  connectOptions2(PGconn *conn)
  {
  	/*
  	 * If database name was not given, default it to equal user name
  	 */
! 	if ((conn->dbName == NULL || conn->dbName[0] == '\0')
! 		&& conn->pguser != NULL)
  	{
  		if (conn->dbName)
  			free(conn->dbName);
--- 765,790 ----
  connectOptions2(PGconn *conn)
  {
  	/*
+ 	 * If user name was not given, fetch it.  (Most likely, the fetch will
+ 	 * fail, since the only way we get here is if pg_fe_getauthname() failed
+ 	 * during conninfo_add_defaults().  But now we want an error message.)
+ 	 */
+ 	if (conn->pguser == NULL || conn->pguser[0] == '\0')
+ 	{
+ 		if (conn->pguser)
+ 			free(conn->pguser);
+ 		conn->pguser = pg_fe_getauthname(&conn->errorMessage);
+ 		if (!conn->pguser)
+ 		{
+ 			conn->status = CONNECTION_BAD;
+ 			return false;
+ 		}
+ 	}
+ 
+ 	/*
  	 * If database name was not given, default it to equal user name
  	 */
! 	if (conn->dbName == NULL || conn->dbName[0] == '\0')
  	{
  		if (conn->dbName)
  			free(conn->dbName);
*************** keep_going:						/* We will come back to
*** 1967,1972 ****
--- 1983,1989 ----
  					char		pwdbuf[BUFSIZ];
  					struct passwd pass_buf;
  					struct passwd *pass;
+ 					int			passerr;
  					uid_t		uid;
  					gid_t		gid;
  
*************** keep_going:						/* We will come back to
*** 1987,1999 ****
  						goto error_return;
  					}
  
! 					pqGetpwuid(uid, &pass_buf, pwdbuf, sizeof(pwdbuf), &pass);
! 
  					if (pass == NULL)
  					{
! 						appendPQExpBuffer(&conn->errorMessage,
! 										  libpq_gettext("local user with ID %d does not exist\n"),
! 										  (int) uid);
  						goto error_return;
  					}
  
--- 2004,2021 ----
  						goto error_return;
  					}
  
! 					passerr = pqGetpwuid(uid, &pass_buf, pwdbuf, sizeof(pwdbuf), &pass);
  					if (pass == NULL)
  					{
! 						if (passerr != 0)
! 							appendPQExpBuffer(&conn->errorMessage,
! 											  libpq_gettext("could not look up local user ID %d: %s\n"),
! 											  (int) uid,
! 											  pqStrerror(passerr, sebuf, sizeof(sebuf)));
! 						else
! 							appendPQExpBuffer(&conn->errorMessage,
! 											  libpq_gettext("local user with ID %d does not exist\n"),
! 											  (int) uid);
  						goto error_return;
  					}
  
*************** conninfo_add_defaults(PQconninfoOption *
*** 4605,4622 ****
  		}
  
  		/*
! 		 * Special handling for "user" option
  		 */
  		if (strcmp(option->keyword, "user") == 0)
  		{
! 			option->val = pg_fe_getauthname();
! 			if (!option->val)
! 			{
! 				if (errorMessage)
! 					printfPQExpBuffer(errorMessage,
! 									  libpq_gettext("out of memory\n"));
! 				return false;
! 			}
  			continue;
  		}
  	}
--- 4627,4641 ----
  		}
  
  		/*
! 		 * Special handling for "user" option.  Note that if pg_fe_getauthname
! 		 * fails, we just leave the value as NULL; there's no need for this to
! 		 * be an error condition if the caller provides a user name.  The only
! 		 * reason we do this now at all is so that callers of PQconndefaults
! 		 * will see a correct default (barring error, of course).
  		 */
  		if (strcmp(option->keyword, "user") == 0)
  		{
! 			option->val = pg_fe_getauthname(NULL);
  			continue;
  		}
  	}
*************** pqGetHomeDirectory(char *buf, int bufsiz
*** 5843,5849 ****
  	struct passwd pwdstr;
  	struct passwd *pwd = NULL;
  
! 	if (pqGetpwuid(geteuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd) != 0)
  		return false;
  	strlcpy(buf, pwd->pw_dir, bufsize);
  	return true;
--- 5862,5869 ----
  	struct passwd pwdstr;
  	struct passwd *pwd = NULL;
  
! 	(void) pqGetpwuid(geteuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd);
! 	if (pwd == NULL)
  		return false;
  	strlcpy(buf, pwd->pw_dir, bufsize);
  	return true;
diff --git a/src/port/path.c b/src/port/path.c
index e8faac3..d0f72df 100644
*** a/src/port/path.c
--- b/src/port/path.c
*************** get_home_path(char *ret_path)
*** 777,783 ****
  	struct passwd pwdstr;
  	struct passwd *pwd = NULL;
  
! 	if (pqGetpwuid(geteuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd) != 0)
  		return false;
  	strlcpy(ret_path, pwd->pw_dir, MAXPGPATH);
  	return true;
--- 777,784 ----
  	struct passwd pwdstr;
  	struct passwd *pwd = NULL;
  
! 	(void) pqGetpwuid(geteuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd);
! 	if (pwd == NULL)
  		return false;
  	strlcpy(ret_path, pwd->pw_dir, MAXPGPATH);
  	return true;
diff --git a/src/port/thread.c b/src/port/thread.c
index 1568803..aab7451 100644
*** a/src/port/thread.c
--- b/src/port/thread.c
*************** pqStrerror(int errnum, char *strerrbuf, 
*** 83,88 ****
--- 83,94 ----
  /*
   * Wrapper around getpwuid() or getpwuid_r() to mimic POSIX getpwuid_r()
   * behaviour, if it is not available or required.
+  *
+  * Per POSIX, the possible cases are:
+  * success: returns zero, *result is non-NULL
+  * uid not found: returns zero, *result is NULL
+  * error during lookup: returns an errno code, *result is NULL
+  * (caller should *not* assume that the errno variable is set)
   */
  #ifndef WIN32
  int
*************** pqGetpwuid(uid_t uid, struct passwd * re
*** 93,114 ****
  
  #ifdef GETPWUID_R_5ARG
  	/* POSIX version */
! 	getpwuid_r(uid, resultbuf, buffer, buflen, result);
  #else
  
  	/*
  	 * Early POSIX draft of getpwuid_r() returns 'struct passwd *'.
  	 * getpwuid_r(uid, resultbuf, buffer, buflen)
  	 */
  	*result = getpwuid_r(uid, resultbuf, buffer, buflen);
  #endif
  #else
- 
  	/* no getpwuid_r() available, just use getpwuid() */
  	*result = getpwuid(uid);
  #endif
- 
- 	return (*result == NULL) ? -1 : 0;
  }
  #endif
  
--- 99,123 ----
  
  #ifdef GETPWUID_R_5ARG
  	/* POSIX version */
! 	return getpwuid_r(uid, resultbuf, buffer, buflen, result);
  #else
  
  	/*
  	 * Early POSIX draft of getpwuid_r() returns 'struct passwd *'.
  	 * getpwuid_r(uid, resultbuf, buffer, buflen)
  	 */
+ 	errno = 0;
  	*result = getpwuid_r(uid, resultbuf, buffer, buflen);
+ 	/* paranoia: ensure we return zero on success */
+ 	return (*result == NULL) ? errno : 0;
  #endif
  #else
  	/* no getpwuid_r() available, just use getpwuid() */
+ 	errno = 0;
  	*result = getpwuid(uid);
+ 	/* paranoia: ensure we return zero on success */
+ 	return (*result == NULL) ? errno : 0;
  #endif
  }
  #endif
  
