*** a/src/backend/utils/init/miscinit.c
--- b/src/backend/utils/init/miscinit.c
***************
*** 88,98 **** void
  SetDataDir(const char *dir)
  {
  	char	   *new;
  
  	AssertArg(dir);
  
  	/* If presented path is relative, convert to absolute */
! 	new = make_absolute_path(dir);
  
  	if (DataDir)
  		free(DataDir);
--- 88,101 ----
  SetDataDir(const char *dir)
  {
  	char	   *new;
+ 	char	   *errstr;
  
  	AssertArg(dir);
  
  	/* If presented path is relative, convert to absolute */
! 	new = make_absolute_path(dir, &errstr);
! 	if (new == NULL)
! 		ereport(FATAL, (errmsg_internal("%s", errstr)));
  
  	if (DataDir)
  		free(DataDir);
***************
*** 117,194 **** ChangeToDataDir(void)
  						DataDir)));
  }
  
- /*
-  * If the given pathname isn't already absolute, make it so, interpreting
-  * it relative to the current working directory.
-  *
-  * Also canonicalizes the path.  The result is always a malloc'd copy.
-  *
-  * Note: interpretation of relative-path arguments during postmaster startup
-  * should happen before doing ChangeToDataDir(), else the user will probably
-  * not like the results.
-  */
- char *
- make_absolute_path(const char *path)
- {
- 	char	   *new;
- 
- 	/* Returning null for null input is convenient for some callers */
- 	if (path == NULL)
- 		return NULL;
- 
- 	if (!is_absolute_path(path))
- 	{
- 		char	   *buf;
- 		size_t		buflen;
- 
- 		buflen = MAXPGPATH;
- 		for (;;)
- 		{
- 			buf = malloc(buflen);
- 			if (!buf)
- 				ereport(FATAL,
- 						(errcode(ERRCODE_OUT_OF_MEMORY),
- 						 errmsg("out of memory")));
- 
- 			if (getcwd(buf, buflen))
- 				break;
- 			else if (errno == ERANGE)
- 			{
- 				free(buf);
- 				buflen *= 2;
- 				continue;
- 			}
- 			else
- 			{
- 				free(buf);
- 				elog(FATAL, "could not get current working directory: %m");
- 			}
- 		}
- 
- 		new = malloc(strlen(buf) + strlen(path) + 2);
- 		if (!new)
- 			ereport(FATAL,
- 					(errcode(ERRCODE_OUT_OF_MEMORY),
- 					 errmsg("out of memory")));
- 		sprintf(new, "%s/%s", buf, path);
- 		free(buf);
- 	}
- 	else
- 	{
- 		new = strdup(path);
- 		if (!new)
- 			ereport(FATAL,
- 					(errcode(ERRCODE_OUT_OF_MEMORY),
- 					 errmsg("out of memory")));
- 	}
- 
- 	/* Make sure punctuation is canonical, too */
- 	canonicalize_path(new);
- 
- 	return new;
- }
- 
- 
  /* ----------------------------------------------------------------
   *	User ID state
   *
--- 120,125 ----
*** a/src/backend/utils/misc/guc.c
--- b/src/backend/utils/misc/guc.c
***************
*** 4214,4226 **** SelectConfigFiles(const char *userDoption, const char *progname)
  {
  	char	   *configdir;
  	char	   *fname;
  	struct stat stat_buf;
  
  	/* configdir is -D option, or $PGDATA if no -D */
  	if (userDoption)
! 		configdir = make_absolute_path(userDoption);
  	else
! 		configdir = make_absolute_path(getenv("PGDATA"));
  
  	/*
  	 * Find the configuration file: if config_file was specified on the
--- 4214,4230 ----
  {
  	char	   *configdir;
  	char	   *fname;
+ 	char	   *errstr;
  	struct stat stat_buf;
  
  	/* configdir is -D option, or $PGDATA if no -D */
  	if (userDoption)
! 		configdir = make_absolute_path(userDoption, &errstr);
  	else
! 		configdir = make_absolute_path(getenv("PGDATA"), &errstr);
! 
! 	if (configdir == NULL)
! 		ereport(FATAL, (errmsg_internal("%s", errstr)));
  
  	/*
  	 * Find the configuration file: if config_file was specified on the
***************
*** 4229,4235 **** SelectConfigFiles(const char *userDoption, const char *progname)
  	 * the same way by future backends.
  	 */
  	if (ConfigFileName)
