From a3f98d579534721d8c2aa890c8dda678f14098d8 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Thu, 6 Jan 2005 18:29:11 +0000
Subject: [PATCH] Adjust lookup of client-side profile files (.pgpass and so
 on) as per discussion on pgsql-hackers-win32 list.  Documentation still needs
 to be tweaked --- I'm not sure how to refer to the APPDATA folder in user
 documentation.

---
 doc/src/sgml/libpq.sgml           | 32 +++++++++++++------
 doc/src/sgml/ref/pg_dumpall.sgml  |  5 +--
 doc/src/sgml/ref/psql-ref.sgml    | 52 +++++++++++++++++--------------
 doc/src/sgml/ref/vacuumdb.sgml    | 44 +++++++++++++-------------
 doc/src/sgml/release.sgml         |  4 +--
 src/backend/libpq/README.SSL      | 12 +++----
 src/bin/psql/input.c              | 21 ++++++-------
 src/bin/psql/startup.c            | 20 ++++++------
 src/interfaces/libpq/fe-connect.c | 29 +++++++++--------
 src/interfaces/libpq/fe-secure.c  | 42 ++++++++++++++-----------
 src/port/path.c                   | 21 +++++++------
 11 files changed, 156 insertions(+), 126 deletions(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index cf2cbcceaa..97c246f1c0 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.174 2004/12/28 23:17:18 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.175 2005/01/06 18:29:07 tgl Exp $
 -->
 
  <chapter id="libpq">
@@ -147,8 +147,8 @@ PGconn *PQconnectdb(const char *conninfo);
       likely to fail if <application>libpq</application> is passed a host name
       that is not the name of the machine at <literal>hostaddr</>.)  Also,
       <literal>host</> rather than <literal>hostaddr</> is used to identify
-      the connection in <filename>$HOME/.pgpass</> (or 
-      <filename>%USERPROFILE%\.pgpass</> on Microsoft Windows).
+      the connection in <filename>~/.pgpass</> (see
+      <xref linkend="libpq-pgpass">).
      </para>
      <para>
       Without either a host name or host address,
@@ -3691,7 +3691,7 @@ sets the user name used to connect to the database.
 <envar>PGPASSWORD</envar>
 sets the password used if the server demands password
 authentication.  This environment variable is deprecated for security
-reasons; instead consider using the <filename>$HOME/.pgpass</>
+reasons; instead consider using the <filename>~/.pgpass</>
 file (see <xref linkend="libpq-pgpass">).
 </para>
 </listitem>
@@ -3881,7 +3881,12 @@ internationalization.
 The file <filename>.pgpass</filename> in a user's home directory is a file
 that can contain passwords to be used if the connection requires a
 password (and no password has been specified otherwise).
-This file should have lines of the following format:
+On Microsoft Windows the file is named
+<filename>APPDATA/postgresql/pgpass.txt</>.
+</para>
+
+<para>
+This file should contain lines of the following format:
 <synopsis>
 <replaceable>hostname</replaceable>:<replaceable>port</replaceable>:<replaceable>database</replaceable>:<replaceable>username</replaceable>:<replaceable>password</replaceable>
 </synopsis>
@@ -3893,11 +3898,14 @@ entries first when you are using wildcards.)
 If an entry needs to contain <literal>:</literal> or
 <literal>\</literal>, escape this character with <literal>\</literal>.
 </para>
+
 <para>
 The permissions on <filename>.pgpass</filename> must disallow any
 access to world or group; achieve this by the command
 <command>chmod 0600 ~/.pgpass</command>.
 If the permissions are less strict than this, the file will be ignored.
+(The file permissions are not currently checked on Microsoft Windows,
+however.)
 </para>
 </sect1>
 
@@ -3920,16 +3928,22 @@ If the permissions are less strict than this, the file will be ignored.
    If the server demands a client certificate, 
    <application>libpq</application>
    will send the certificate stored in file
-   <filename>.postgresql/postgresql.crt</> within the user's home directory.
-   A matching private key file <filename>.postgresql/postgresql.key</>
+   <filename>~/.postgresql/postgresql.crt</> within the user's home directory.
+   A matching private key file <filename>~/.postgresql/postgresql.key</>
    must also be present, and must not be world-readable.
