From d46e6438225d8741100dc400a4a63c87799f0945 Mon Sep 17 00:00:00 2001
From: Bruce Momjian <bruce@momjian.us>
Date: Fri, 4 Apr 2003 20:42:13 +0000
Subject: [PATCH] Add Win32 path handling for / vs. \ and drive letters.

---
 src/Makefile.global.in                  |  4 +-
 src/backend/commands/copy.c             |  4 +-
 src/backend/commands/dbcommands.c       |  8 +--
 src/backend/storage/file/fd.c           |  4 +-
 src/backend/utils/fmgr/dfmgr.c          | 16 +++--
 src/backend/utils/init/findbe.c         | 10 ++--
 src/backend/utils/init/miscinit.c       | 10 +++-
 src/backend/utils/misc/database.c       |  8 +--
 src/bin/pg_controldata/pg_controldata.c |  7 +--
 src/bin/pg_dump/pg_dump.c               |  7 +--
 src/bin/pg_dump/pg_dumpall.c            |  9 +--
 src/bin/pg_dump/pg_restore.c            |  7 +--
 src/bin/pg_resetxlog/pg_resetxlog.c     |  7 +--
 src/bin/psql/prompt.c                   |  4 +-
 src/bin/psql/startup.c                  |  7 +--
 src/bin/scripts/common.c                | 15 +----
 src/bin/scripts/common.h                |  1 -
 src/include/c.h                         |  8 ++-
 src/interfaces/ecpg/ecpglib/connect.c   |  4 +-
 src/interfaces/ecpg/preproc/ecpg.c      |  9 +--
 src/interfaces/libpq/fe-connect.c       |  8 +--
 src/port/path.c                         | 78 +++++++++++++++++++++++++
 22 files changed, 147 insertions(+), 88 deletions(-)
 create mode 100644 src/port/path.c

diff --git a/src/Makefile.global.in b/src/Makefile.global.in
index 29e48ca17bd..192381b7b62 100644
--- a/src/Makefile.global.in
+++ b/src/Makefile.global.in
@@ -1,5 +1,5 @@
 # -*-makefile-*-
-# $Header: /cvsroot/pgsql/src/Makefile.global.in,v 1.160 2003/03/29 11:31:51 petere Exp $
+# $Header: /cvsroot/pgsql/src/Makefile.global.in,v 1.161 2003/04/04 20:42:11 momjian Exp $
 
 #------------------------------------------------------------------------------
 # All PostgreSQL makefiles include this file and use the variables it sets,
@@ -338,7 +338,7 @@ endif
 #
 # substitute implementations of the C library
 
-LIBOBJS = @LIBOBJS@
+LIBOBJS = @LIBOBJS@ path.o
 
 ifneq (,$(LIBOBJS))
 LIBS += -lpgport
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 978429c87f7..0f20bfb2aea 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.190 2003/03/27 16:51:27 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.191 2003/04/04 20:42:11 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -476,7 +476,7 @@ DoCopy(const CopyStmt *stmt)
 			 * Prevent write to relative path ... too easy to shoot
 			 * oneself in the foot by overwriting a database file ...
 			 */
-			if (filename[0] != '/')
+			if (!is_absolute_path(filename))
 				elog(ERROR, "Relative path not allowed for server side"
 					 " COPY command");
 
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index 32c4c459c9a..3ef778c9648 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.111 2003/04/04 20:40:44 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.112 2003/04/04 20:42:12 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -698,9 +698,9 @@ resolve_alt_dbpath(const char *dbpath, Oid dboid)
 	if (dbpath == NULL || dbpath[0] == '\0')
 		return NULL;
 
-	if (strchr(dbpath, '/'))
+	if (first_path_separator(dbpath))
 	{
-		if (dbpath[0] != '/')
+		if (!is_absolute_path(dbpath))
 			elog(ERROR, "Relative paths are not allowed as database locations");
 #ifndef ALLOW_ABSOLUTE_DBPATHS
 		elog(ERROR, "Absolute paths are not allowed as database locations");
@@ -714,7 +714,7 @@ resolve_alt_dbpath(const char *dbpath, Oid dboid)
 
 		if (!var)
 			elog(ERROR, "Postmaster environment variable '%s' not set", dbpath);
-		if (var[0] != '/')
+		if (!is_absolute_path(var))
 			elog(ERROR, "Postmaster environment variable '%s' must be absolute path", dbpath);
 		prefix = var;
 	}
diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c
index 7607d4186cc..b84e2cb82d1 100644
--- a/src/backend/storage/file/fd.c
+++ b/src/backend/storage/file/fd.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/file/fd.c,v 1.96 2003/03/27 16:51:29 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/file/fd.c,v 1.97 2003/04/04 20:42:12 momjian Exp $
  *
  * NOTES:
  *
@@ -607,7 +607,7 @@ filepath(const char *filename)
 	char	   *buf;
 
 	/* Not an absolute path name? Then fill in with database path... */
-	if (*filename != '/')
+	if (!is_absolute_path(filename))
 	{
 		buf = (char *) palloc(strlen(DatabasePath) + strlen(filename) + 2);
 		sprintf(buf, "%s/%s", DatabasePath, filename);
diff --git a/src/backend/utils/fmgr/dfmgr.c b/src/backend/utils/fmgr/dfmgr.c
index d8e6ff3ee10..c7f79df416d 100644
--- a/src/backend/utils/fmgr/dfmgr.c
+++ b/src/backend/utils/fmgr/dfmgr.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.57 2002/09/02 02:47:05 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.58 2003/04/04 20:42:12 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -271,7 +271,7 @@ expand_dynamic_library_name(const char *name)
 
 	AssertArg(name);
 
-	have_slash = (strchr(name, '/') != NULL);
+	have_slash = (first_path_separator(name) != NULL);
 
 	if (!have_slash)
 	{
@@ -326,7 +326,13 @@ substitute_libpath_macro(const char *name)
 	if (name[0] != '$')
 		return pstrdup(name);
 
-	macroname_len = strcspn(name + 1, "/") + 1;
+	macroname_len = strcspn(name + 1,
+#ifndef WIN32
+		"/"
+#else
+		"/\\"
+#endif
+		) + 1;
 
 	if (strncmp(name, "$libdir", macroname_len) == 0)
 		replacement = PKGLIBDIR;
@@ -362,7 +368,7 @@ find_in_dynamic_libpath(const char *basename)
 	size_t		baselen;
 
 	AssertArg(basename != NULL);
-	AssertArg(strchr(basename, '/') == NULL);
+	AssertArg(first_path_separator(basename) == NULL);
 	AssertState(Dynamic_library_path != NULL);
 
 	p = Dynamic_library_path;
@@ -391,7 +397,7 @@ find_in_dynamic_libpath(const char *basename)
 		pfree(piece);
 
 		/* only absolute paths */
-		if (mangled[0] != '/')
+		if (!is_absolute_path(mangled))
 			elog(ERROR, "dynamic_library_path component is not absolute");
 
 		full = palloc(strlen(mangled) + 1 + baselen + 1);
diff --git a/src/backend/utils/init/findbe.c b/src/backend/utils/init/findbe.c
index ce5c521f3e0..94d744bce9c 100644
--- a/src/backend/utils/init/findbe.c
+++ b/src/backend/utils/init/findbe.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/init/Attic/findbe.c,v 1.31 2002/11/02 15:54:13 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/init/Attic/findbe.c,v 1.32 2003/04/04 20:42:12 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -159,14 +159,14 @@ FindExec(char *full_path, const char *argv0, const char *binary_name)
 	 * (making sure that a relative path is made absolute before returning
 	 * it).
 	 */
-	if (argv0 && (p = strrchr(argv0, '/')) && *++p)
+	if (argv0 && (p = last_path_separator(argv0)) && *++p)
 	{
-		if (*argv0 == '/' || !getcwd(buf, MAXPGPATH))
+		if (is_absolute_path(argv0) || !getcwd(buf, MAXPGPATH))
 			buf[0] = '\0';
 		else
 			strcat(buf, "/");
 		strcat(buf, argv0);
-		p = strrchr(buf, '/');
+		p = last_path_separator(buf);
 		strcpy(++p, binary_name);
 		if (ValidateBinary(buf) == 0)
 		{
@@ -194,7 +194,7 @@ FindExec(char *full_path, const char *argv0, const char *binary_name)
 				continue;
 			if (endp)
 				*endp = '\0';
-			if (*startp == '/' || !getcwd(buf, MAXPGPATH))
+			if (is_absolute_path(startp) || !getcwd(buf, MAXPGPATH))
 				buf[0] = '\0';
 			else
 				strcat(buf, "/");
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index 8b49ca2e584..6ffd1e01b97 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.101 2003/03/20 04:51:44 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.102 2003/04/04 20:42:12 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -134,7 +134,7 @@ SetDataDir(const char *dir)
 	AssertArg(dir);
 
 	/* If presented path is relative, convert to absolute */
-	if (dir[0] != '/')
+	if (!is_absolute_path(dir))
 	{
 		char	   *buf;
 		size_t		buflen;
@@ -179,7 +179,11 @@ SetDataDir(const char *dir)
 	 * generating funny-looking paths to individual files.
 	 */
 	newlen = strlen(new);
-	if (newlen > 1 && new[newlen - 1] == '/')
+	if (newlen > 1 && new[newlen - 1] == '/'
+#ifdef WIN32
+		|| new[newlen - 1] == '\\'
+#endif
+		)
 		new[newlen - 1] = '\0';
 
 	if (DataDir)
diff --git a/src/backend/utils/misc/database.c b/src/backend/utils/misc/database.c
index 981d7ea7dcc..ce8e6fb5fac 100644
--- a/src/backend/utils/misc/database.c
+++ b/src/backend/utils/misc/database.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/misc/Attic/database.c,v 1.55 2003/03/10 22:28:19 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/misc/Attic/database.c,v 1.56 2003/04/04 20:42:12 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -50,10 +50,10 @@ ExpandDatabasePath(const char *dbpath)
 		return NULL;			/* ain't gonna fit nohow */
 
 	/* leading path delimiter? then already absolute path */
-	if (*dbpath == '/')
+	if (is_absolute_path(dbpath))
 	{
 #ifdef ALLOW_ABSOLUTE_DBPATHS
-		cp = strrchr(dbpath, '/');
+		cp = last_path_separator(dbpath);
 		len = cp - dbpath;
 		strncpy(buf, dbpath, len);
 		snprintf(&buf[len], MAXPGPATH - len, "/base/%s", (cp + 1));
@@ -62,7 +62,7 @@ ExpandDatabasePath(const char *dbpath)
 #endif
 	}
 	/* path delimiter somewhere? then has leading environment variable */
-	else if ((cp = strchr(dbpath, '/')) != NULL)
+	else if ((cp = first_path_separator(dbpath)) != NULL)
 	{
 		const char *envvar;
 
diff --git a/src/bin/pg_controldata/pg_controldata.c b/src/bin/pg_controldata/pg_controldata.c
index 7c99bbb10cf..15c5000e105 100644
--- a/src/bin/pg_controldata/pg_controldata.c
+++ b/src/bin/pg_controldata/pg_controldata.c
@@ -6,7 +6,7 @@
  * copyright (c) Oliver Elphick <olly@lfix.co.uk>, 2001;
  * licence: BSD
  *
- * $Header: /cvsroot/pgsql/src/bin/pg_controldata/pg_controldata.c,v 1.8 2003/01/08 22:26:34 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/bin/pg_controldata/pg_controldata.c,v 1.9 2003/04/04 20:42:12 momjian Exp $
  */
 #include "postgres.h"
 
@@ -82,10 +82,7 @@ main(int argc, char *argv[])
 	textdomain("pg_controldata");
 #endif
 
-	if (!strrchr(argv[0], '/'))
-		progname = argv[0];
-	else
-		progname = strrchr(argv[0], '/') + 1;
+	progname = get_progname(argv[0]);
 
 	if (argc > 1)
 	{
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 1c6dfe2469f..409a961701a 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -12,7 +12,7 @@
  *	by PostgreSQL
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.325 2003/03/31 20:48:45 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.326 2003/04/04 20:42:12 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -244,10 +244,7 @@ main(int argc, char **argv)
 
 	dataOnly = schemaOnly = dumpData = attrNames = false;
 
-	if (!strrchr(argv[0], '/'))
-		progname = argv[0];
-	else
-		progname = strrchr(argv[0], '/') + 1;
+	progname = get_progname(argv[0]);
 
 	/* Set default options based on progname */
 	if (strcmp(progname, "pg_backup") == 0)
diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c
index 52facb459a5..f3919048f82 100644
--- a/src/bin/pg_dump/pg_dumpall.c
+++ b/src/bin/pg_dump/pg_dumpall.c
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  *
- * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.16 2003/03/14 22:45:49 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.17 2003/04/04 20:42:12 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -100,10 +100,7 @@ main(int argc, char *argv[])
 	textdomain("pg_dump");
 #endif
 
-	if (!strrchr(argv[0], '/'))
-		progname = argv[0];
-	else
-		progname = strrchr(argv[0], '/') + 1;
+	progname = get_progname(argv[0]);
 
 	if (argc > 1)
 	{
@@ -730,7 +727,7 @@ findPgDump(const char *argv0)
 		return result;
 
 	cmd = createPQExpBuffer();
-	last = strrchr(argv0, '/');
+	last = last_path_separator(argv0);
 
 	if (!last)
 		appendPQExpBuffer(cmd, "pg_dump");
diff --git a/src/bin/pg_dump/pg_restore.c b/src/bin/pg_dump/pg_restore.c
index fe1471ff99e..8e7cea02098 100644
--- a/src/bin/pg_dump/pg_restore.c
+++ b/src/bin/pg_dump/pg_restore.c
@@ -34,7 +34,7 @@
  *
  *
  * IDENTIFICATION
- *		$Header: /cvsroot/pgsql/src/bin/pg_dump/pg_restore.c,v 1.44 2003/01/06 18:53:25 petere Exp $
+ *		$Header: /cvsroot/pgsql/src/bin/pg_dump/pg_restore.c,v 1.45 2003/04/04 20:42:13 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -137,10 +137,7 @@ main(int argc, char **argv)
 
 	opts = NewRestoreOptions();
 
-	if (!strrchr(argv[0], '/'))
-		progname = argv[0];
-	else
-		progname = strrchr(argv[0], '/') + 1;
+	progname = get_progname(argv[0]);
 
 	if (argc > 1)
 	{
diff --git a/src/bin/pg_resetxlog/pg_resetxlog.c b/src/bin/pg_resetxlog/pg_resetxlog.c
index ee6a3b51732..b07cfd09e23 100644
--- a/src/bin/pg_resetxlog/pg_resetxlog.c
+++ b/src/bin/pg_resetxlog/pg_resetxlog.c
@@ -23,7 +23,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Header: /cvsroot/pgsql/src/bin/pg_resetxlog/pg_resetxlog.c,v 1.8 2002/10/18 22:05:36 petere Exp $
+ * $Header: /cvsroot/pgsql/src/bin/pg_resetxlog/pg_resetxlog.c,v 1.9 2003/04/04 20:42:13 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -105,10 +105,7 @@ main(int argc, char *argv[])
 	textdomain("pg_resetxlog");
 #endif
 
-	if (!strrchr(argv[0], '/'))
-		progname = argv[0];
-	else
-		progname = strrchr(argv[0], '/') + 1;
+	progname = get_progname(argv[0]);
 
 	if (argc > 1)
 	{
diff --git a/src/bin/psql/prompt.c b/src/bin/psql/prompt.c
index c65da457db8..f9d66b752ec 100644
--- a/src/bin/psql/prompt.c
+++ b/src/bin/psql/prompt.c
@@ -3,7 +3,7 @@
  *
  * Copyright 2000 by PostgreSQL Global Development Group
  *
- * $Header: /cvsroot/pgsql/src/bin/psql/prompt.c,v 1.24 2003/03/20 15:39:53 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/prompt.c,v 1.25 2003/04/04 20:42:13 momjian Exp $
  */
 #include "postgres_fe.h"
 #include "prompt.h"
@@ -130,7 +130,7 @@ get_prompt(promptStatus_t status)
 						const char *host = PQhost(pset.db);
 
 						/* INET socket */
-						if (host && host[0] && host[0] != '/')
+						if (host && host[0] && !is_absolute_path(host))
 						{
 							strncpy(buf, host, MAX_PROMPT_SIZE);
 							if (*p == 'm')
diff --git a/src/bin/psql/startup.c b/src/bin/psql/startup.c
index 47e17e3535f..74d79fc5078 100644
--- a/src/bin/psql/startup.c
+++ b/src/bin/psql/startup.c
@@ -3,7 +3,7 @@
  *
  * Copyright 2000 by PostgreSQL Global Development Group
  *
- * $Header: /cvsroot/pgsql/src/bin/psql/startup.c,v 1.72 2003/03/20 06:43:35 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/startup.c,v 1.73 2003/04/04 20:42:13 momjian Exp $
  */
 #include "postgres_fe.h"
 
@@ -110,10 +110,7 @@ main(int argc, char *argv[])
 	textdomain("psql");
 #endif
 
-	if (!strrchr(argv[0], '/'))
-		pset.progname = argv[0];
-	else
-		pset.progname = strrchr(argv[0], '/') + 1;
+	pset.progname = get_progname(argv[0]);
 
 	if (argc > 1)
 	{
diff --git a/src/bin/scripts/common.c b/src/bin/scripts/common.c
index a04cf19555f..a1a6993e724 100644
--- a/src/bin/scripts/common.c
+++ b/src/bin/scripts/common.c
@@ -5,7 +5,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Header: /cvsroot/pgsql/src/bin/scripts/common.c,v 1.1 2003/03/18 22:19:46 petere Exp $
+ * $Header: /cvsroot/pgsql/src/bin/scripts/common.c,v 1.2 2003/04/04 20:42:13 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -35,19 +35,6 @@ get_user_name(const char *progname)
 }
 
 
-/*
- * Extracts the actual name of the program as called.
- */
-char *
-get_progname(char *argv0)
-{
-	if (!strrchr(argv0, '/'))
-		return argv0;
-	else
-		return strrchr(argv0, '/') + 1;
-}
-
-
 /*
  * Initialized NLS if enabled.
  */
diff --git a/src/bin/scripts/common.h b/src/bin/scripts/common.h
index 52e7b0c3fcc..6122b686ceb 100644
--- a/src/bin/scripts/common.h
+++ b/src/bin/scripts/common.h
@@ -16,7 +16,6 @@ int optreset;
 #endif
 
 const char *get_user_name(const char *progname);
-char *get_progname(char *argv0);
 
 #define _(x) gettext((x))
 void init_nls(void);
diff --git a/src/include/c.h b/src/include/c.h
index 724bbb50b84..0129098d451 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -12,7 +12,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: c.h,v 1.135 2003/01/09 18:00:24 tgl Exp $
+ * $Id: c.h,v 1.136 2003/04/04 20:42:13 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -692,6 +692,12 @@ typedef NameData *Name;
 #include <unistd.h>
 #endif
 
+/* Portable path handling for Unix/Win32 */
+bool is_absolute_path(const char *filename);
+char *first_path_separator(const char *filename);
+char *last_path_separator(const char *filename);
+char *get_progname(char *argv0);
+
 #if defined(bsdi) || defined(netbsd)
 int fseeko(FILE *stream, off_t offset, int whence);
 off_t ftello(FILE *stream);
diff --git a/src/interfaces/ecpg/ecpglib/connect.c b/src/interfaces/ecpg/ecpglib/connect.c
index 5c3c096dd57..69433bdc4b1 100644
--- a/src/interfaces/ecpg/ecpglib/connect.c
+++ b/src/interfaces/ecpg/ecpglib/connect.c
@@ -1,4 +1,4 @@
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/connect.c,v 1.1 2003/03/16 10:42:53 meskes Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/connect.c,v 1.2 2003/04/04 20:42:13 momjian Exp $ */
 
 #include "postgres_fe.h"
 
@@ -326,7 +326,7 @@ ECPGconnect(int lineno, const char *name, const char *user, const char *passwd,
 				*tmp = '\0';
 			}
 
-			tmp = strrchr(dbname + offset, '/');
+			tmp = last_path_separator(dbname + offset);
 			if (tmp != NULL)	/* database name given */
 			{
 				realname = strdup(tmp + 1);
diff --git a/src/interfaces/ecpg/preproc/ecpg.c b/src/interfaces/ecpg/preproc/ecpg.c
index d3b61525dd8..fa35b30e7f5 100644
--- a/src/interfaces/ecpg/preproc/ecpg.c
+++ b/src/interfaces/ecpg/preproc/ecpg.c
@@ -1,4 +1,4 @@
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/ecpg.c,v 1.64 2003/03/27 14:29:17 meskes Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/ecpg.c,v 1.65 2003/04/04 20:42:13 momjian Exp $ */
 
 /* New main for ecpg, the PostgreSQL embedded SQL precompiler. */
 /* (C) Michael Meskes <meskes@postgresql.org> Feb 5th, 1998 */
@@ -105,10 +105,7 @@ main(int argc, char *const argv[])
 	struct _include_path *ip;
 	char	   *progname;
 
-	if (!strrchr(argv[0], '/'))
-		progname = argv[0];
-	else
-		progname = strrchr(argv[0], '/') + 1;
+	progname = get_progname(argv[0]);
 
 	if (argc > 1)
 	{
@@ -213,7 +210,7 @@ main(int argc, char *const argv[])
 			strcpy(input_filename, argv[fnr]);
 
 			/* take care of relative paths */
-			ptr2ext = strrchr(input_filename, '/');
+			ptr2ext = last_path_separator(input_filename);
 			ptr2ext = (ptr2ext ? strrchr(ptr2ext, '.') : strrchr(input_filename, '.'));
 
 			/* no extension? */
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 3d938031efe..f2e509e6246 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.230 2003/04/02 00:49:28 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.231 2003/04/04 20:42:13 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -330,7 +330,7 @@ PQconnectStart(const char *conninfo)
 	/*
 	 * Allow unix socket specification in the host name
 	 */
-	if (conn->pghost && conn->pghost[0] == '/')
+	if (conn->pghost && is_absolute_path(conn->pghost))
 	{
 		if (conn->pgunixsocket)
 			free(conn->pgunixsocket);
@@ -449,7 +449,7 @@ PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions,
 	 * We don't allow unix socket path as a function parameter. This
 	 * allows unix socket specification in the host name.
 	 */
-	if (conn->pghost && conn->pghost[0] == '/')
+	if (conn->pghost && is_absolute_path(conn->pghost))
 	{
 		if (conn->pgunixsocket)
 			free(conn->pgunixsocket);
@@ -604,7 +604,7 @@ update_db_info(PGconn *conn)
 				*tmp = '\0';
 			}
 
-			tmp = strrchr(conn->dbName + offset, '/');
+			tmp = last_path_separator(conn->dbName + offset);
 			if (tmp != NULL)	/* database name given */
 			{
 				if (conn->dbName)
diff --git a/src/port/path.c b/src/port/path.c
new file mode 100644
index 00000000000..9cca1586f17
--- /dev/null
+++ b/src/port/path.c
@@ -0,0 +1,78 @@
+/* $Id: path.c,v 1.1 2003/04/04 20:42:13 momjian Exp $ */
+
+#include "c.h"
+#include <ctype.h>
+
+/*
+ *	is_absolute_path
+ */
+bool is_absolute_path(const char *filename)
+{
+	return filename[0] == '/'
+#ifdef WIN32	/* WIN32 paths can either have forward or backward slashes */
+		|| filename[0] == '\\'
+		|| (isalpha(filename[0]) && filename[1] == ':'
+		    && (filename[2] == '\\' || filename[2] == '/'))
+#endif
+		;
+}
+
+
+	
+/*
+ *	first_path_separator
+ */
+char *first_path_separator(const char *filename)
+{
+#ifndef WIN32
+	return strchr(filename, '/');
+#else
+	char *slash, *bslash;
+
+	/* How should we handle "C:file.c"? */
+	slash = strchr(filename, '/');
+	bslash = strchr(filename, '\\');
+	if (slash == NULL)
+		return bslash;
+	else if (bslash == NULL)
+		return slash;
+	else
+		return (slash < bslash) ? slash : bslash;
+#endif
+}
+
+
+/*
+ *	last_path_separator
+ */
+char *last_path_separator(const char *filename)
+{
+#ifndef WIN32
+	return strrchr(filename, '/');
+#else
+	char *slash, *bslash;
+
+	/* How should we handle "C:file.c"? */
+	slash = strrchr(filename, '/');
+	bslash = strrchr(filename, '\\');
+	if (slash == NULL)
+		return bslash;
+	else if (bslash == NULL)
+		return slash;
+	else
+		return (slash > bslash) ? slash : bslash;
+#endif
+}
+
+
+/*
+ * Extracts the actual name of the program as called.
+ */
+char *
+get_progname(char *argv0)
+{
+	if (!last_path_separator(argv0))
+		return argv0;
+	else
+		return last_path_separator(argv0) + 1;
+}
-- 
GitLab