! 		fname = make_absolute_path(ConfigFileName);
  	else if (configdir)
  	{
  		fname = guc_malloc(FATAL,
--- 4233,4243 ----
  	 * the same way by future backends.
  	 */
  	if (ConfigFileName)
! 	{
! 		fname = make_absolute_path(ConfigFileName, &errstr);
! 		if (fname == NULL)
! 			ereport(FATAL, (errmsg_internal("%s", errstr)));
! 	}
  	else if (configdir)
  	{
  		fname = guc_malloc(FATAL,
***************
*** 4311,4317 **** SelectConfigFiles(const char *userDoption, const char *progname)
  	 * Figure out where pg_hba.conf is, and make sure the path is absolute.
  	 */
  	if (HbaFileName)
! 		fname = make_absolute_path(HbaFileName);
  	else if (configdir)
  	{
  		fname = guc_malloc(FATAL,
--- 4319,4329 ----
  	 * Figure out where pg_hba.conf is, and make sure the path is absolute.
  	 */
  	if (HbaFileName)
! 	{
! 		fname = make_absolute_path(HbaFileName, &errstr);
! 		if (fname == NULL)
! 			ereport(FATAL, (errmsg_internal("%s", errstr)));
! 	}
  	else if (configdir)
  	{
  		fname = guc_malloc(FATAL,
***************
*** 4334,4340 **** SelectConfigFiles(const char *userDoption, const char *progname)
  	 * Likewise for pg_ident.conf.
  	 */
  	if (IdentFileName)
! 		fname = make_absolute_path(IdentFileName);
  	else if (configdir)
  	{
  		fname = guc_malloc(FATAL,
--- 4346,4356 ----
  	 * Likewise for pg_ident.conf.
  	 */
  	if (IdentFileName)
! 	{
! 		fname = make_absolute_path(IdentFileName, &errstr);
! 		if (fname == NULL)
! 			ereport(FATAL, (errmsg_internal("%s", errstr)));
! 	}
  	else if (configdir)
  	{
  		fname = guc_malloc(FATAL,
*** a/src/include/miscadmin.h
--- b/src/include/miscadmin.h
***************
*** 296,302 **** extern void SetCurrentRoleId(Oid roleid, bool is_superuser);
  
  extern void SetDataDir(const char *dir);
  extern void ChangeToDataDir(void);
- extern char *make_absolute_path(const char *path);
  
  /* in utils/misc/superuser.c */
  extern bool superuser(void);	/* current user is superuser */
--- 296,301 ----
*** a/src/include/port.h
--- b/src/include/port.h
***************
*** 60,65 **** extern void get_man_path(const char *my_exec_path, char *ret_path);
--- 60,69 ----
  extern bool get_home_path(char *ret_path);
  extern void get_parent_directory(char *path);
  
+ /* port/abspath.c */
+ extern char *make_absolute_path(const char *path, char **errstr);
+ extern char *make_absolute_path_or_exit(const char *progname, const char *path);
+ 
  /* port/dirmod.c */
  extern char **pgfnames(const char *path);
  extern void pgfnames_cleanup(char **filenames);
*** a/src/interfaces/ecpg/ecpglib/Makefile
--- b/src/interfaces/ecpg/ecpglib/Makefile
***************
*** 25,31 **** override CFLAGS += $(PTHREAD_CFLAGS)
  LIBS := $(filter-out -lpgport, $(LIBS))
  
  OBJS= execute.o typename.o descriptor.o sqlda.o data.o error.o prepare.o memory.o \
! 	connect.o misc.o path.o pgstrcasecmp.o \
  	$(filter snprintf.o strlcpy.o win32setlocale.o isinf.o, $(LIBOBJS))
  
  # thread.c is needed only for non-WIN32 implementation of path.c
--- 25,31 ----
  LIBS := $(filter-out -lpgport, $(LIBS))
  
  OBJS= execute.o typename.o descriptor.o sqlda.o data.o error.o prepare.o memory.o \
! 	connect.o misc.o path.o pgstrcasecmp.o psprintf.o \
  	$(filter snprintf.o strlcpy.o win32setlocale.o isinf.o, $(LIBOBJS))
  
  # thread.c is needed only for non-WIN32 implementation of path.c
***************
*** 62,67 **** include $(top_srcdir)/src/Makefile.shlib
--- 62,70 ----
  path.c pgstrcasecmp.c snprintf.c strlcpy.c thread.c win32setlocale.c isinf.c: % : $(top_srcdir)/src/port/%
  	rm -f $@ && $(LN_S) $< .
  
+ psprintf.c : % : $(top_srcdir)/src/common/%
+ 	rm -f $@ && $(LN_S) $< .
+ 
  misc.o: misc.c $(top_builddir)/src/port/pg_config_paths.h
  path.o: path.c $(top_builddir)/src/port/pg_config_paths.h
  
***************
*** 76,81 **** uninstall: uninstall-lib
  
  clean distclean: clean-lib
  	rm -f $(OBJS)
! 	rm -f path.c pgstrcasecmp.c snprintf.c strlcpy.c thread.c win32setlocale.c
  
  maintainer-clean: distclean maintainer-clean-lib
--- 79,84 ----
  
  clean distclean: clean-lib
  	rm -f $(OBJS)
! 	rm -f path.c pgstrcasecmp.c snprintf.c strlcpy.c thread.c win32setlocale.c psprintf.c
  
  maintainer-clean: distclean maintainer-clean-lib
*** a/src/port/path.c
--- b/src/port/path.c
***************
*** 13,18 ****
--- 13,24 ----
   *-------------------------------------------------------------------------
   */
  
+ #ifndef FRONTEND
+ #include "postgres.h"
+ #else
+ #include "postgres_fe.h"
+ #endif
+ 
  #include "c.h"
  
  #include <ctype.h>
***************
*** 757,759 **** trim_trailing_separator(char *path)
--- 763,861 ----
  		for (p--; p > path && IS_DIR_SEP(*p); p--)
  			*p = '\0';
  }
+ 
+ /*
+  * If the given pathname isn't already absolute, make it so, interpreting
+  * it relative to the current working directory.
+  *
+  * Also canonicalizes the path.  The result is always a malloc'd copy.
+  * incase of error, the errstr is filled with palloced copy of error and
+  * returns NULL. Caller needs to take care of freeing the errstr memory.
+  */
+ char *
+ make_absolute_path(const char *path, char **errstr)
+ {
+ 	char	   *result;
+ 
+ 	/* Returning null for null input is convenient for some callers */
+ 	if (path == NULL)
+ 		return NULL;
+ 
+ 	if (!is_absolute_path(path))
+ 	{
+ 		char	   *buf;
+ 		size_t		buflen;
+ 
+ 		buflen = MAXPGPATH;
+ 		for (;;)
+ 		{
+ 			buf = malloc(buflen);
+ 			if (buf == NULL)
+ 			{
+ 				*errstr = psprintf("out of memory");
+ 				return NULL;
+ 			}
+ 			if (getcwd(buf, buflen))
+ 				break;
+ 			else if (errno == ERANGE)
+ 			{
+ 				free(buf);
+ 				buflen *= 2;
+ 				continue;
+ 			}
+ 			else
+ 			{
+ 				free(buf);
+ 				*errstr = psprintf("could not get current working directory :%s", strerror(errno));
+ 				return NULL;
+ 			}
+ 		}
+ 
+ 		result = malloc(strlen(buf) + strlen(path) + 2);
+ 		if (result == NULL)
+ 		{
+ 			free(buf);
+ 			*errstr = psprintf("out of memory");
+ 			return NULL;
+ 		}
+ 
+ 		sprintf(result, "%s/%s", buf, path);
+ 		free(buf);
+ 	}
+ 	else
+ 	{
+ 		result = strdup(path);
+ 		if (result == NULL)
+ 		{
+ 			*errstr = psprintf("out of memory");
+ 			return NULL;
+ 		}
+ 	}
+ 
+ 	/* Make sure punctuation is canonical, too */
+ 	canonicalize_path(result);
+ 	return result;
+ }
+ 
+ /*
+  * If the given pathname isn't already absolute, make it so, interpreting
+  * it relative to the current working directory.
+  *
+  * Also canonicalizes the path.  The result is always a malloc'd copy.
+  * incase of error it exits.
+  */
+ char *
+ make_absolute_path_or_exit(const char *progname, const char *path)
+ {
+ 	char	   *errstr;
+ 	char	   *result;
+ 
+ 	result = make_absolute_path(path, &errstr);
+ 	if (result == NULL)
+ 	{
+ 		fprintf(stderr, "%s: %s\n", progname, errstr);
+ 		exit(1);
+ 	}
+ 
+ 	return result;
+ }
*** a/src/test/regress/pg_regress.c
--- b/src/test/regress/pg_regress.c
***************
*** 1832,1864 **** create_role(const char *rolename, const _stringlist * granted_dbs)
  	}
  }
  
- static char *
- make_absolute_path(const char *in)
- {
- 	char	   *result;
- 
- 	if (is_absolute_path(in))
- 		result = strdup(in);
- 	else
- 	{
- 		static char cwdbuf[MAXPGPATH];
- 
- 		if (!cwdbuf[0])
- 		{
- 			if (!getcwd(cwdbuf, sizeof(cwdbuf)))
- 			{
- 				fprintf(stderr, _("could not get current working directory: %s\n"), strerror(errno));
- 				exit(2);
- 			}
- 		}
- 
- 		result = psprintf("%s/%s", cwdbuf, in);
- 	}
- 
- 	canonicalize_path(result);
- 	return result;
- }
- 
  static void
  help(void)
  {
--- 1832,1837 ----
***************
*** 2003,2009 **** regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
  				add_stringlist_item(&schedulelist, optarg);
  				break;
  			case 9:
! 				temp_install = make_absolute_path(optarg);
  				break;
  			case 10:
  				nolocale = true;
--- 1976,1982 ----
  				add_stringlist_item(&schedulelist, optarg);
  				break;
  			case 9:
! 				temp_install = make_absolute_path_or_exit(progname, optarg);
  				break;
  			case 10:
  				nolocale = true;
***************
*** 2073,2081 **** regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
  		 */
  		port = 0xC000 | (PG_VERSION_NUM & 0x3FFF);
  
! 	inputdir = make_absolute_path(inputdir);
! 	outputdir = make_absolute_path(outputdir);
! 	dlpath = make_absolute_path(dlpath);
  
  	/*
  	 * Initialization
--- 2046,2054 ----
  		 */
  		port = 0xC000 | (PG_VERSION_NUM & 0x3FFF);
  
! 	inputdir = make_absolute_path_or_exit(progname, inputdir);
! 	outputdir = make_absolute_path_or_exit(progname, outputdir);
! 	dlpath = make_absolute_path_or_exit(progname, dlpath);
  
  	/*
  	 * Initialization