+   (On Microsoft Windows these files are named
+   <filename>APPDATA/postgresql/postgresql.crt</filename> and
+   <filename>APPDATA/postgresql/postgresql.key</filename>.)
   </para>
 
   <para>
-   If the file <filename>.postgresql/root.crt</> is present in the user's
+   If the file <filename>~/.postgresql/root.crt</> is present in the user's
    home directory,
    <application>libpq</application> will use the certificate list stored
-   therein to verify the server's certificate.  The SSL connection will
+   therein to verify the server's certificate.
+   (On Microsoft Windows the file is named
+   <filename>APPDATA/postgresql/root.crt</filename>.)
+   The SSL connection will
    fail if the server does not present a certificate; therefore, to
    use this feature the server must also have a <filename>root.crt</> file.
   </para>
diff --git a/doc/src/sgml/ref/pg_dumpall.sgml b/doc/src/sgml/ref/pg_dumpall.sgml
index 64cc8a09fa..7863c79407 100644
--- a/doc/src/sgml/ref/pg_dumpall.sgml
+++ b/doc/src/sgml/ref/pg_dumpall.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/pg_dumpall.sgml,v 1.47 2005/01/04 03:58:16 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/pg_dumpall.sgml,v 1.48 2005/01/06 18:29:08 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -71,7 +71,8 @@ PostgreSQL documentation
   times to the <productname>PostgreSQL</productname> server (once per
   database).  If you use password authentication it is likely to ask for
   a password each time. It is convenient to have a
-  <filename>$HOME/.pgpass</> file in such cases.
+  <filename>~/.pgpass</> file in such cases. See <xref
+  linkend="libpq-pgpass"> for more information.
   </para>
 
  </refsect1>
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index 30ebeebe3b..afdee5c2ba 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.127 2005/01/04 03:58:16 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.128 2005/01/06 18:29:08 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -440,8 +440,9 @@ PostgreSQL documentation
       <term><option>--no-psqlrc</></term>
       <listitem>
       <para>
-      Do not read the start-up file <filename>/psqlrc</filename> or
-      <filename>~/.psqlrc</filename>.
+      Do not read the start-up file (neither the system-wide
+      <filename>psqlrc</filename> file nor the user's
+      <filename>~/.psqlrc</filename> file).
       </para>
       </listitem>
     </varlistentry>
@@ -1109,7 +1110,7 @@ testdb=>
 => <userinput>\echo `date`</userinput>
 Tue Oct 26 21:40:57 CEST 1999
 </programlisting>
-        If the first argument is an unquoted <literal>-n</literal> the the trailing
+        If the first argument is an unquoted <literal>-n</literal> the trailing
         newline is not written.
         </para>
 
@@ -1901,8 +1902,8 @@ bar
          The autocommit-on mode is <productname>PostgreSQL</>'s traditional
          behavior, but autocommit-off is closer to the SQL spec.  If you
          prefer autocommit-off, you may wish to set it in the system-wide
-         <filename>psqlrc</filename> or your
-         <filename>.psqlrc</filename> file.
+         <filename>psqlrc</filename> file or your
+         <filename>~/.psqlrc</filename> file.
         </para>
         </note>
         </listitem>
@@ -2415,8 +2416,8 @@ testdb=> \set PROMPT1 '%[%033[1;33;40m%]%n@%/%R%[%033[0m%#%] '
     <para>
     <application>psql</application> supports the <application>Readline</application>
     library for convenient line editing and retrieval. The command
-    history is stored in a file named <filename>.psql_history</filename>
-    in your home directory and is reloaded when
+    history is automatically saved when <application>psql</application>
+    exits and is reloaded when
     <application>psql</application> starts up. Tab-completion is also
     supported, although the completion logic makes no claim to be an
     <acronym>SQL</acronym> parser.  If for some reason you do not like the tab completion, you
@@ -2440,17 +2441,6 @@ $endif
   <title>Environment</title>
 
   <variablelist>
