diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index d67212b831..f5f2668f15 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -7231,6 +7231,16 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
      </para>
     </listitem>
 
+    <listitem>
+     <para>
+      <indexterm>
+       <primary><envar>PGPASSCOMMAND</envar></primary>
+      </indexterm>
+      <envar>PGPASSCOMMAND</envar> behaves the same as the <xref
+      linkend="libpq-connect-passcommand"/> connection parameter.
+     </para>
+    </listitem>
+
     <listitem>
      <para>
       <indexterm>
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index a7e969d7c1..60382bc67b 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -204,6 +204,10 @@ static const internalPQconninfoOption PQconninfoOptions[] = {
 		"Database-Password-File", "", 64,
 	offsetof(struct pg_conn, pgpassfile)},
 
+	{"passcommand", "PGPASSCOMMAND", NULL, NULL,
+		"Database-Password-Command", "", 64,
+	offsetof(struct pg_conn, pgpasscommand)},
+
 	{"connect_timeout", "PGCONNECT_TIMEOUT", NULL, NULL,
 		"Connect-timeout", "", 10,	/* strlen(INT32_MAX) == 10 */
 	offsetof(struct pg_conn, connect_timeout)},
@@ -406,8 +410,8 @@ static int parseServiceFile(const char *serviceFile,
 				 PQExpBuffer errorMessage,
 				 bool *group_found);
 static char *pwdfMatchesString(char *buf, const char *token);
-static char *passwordFromFile(const char *hostname, const char *port, const char *dbname,
-				 const char *username, const char *pgpassfile);
+static char *passwordFromFileOrCommand(const char *hostname, const char *port, const char *dbname,
+				 const char *username, const char *pgpassfile, const char *pgpasscommand);
 static void pgpassfileWarning(PGconn *conn);
 static void default_threadlock(int acquire);
 
@@ -1068,7 +1072,8 @@ connectOptions2(PGconn *conn)
 	 * Supply default password if none given.  Note that the password might be
 	 * different for each host/port pair.
 	 */
-	if (conn->pgpass == NULL || conn->pgpass[0] == '\0')
+	if ( (conn->pgpass == NULL || conn->pgpass[0] == '\0')
+	||   (conn->pgpasscommand != NULL && conn->pgpasscommand[0] != '\0') )
 	{
 		/* If password file wasn't specified, use ~/PGPASSFILE */
 		if (conn->pgpassfile == NULL || conn->pgpassfile[0] == '\0')
@@ -1087,7 +1092,8 @@ connectOptions2(PGconn *conn)
 			}
 		}
 
-		if (conn->pgpassfile != NULL && conn->pgpassfile[0] != '\0')
+		if ( (conn->pgpassfile != NULL && conn->pgpassfile[0] != '\0')
+		||   (conn->pgpasscommand != NULL && conn->pgpasscommand[0] != '\0') )
 		{
 			int			i;
 
@@ -1106,11 +1112,12 @@ connectOptions2(PGconn *conn)
 					pwhost = conn->connhost[i].hostaddr;
 
 				conn->connhost[i].password =
-					passwordFromFile(pwhost,
+					passwordFromFileOrCommand(pwhost,
 									 conn->connhost[i].port,
 									 conn->dbName,
 									 conn->pguser,
-									 conn->pgpassfile);
+									 conn->pgpassfile,
+									 conn->pgpasscommand);
 				/* If we got one, set pgpassfile_used */
 				if (conn->connhost[i].password != NULL)
 					conn->pgpassfile_used = true;
@@ -3468,6 +3475,8 @@ freePGconn(PGconn *conn)
 		free(conn->pgpass);
 	if (conn->pgpassfile)
 		free(conn->pgpassfile);
+	if (conn->pgpasscommand)
+		free(conn->pgpasscommand);
 	if (conn->keepalives)
 		free(conn->keepalives);
 	if (conn->keepalives_idle)
@@ -6376,11 +6385,12 @@ pwdfMatchesString(char *buf, const char *token)
 
 /* Get a password from the password file. Return value is malloc'd. */
 static char *
-passwordFromFile(const char *hostname, const char *port, const char *dbname,
-				 const char *username, const char *pgpassfile)
+passwordFromFileOrCommand(const char *hostname, const char *port, const char *dbname,
+				 const char *username, const char *pgpassfile, const char *pgpasscommand)
 {
 	FILE	   *fp;
 	struct stat stat_buf;
+	char has_pgpassfile=0;
 
 #define LINELEN NAMEDATALEN*5
 	char		buf[LINELEN];
@@ -6407,11 +6417,12 @@ passwordFromFile(const char *hostname, const char *port, const char *dbname,
 		port = DEF_PGPORT_STR;
 
 	/* If password file cannot be opened, ignore it. */
-	if (stat(pgpassfile, &stat_buf) != 0)
-		return NULL;
+	if (stat(pgpassfile, &stat_buf) == 0)
+		has_pgpassfile=1;
+
 
 #ifndef WIN32
-	if (!S_ISREG(stat_buf.st_mode))
+	if (has_pgpassfile && !S_ISREG(stat_buf.st_mode))
 	{
 		fprintf(stderr,
 				libpq_gettext("WARNING: password file \"%s\" is not a plain file\n"),
@@ -6420,7 +6431,7 @@ passwordFromFile(const char *hostname, const char *port, const char *dbname,
 	}
 
 	/* If password file is insecure, alert the user and ignore it. */
-	if (stat_buf.st_mode & (S_IRWXG | S_IRWXO))
+	if (has_pgpassfile && stat_buf.st_mode & (S_IRWXG | S_IRWXO))
 	{
 		fprintf(stderr,
 				libpq_gettext("WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n"),
@@ -6434,8 +6445,22 @@ passwordFromFile(const char *hostname, const char *port, const char *dbname,
 	 * file.
 	 */
 #endif
+	if (has_pgpassfile)
+	{
+		fp = fopen(pgpassfile, "r");
+	}
+	else if (pgpasscommand != NULL && pgpasscommand[0] != '\0')
+	{
+		fp = popen(pgpasscommand, "r");
+	}
+	else
+	{
+		fprintf(stderr,
+				libpq_gettext("WARNING: password file and password command are not provided, please correct code\n")
+			);
+		return NULL;
+	}
 
-	fp = fopen(pgpassfile, "r");
 	if (fp == NULL)
 		return NULL;
 
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 9a586ff25a..77af2ab550 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -343,6 +343,7 @@ struct pg_conn
 	char	   *pguser;			/* Postgres username and password, if any */
 	char	   *pgpass;
 	char	   *pgpassfile;		/* path to a file containing password(s) */
+	char	   *pgpasscommand; /* path to command producing the password(s) */
 	char	   *keepalives;		/* use TCP keepalives? */
 	char	   *keepalives_idle;	/* time between TCP keepalives */
 	char	   *keepalives_interval;	/* time between TCP keepalive