-   <varlistentry>
-    <term><envar>HOME</envar></term>
-
-    <listitem>
-     <para>
-      Directory for initialization file (<filename>.psqlrc</filename>)
-      and command history file (<filename>.psql_history</filename>).
-     </para>
-    </listitem>
-   </varlistentry>
-
    <varlistentry>
     <term><envar>PAGER</envar></term>
 
@@ -2531,20 +2521,34 @@ $endif
    <listitem>
     <para>
      Before starting up, <application>psql</application> attempts to
-     read and execute commands from the the system-wide
-     <filename>psqlrc</filename> file and the
-     <filename>$HOME/.psqlrc</filename> file in the user's home
-     directory.  See <filename><replaceable>PREFIX</>/share/psqlrc.sample</>
+     read and execute commands from the system-wide
+     <filename>psqlrc</filename> file and the user's
+     <filename>~/.psqlrc</filename> file.
+     (On Windows, the user's startup file is named
+     <filename>APPDATA/postgresql/psqlrc.txt</filename>.)
+     See <filename><replaceable>PREFIX</>/share/psqlrc.sample</>
      for information on setting up the system-wide file.  It could be used
      to set up the client or the server to taste (using the <command>\set
      </command> and <command>SET</command> commands).
     </para>
    </listitem>
 
+   <listitem>
+    <para>
+     Both the system-wide <filename>psqlrc</filename> file and the user's
+     <filename>~/.psqlrc</filename> file can be made version-specific
+     by appending a dash and the <productname>PostgreSQL</productname>
+     release number, for example <filename>~/.psqlrc-&version;</filename>.
+     A matching version-specific file will be read in preference to a
+     non-version-specific file.
+    </para>
+   </listitem>
+
    <listitem>
     <para>
      The command-line history is stored in the file
-     <filename>$HOME/.psql_history</filename>.
+     <filename>~/.psql_history</filename>, or
+     <filename>APPDATA/postgresql/psql_history</filename> on Windows.
     </para>
    </listitem>
   </itemizedlist>
diff --git a/doc/src/sgml/ref/vacuumdb.sgml b/doc/src/sgml/ref/vacuumdb.sgml
index dee6b81e0d..1fe4db8dc2 100644
--- a/doc/src/sgml/ref/vacuumdb.sgml
+++ b/doc/src/sgml/ref/vacuumdb.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/vacuumdb.sgml,v 1.34 2003/11/29 19:51:39 pgsql Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/vacuumdb.sgml,v 1.35 2005/01/06 18:29:08 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -73,7 +73,7 @@ PostgreSQL documentation
       <term><option>--all</option></term>
       <listitem>
        <para>
-	Vacuum all databases.
+        Vacuum all databases.
        </para>
       </listitem>
      </varlistentry>
@@ -83,12 +83,12 @@ PostgreSQL documentation
       <term><option><optional>--dbname</> <replaceable class="parameter">dbname</replaceable></option></term>
       <listitem>
        <para>
-	Specifies the name of the database to be cleaned or analyzed.
-	If this is not specified and <option>-a</option> (or
-	<option>--all</option>) is not used, the database name is read
-	from the environment variable <envar>PGDATABASE</envar>.  If
-	that is not set, the user name specified for the connection is
-	used.
+        Specifies the name of the database to be cleaned or analyzed.
+        If this is not specified and <option>-a</option> (or
+        <option>--all</option>) is not used, the database name is read
+        from the environment variable <envar>PGDATABASE</envar>.  If
+        that is not set, the user name specified for the connection is
+        used.
        </para>
       </listitem>
      </varlistentry>
@@ -99,7 +99,7 @@ PostgreSQL documentation
       <listitem>
        <para>
         Echo the commands that <application>vacuumdb</application> generates
-	and sends to the server.
+        and sends to the server.
        </para>
       </listitem>
      </varlistentry>
@@ -129,9 +129,9 @@ PostgreSQL documentation
       <term><option>--table <replaceable class="parameter">table</replaceable> [ (<replaceable class="parameter">column</replaceable> [,...]) ]</option></term>
       <listitem>
        <para>
-	Clean or analyze <replaceable class="parameter">table</replaceable> only.
-	Column names may be specified only in conjunction with
-	the <option>--analyze</option> option.
+        Clean or analyze <replaceable class="parameter">table</replaceable> only.
+        Column names may be specified only in conjunction with
+        the <option>--analyze</option> option.
        </para>
        <tip>
         <para>
@@ -147,7 +147,7 @@ PostgreSQL documentation
       <term><option>--verbose</option></term>
       <listitem>
        <para>
-	Print detailed information during processing.
+        Print detailed information during processing.
        </para>
       </listitem>
      </varlistentry>
@@ -157,7 +157,7 @@ PostgreSQL documentation
       <term><option>--analyze</option></term>
       <listitem>
        <para>
-	Calculate statistics for use by the optimizer.
+        Calculate statistics for use by the optimizer.
        </para>
       </listitem>
      </varlistentry>
@@ -174,10 +174,10 @@ PostgreSQL documentation
       <term><option>--host <replaceable class="parameter">host</replaceable></></term>
       <listitem>
        <para>
-	Specifies the host name of the machine on which the 
-	server
-	is running.  If the value begins with a slash, it is used 
-	as the directory for the Unix domain socket.
+        Specifies the host name of the machine on which the 
+        server
+        is running.  If the value begins with a slash, it is used 
+        as the directory for the Unix domain socket.
        </para>
       </listitem>
      </varlistentry>
@@ -187,9 +187,9 @@ PostgreSQL documentation
       <term><option>--port <replaceable class="parameter">port</replaceable></></term>
       <listitem>
        <para>
-	Specifies the TCP port or local Unix domain socket file 
-	extension on which the server
-	is listening for connections.
+        Specifies the TCP port or local Unix domain socket file 
+        extension on which the server
+        is listening for connections.
        </para>
       </listitem>
      </varlistentry>
@@ -261,7 +261,7 @@ PostgreSQL documentation
    <application>vacuumdb</application> might need to connect several
    times to the <productname>PostgreSQL</productname> server, asking
    for a password each time. It is convenient to have a
-   <filename>$HOME/.pgpass</> file in such cases. See <xref
+   <filename>~/.pgpass</> file in such cases. See <xref
    linkend="libpq-pgpass"> for more information.
   </para>
  </refsect1>
diff --git a/doc/src/sgml/release.sgml b/doc/src/sgml/release.sgml
index fe77a978b8..c335497c57 100644
--- a/doc/src/sgml/release.sgml
+++ b/doc/src/sgml/release.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/release.sgml,v 1.317 2005/01/06 01:49:24 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/release.sgml,v 1.318 2005/01/06 18:29:07 tgl Exp $
 -->
 
 <appendix id="release">
@@ -5615,7 +5615,7 @@ operations on bytea columns (Joe)</para></listitem>
    <sect3>
     <title>libpq</title>
 <itemizedlist>
-<listitem><para>Add $HOME/.pgpass to store host/user password combinations (Alvaro Herrera)</para></listitem>
+<listitem><para>Add ~/.pgpass to store host/user password combinations (Alvaro Herrera)</para></listitem>
 <listitem><para>Add PQunescapeBytea() function to libpq (Patrick Welche)</para></listitem>
 <listitem><para>Fix for sending large queries over non-blocking connections (Bernhard Herzog)</para></listitem>
 <listitem><para>Fix for libpq using timers on Win9X (David Ford)</para></listitem>
diff --git a/src/backend/libpq/README.SSL b/src/backend/libpq/README.SSL
index 9d9adcb7fb..9b00a4f0ff 100644
--- a/src/backend/libpq/README.SSL
+++ b/src/backend/libpq/README.SSL
@@ -177,7 +177,7 @@ user should be set up on the database server.  It is acceptable
 for the shell program to be bogus (e.g., /bin/false), if the
 tunnel is set up in to avoid launching a remote shell.
 
-On each client system the $HOME/.ssh/config file should contain
+On each client system the ~/.ssh/config file should contain
 an additional line similiar to
 
  LocalForward 5555 psql.example.com:5432
@@ -192,7 +192,7 @@ that establishes an SSH tunnel when the program is launched:
 
   #!/bin/sh
   HOST=psql.example.com
-  IDENTITY=$HOME/.ssh/identity.psql
+  IDENTITY=~/.ssh/identity.psql
   /usr/bin/ssh -1 -i $IDENTITY -n $HOST 'sleep 60' & \
 	/usr/bin/psql -h $HOST -p 5555 $1
 
@@ -335,12 +335,12 @@ PostgreSQL can generate client certificates via a four-step process.
 
    The client.conf file is normally installed in /etc/postgresql/root.crt.
    The client should also copy the server's root.crt file to
-   $HOME/.postgresql/root.crt.
+   ~/.postgresql/root.crt.
 
 2. If the user has the OpenSSL applications installed, they can
    run pgkeygen.sh.  (An equivalent compiled program will be available
    in the future.)  They should provide a copy of the
-   $HOME/.postgresql/postgresql.pem file to their DBA.
+   ~/.postgresql/postgresql.pem file to their DBA.
 
 3. The DBA should sign this file the OpenSSL applications:
 
@@ -348,7 +348,7 @@ PostgreSQL can generate client certificates via a four-step process.
 
    and return the signed cert (postgresql.crt) to the user.
 
-4. The user should install this file in $HOME/.postgresql/postgresql.crt.
+4. The user should install this file in ~/.postgresql/postgresql.crt.
 
 The server will log every time a client certificate has been
 used, but there is not yet a mechanism provided for using client
@@ -429,7 +429,7 @@ until later.
 > for the shell program to be bogus (e.g., /bin/false), if the
 > tunnel is set up in to avoid launching a remote shell.
 > 
-> On each client system the $HOME/.ssh/config file should contain
+> On each client system the ~/.ssh/config file should contain
 > an additional line similiar to
 > 
 >  LocalForward 5555 psql.example.com:5432
diff --git a/src/bin/psql/input.c b/src/bin/psql/input.c
index b216e98843..e75c86f7f8 100644
--- a/src/bin/psql/input.c
+++ b/src/bin/psql/input.c
@@ -3,18 +3,22 @@
  *
  * Copyright (c) 2000-2005, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/bin/psql/input.c,v 1.42 2005/01/01 05:43:08 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/input.c,v 1.43 2005/01/06 18:29:09 tgl Exp $
  */
 #include "postgres_fe.h"
-#include "input.h"
-
-#include <errno.h>
 
+#include "input.h"
 #include "pqexpbuffer.h"
 #include "settings.h"
 #include "tab-complete.h"
 #include "common.h"
 
+#ifndef WIN32
+#define PSQLHISTORY ".psql_history"
+#else
+#define PSQLHISTORY "psql_history"
+#endif
+
 /* Runtime options for turning off readline and history */
 /* (of course there is no runtime command for doing that :) */
 #ifdef USE_READLINE
@@ -32,14 +36,11 @@ enum histcontrol
 
 #ifdef HAVE_ATEXIT
 static void finishInput(void);
-
 #else
 /* designed for use with on_exit() */
 static void finishInput(int, void *);
 #endif
 
-#define PSQLHISTORY ".psql_history"
-
 
 #ifdef USE_READLINE
 static enum histcontrol
@@ -235,14 +236,12 @@ finishInput(int exitstatus, void *arg)
 			char	   *psql_history;
 			int			hist_size;
 
-			psql_history = pg_malloc(strlen(home) + 1 +
-									 strlen(PSQLHISTORY) + 1);
-
 			hist_size = GetVariableNum(pset.vars, "HISTSIZE", -1, -1, true);
-
 			if (hist_size >= 0)
 				stifle_history(hist_size);
 
+			psql_history = pg_malloc(strlen(home) + 1 +
+									 strlen(PSQLHISTORY) + 1);
 			sprintf(psql_history, "%s/%s", home, PSQLHISTORY);
 			write_history(psql_history);
 			free(psql_history);
diff --git a/src/bin/psql/startup.c b/src/bin/psql/startup.c
index e9ea17dc89..b8f6ca5f56 100644
--- a/src/bin/psql/startup.c
+++ b/src/bin/psql/startup.c
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2000-2005, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/bin/psql/startup.c,v 1.108 2005/01/01 05:43:08 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/startup.c,v 1.109 2005/01/06 18:29:09 tgl Exp $
  */
 #include "postgres_fe.h"
 
@@ -43,8 +43,13 @@ int			optreset;
  */
 PsqlSettings pset;
 
+#ifndef WIN32
 #define SYSPSQLRC	"psqlrc"
 #define PSQLRC		".psqlrc"
+#else
+#define SYSPSQLRC	"psqlrc"
+#define PSQLRC		"psqlrc.txt"
+#endif
 
 /*
  * Structures to pass information between the option parsing routine
@@ -568,24 +573,21 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts * options)
 static void
 process_psqlrc(char *argv0)
 {
-	char	   *psqlrc;
 	char		home[MAXPGPATH];
-	char		global_file[MAXPGPATH];
+	char		rc_file[MAXPGPATH];
 	char		my_exec_path[MAXPGPATH];
 	char		etc_path[MAXPGPATH];
 
 	find_my_exec(argv0, my_exec_path);
 	get_etc_path(my_exec_path, etc_path);
 
-	snprintf(global_file, MAXPGPATH, "%s/%s", etc_path, SYSPSQLRC);
-	process_psqlrc_file(global_file);
+	snprintf(rc_file, MAXPGPATH, "%s/%s", etc_path, SYSPSQLRC);
+	process_psqlrc_file(rc_file);
 
 	if (get_home_path(home))
 	{
-		psqlrc = pg_malloc(strlen(home) + 1 + strlen(PSQLRC) + 1);
-		sprintf(psqlrc, "%s/%s", home, PSQLRC);
-		process_psqlrc_file(psqlrc);
-		free(psqlrc);
+		snprintf(rc_file, MAXPGPATH, "%s/%s", home, PSQLRC);
+		process_psqlrc_file(rc_file);
 	}
 }
 
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 9f7bd09ce4..908c39c256 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.296 2005/01/06 00:59:47 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.297 2005/01/06 18:29:10 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -35,6 +35,7 @@
 
 #ifdef WIN32
 #include "win32.h"
+#include <shlobj.h>
 #else
 #include <sys/socket.h>
 #include <netdb.h>
@@ -57,7 +58,11 @@
 #endif
 
 
+#ifndef WIN32
 #define PGPASSFILE ".pgpass"
+#else
+#define PGPASSFILE "pgpass.txt"
+#endif
 
 /* fall back options if they are not specified by arguments or defined
    by environment variables */
@@ -3175,6 +3180,7 @@ static char *
 PasswordFromFile(char *hostname, char *port, char *dbname, char *username)
 {
 	FILE	   *fp;
+	char		homedir[MAXPGPATH];
 	char		pgpassfile[MAXPGPATH];
 	struct stat stat_buf;
 
@@ -3193,12 +3199,10 @@ PasswordFromFile(char *hostname, char *port, char *dbname, char *username)
 	if (port == NULL)
 		port = DEF_PGPORT_STR;
 
-	if (!pqGetHomeDirectory(pgpassfile, sizeof(pgpassfile)))
+	if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
 		return NULL;
 
-	snprintf(pgpassfile + strlen(pgpassfile),
-			 sizeof(pgpassfile) - strlen(pgpassfile),
-			 "/%s", PGPASSFILE);
+	snprintf(pgpassfile, sizeof(pgpassfile), "%s/%s", homedir, PGPASSFILE);
 
 	/* If password file cannot be opened, ignore it. */
 	if (stat(pgpassfile, &stat_buf) == -1)
@@ -3254,6 +3258,9 @@ PasswordFromFile(char *hostname, char *port, char *dbname, char *username)
 /*
  * Obtain user's home directory, return in given buffer
  *
+ * On Unix, this actually returns the user's home directory.  On Windows
+ * it returns the PostgreSQL-specific application data folder.
+ *
  * This is essentially the same as get_home_path(), but we don't use that
  * because we don't want to pull path.c into libpq (it pollutes application
  * namespace)
@@ -3272,16 +3279,12 @@ pqGetHomeDirectory(char *buf, int bufsize)
 	return true;
 
 #else
+	char		tmppath[MAX_PATH];
 
-	/* TEMPORARY PLACEHOLDER IMPLEMENTATION */
-	const char *homedir;
-
-	homedir = getenv("USERPROFILE");
-	if (homedir == NULL)
-		homedir = getenv("HOME");
-	if (homedir == NULL)
+	ZeroMemory(tmppath, sizeof(tmppath));
+	if (!SHGetSpecialFolderPath(NULL, tmppath, CSIDL_APPDATA, FALSE))
 		return false;
-	StrNCpy(buf, homedir, bufsize);
+	snprintf(buf, bufsize, "%s/postgresql", tmppath);
 	return true;
 #endif
 }
diff --git a/src/interfaces/libpq/fe-secure.c b/src/interfaces/libpq/fe-secure.c
index a87d7221e2..382c1d9b56 100644
--- a/src/interfaces/libpq/fe-secure.c
+++ b/src/interfaces/libpq/fe-secure.c
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.63 2005/01/06 00:59:47 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.64 2005/01/06 18:29:10 tgl Exp $
  *
  * NOTES
  *	  [ Most of these notes are wrong/obsolete, but perhaps not all ]
@@ -26,7 +26,7 @@
  *	  "man-in-the-middle" and "impersonation" attacks.	The
  *	  server certificate, or better yet the CA certificate used
  *	  to sign the server certificate, should be present in the
- *	  "$HOME/.postgresql/root.crt" file.  If this file isn't
+ *	  "~/.postgresql/root.crt" file.  If this file isn't
  *	  readable, or the server certificate can't be validated,
  *	  pqsecure_open_client() will return an error code.
  *
@@ -50,7 +50,7 @@
  *	  ...
  *
  *	  Unlike the server's static private key, the client's
- *	  static private key ($HOME/.postgresql/postgresql.key)
+ *	  static private key (~/.postgresql/postgresql.key)
  *	  should normally be stored encrypted.	However we still
  *	  support EPH since it's useful for other reasons.
  *
@@ -63,9 +63,9 @@
  *	  keeping it closed to everyone else.
  *
  *	  The user's certificate and private key are located in
- *		$HOME/.postgresql/postgresql.crt
+ *		~/.postgresql/postgresql.crt
  *	  and
- *		$HOME/.postgresql/postgresql.key
+ *		~/.postgresql/postgresql.key
  *	  respectively.
  *
  *	  ...
@@ -74,10 +74,6 @@
  *	  info_cb() in be-secure.c), since there's mechanism to
  *	  display that information to the client.
  *
- * OS DEPENDENCIES
- *	  The code currently assumes a POSIX password entry.  How should
- *	  Windows and Mac users be handled?
- *
  *-------------------------------------------------------------------------
  */
 
@@ -124,11 +120,24 @@
 
 
 #ifdef USE_SSL
-static int	verify_cb(int ok, X509_STORE_CTX *ctx);
+
+#ifndef WIN32
+#define USERCERTFILE	".postgresql/postgresql.crt"
+#define USERKEYFILE		".postgresql/postgresql.key"
+#define ROOTCERTFILE	".postgresql/root.crt"
+#define DHFILEPATTERN	"%s/.postgresql/dh%d.pem"
+#else
+/* On Windows, the "home" directory is already PostgreSQL-specific */
+#define USERCERTFILE	"postgresql.crt"
+#define USERKEYFILE		"postgresql.key"
+#define ROOTCERTFILE	"root.crt"
+#define DHFILEPATTERN	"%s/dh%d.pem"
+#endif
 
 #ifdef NOT_USED
 static int	verify_peer(PGconn *);
 #endif
+static int	verify_cb(int ok, X509_STORE_CTX *ctx);
 static DH  *load_dh_file(int keylength);
 static DH  *load_dh_buffer(const char *, size_t);
 static DH  *tmp_dh_cb(SSL *s, int is_export, int keylength);
@@ -158,7 +167,7 @@ static SSL_CTX *SSL_context = NULL;
  *	sessions even if the static private key is compromised,
  *	so we are *highly* motivated to ensure that we can use
  *	EDH even if the user... or an attacker... deletes the
- *	$HOME/.postgresql/dh*.pem files.
+ *	~/.postgresql/dh*.pem files.
  *
  *	It's not critical that users have EPH keys, but it doesn't
  *	hurt and if it's missing someone will demand it, so....
@@ -631,8 +640,7 @@ load_dh_file(int keylength)
 		return NULL;
 
 	/* attempt to open file.  It's not an error if it doesn't exist. */
-	snprintf(fnbuf, sizeof(fnbuf), "%s/.postgresql/dh%d.pem",
-			 homedir, keylength);
+	snprintf(fnbuf, sizeof(fnbuf), DHFILEPATTERN, homedir, keylength);
 
 	if ((fp = fopen(fnbuf, "r")) == NULL)
 		return NULL;
@@ -779,8 +787,7 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
 	}
 
 	/* read the user certificate */
-	snprintf(fnbuf, sizeof(fnbuf), "%s/.postgresql/postgresql.crt",
-			 homedir);
+	snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USERCERTFILE);
 	if ((fp = fopen(fnbuf, "r")) == NULL)
 	{
 		printfPQExpBuffer(&conn->errorMessage,
@@ -802,8 +809,7 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
 	fclose(fp);
 
 	/* read the user key */
-	snprintf(fnbuf, sizeof(fnbuf), "%s/.postgresql/postgresql.key",
-			 homedir);
+	snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USERKEYFILE);
 	if (stat(fnbuf, &buf) == -1)
 	{
 		printfPQExpBuffer(&conn->errorMessage,
@@ -966,7 +972,7 @@ initialize_SSL(PGconn *conn)
 	/* Set up to verify server cert, if root.crt is present */
 	if (pqGetHomeDirectory(homedir, sizeof(homedir)))
 	{
-		snprintf(fnbuf, sizeof(fnbuf), "%s/.postgresql/root.crt", homedir);
+		snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, ROOTCERTFILE);
 		if (stat(fnbuf, &buf) == 0)
 		{
 			if (!SSL_CTX_load_verify_locations(SSL_context, fnbuf, NULL))
diff --git a/src/port/path.c b/src/port/path.c
index 204c782ff1..2620f39263 100644
--- a/src/port/path.c
+++ b/src/port/path.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/port/path.c,v 1.47 2005/01/06 01:00:12 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/port/path.c,v 1.48 2005/01/06 18:29:11 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -17,7 +17,9 @@
 
 #include <ctype.h>
 #include <sys/stat.h>
-#ifndef WIN32
+#ifdef WIN32
+#include <shlobj.h>
+#else
 #include <unistd.h>
 #endif
 
@@ -445,6 +447,9 @@ get_locale_path(const char *my_exec_path, char *ret_path)
 
 /*
  *	get_home_path
+ *
+ * On Unix, this actually returns the user's home directory.  On Windows
+ * it returns the PostgreSQL-specific application data folder.
  */
 bool
 get_home_path(char *ret_path)
@@ -460,16 +465,12 @@ get_home_path(char *ret_path)
 	return true;
 
 #else
+	char		tmppath[MAX_PATH];
 
-	/* TEMPORARY PLACEHOLDER IMPLEMENTATION */
-	const char *homedir;
-
-	homedir = getenv("USERPROFILE");
-	if (homedir == NULL)
-		homedir = getenv("HOME");
-	if (homedir == NULL)
+	ZeroMemory(tmppath, sizeof(tmppath));
+	if (!SHGetSpecialFolderPath(NULL, tmppath, CSIDL_APPDATA, FALSE))
 		return false;
-	StrNCpy(ret_path, homedir, MAXPGPATH);
+	snprintf(ret_path, MAXPGPATH, "%s/postgresql", tmppath);
 	return true;
 #endif
 }
-- 
2.40.0