diff --git a/configure b/configure
index 836d68d..fadd06e 100755
*** a/configure
--- b/configure
*************** esac
*** 15537,15555 ****
  
  fi
  
- ac_fn_c_check_func "$LINENO" "strerror" "ac_cv_func_strerror"
- if test "x$ac_cv_func_strerror" = xyes; then :
-   $as_echo "#define HAVE_STRERROR 1" >>confdefs.h
- 
- else
-   case " $LIBOBJS " in
-   *" strerror.$ac_objext "* ) ;;
-   *) LIBOBJS="$LIBOBJS strerror.$ac_objext"
-  ;;
- esac
- 
- fi
- 
  ac_fn_c_check_func "$LINENO" "strlcat" "ac_cv_func_strlcat"
  if test "x$ac_cv_func_strlcat" = xyes; then :
    $as_echo "#define HAVE_STRLCAT 1" >>confdefs.h
--- 15537,15542 ----
diff --git a/configure.in b/configure.in
index 6e14106..3adec10 100644
*** a/configure.in
--- b/configure.in
*************** else
*** 1649,1655 ****
    AC_CHECK_FUNCS([fpclass fp_class fp_class_d class], [break])
  fi
  
! AC_REPLACE_FUNCS([crypt fls getopt getrusage inet_aton mkdtemp random rint srandom strerror strlcat strlcpy strnlen])
  
  case $host_os in
  
--- 1649,1655 ----
    AC_CHECK_FUNCS([fpclass fp_class fp_class_d class], [break])
  fi
  
! AC_REPLACE_FUNCS([crypt fls getopt getrusage inet_aton mkdtemp random rint srandom strlcat strlcpy strnlen])
  
  case $host_os in
  
diff --git a/src/backend/port/win32/socket.c b/src/backend/port/win32/socket.c
index f4356fe..af35cfb 100644
*** a/src/backend/port/win32/socket.c
--- b/src/backend/port/win32/socket.c
*************** pgwin32_select(int nfds, fd_set *readfds
*** 690,728 ****
  		memcpy(writefds, &outwritefds, sizeof(fd_set));
  	return nummatches;
  }
- 
- 
- /*
-  * Return win32 error string, since strerror can't
-  * handle winsock codes
-  */
- static char wserrbuf[256];
- const char *
- pgwin32_socket_strerror(int err)
- {
- 	static HANDLE handleDLL = INVALID_HANDLE_VALUE;
- 
- 	if (handleDLL == INVALID_HANDLE_VALUE)
- 	{
- 		handleDLL = LoadLibraryEx("netmsg.dll", NULL, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE);
- 		if (handleDLL == NULL)
- 			ereport(FATAL,
- 					(errmsg_internal("could not load netmsg.dll: error code %lu", GetLastError())));
- 	}
- 
- 	ZeroMemory(&wserrbuf, sizeof(wserrbuf));
- 	if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS |
- 					  FORMAT_MESSAGE_FROM_SYSTEM |
- 					  FORMAT_MESSAGE_FROM_HMODULE,
- 					  handleDLL,
- 					  err,
- 					  MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
- 					  wserrbuf,
- 					  sizeof(wserrbuf) - 1,
- 					  NULL) == 0)
- 	{
- 		/* Failed to get id */
- 		sprintf(wserrbuf, "unrecognized winsock error %d", err);
- 	}
- 	return wserrbuf;
- }
--- 690,692 ----
diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
index 16531f7..22e5d87 100644
*** a/src/backend/utils/error/elog.c
--- b/src/backend/utils/error/elog.c
*************** static void send_message_to_server_log(E
*** 178,185 ****
  static void write_pipe_chunks(char *data, int len, int dest);
  static void send_message_to_frontend(ErrorData *edata);
  static char *expand_fmt_string(const char *fmt, ErrorData *edata);
- static const char *useful_strerror(int errnum);
- static const char *get_errno_symbol(int errnum);
  static const char *error_severity(int elevel);
  static void append_with_tabs(StringInfo buf, const char *str);
  static bool is_log_level_output(int elevel, int log_min_level);
--- 178,183 ----
*************** expand_fmt_string(const char *fmt, Error
*** 3360,3366 ****
  				 */
  				const char *cp2;
  
! 				cp2 = useful_strerror(edata->saved_errno);
  				for (; *cp2; cp2++)
  				{
  					if (*cp2 == '%')
--- 3358,3364 ----
  				 */
  				const char *cp2;
  
! 				cp2 = strerror(edata->saved_errno);
  				for (; *cp2; cp2++)
  				{
  					if (*cp2 == '%')
*************** expand_fmt_string(const char *fmt, Error
*** 3384,3602 ****
  
  
  /*
-  * A slightly cleaned-up version of strerror()
-  */
- static const char *
- useful_strerror(int errnum)
- {
- 	/* this buffer is only used if strerror() and get_errno_symbol() fail */
- 	static char errorstr_buf[48];
- 	const char *str;
- 
- #ifdef WIN32
- 	/* Winsock error code range, per WinError.h */
- 	if (errnum >= 10000 && errnum <= 11999)
- 		return pgwin32_socket_strerror(errnum);
- #endif
- 	str = strerror(errnum);
- 
- 	/*
- 	 * Some strerror()s return an empty string for out-of-range errno.  This
- 	 * is ANSI C spec compliant, but not exactly useful.  Also, we may get
- 	 * back strings of question marks if libc cannot transcode the message to
- 	 * the codeset specified by LC_CTYPE.  If we get nothing useful, first try
- 	 * get_errno_symbol(), and if that fails, print the numeric errno.
- 	 */
- 	if (str == NULL || *str == '\0' || *str == '?')
- 		str = get_errno_symbol(errnum);
- 
- 	if (str == NULL)
- 	{
- 		snprintf(errorstr_buf, sizeof(errorstr_buf),
- 		/*------
- 		  translator: This string will be truncated at 47
- 		  characters expanded. */
- 				 _("operating system error %d"), errnum);
- 		str = errorstr_buf;
- 	}
- 
- 	return str;
- }
- 
- /*
-  * Returns a symbol (e.g. "ENOENT") for an errno code.
-  * Returns NULL if the code is unrecognized.
-  */
- static const char *
- get_errno_symbol(int errnum)
- {
- 	switch (errnum)
- 	{
- 		case E2BIG:
- 			return "E2BIG";
- 		case EACCES:
- 			return "EACCES";
- #ifdef EADDRINUSE
- 		case EADDRINUSE:
- 			return "EADDRINUSE";
- #endif
- #ifdef EADDRNOTAVAIL
- 		case EADDRNOTAVAIL:
- 			return "EADDRNOTAVAIL";
- #endif
- 		case EAFNOSUPPORT:
- 			return "EAFNOSUPPORT";
- #ifdef EAGAIN
- 		case EAGAIN:
- 			return "EAGAIN";
- #endif
- #ifdef EALREADY
- 		case EALREADY:
- 			return "EALREADY";
- #endif
- 		case EBADF:
- 			return "EBADF";
- #ifdef EBADMSG
- 		case EBADMSG:
- 			return "EBADMSG";
- #endif
- 		case EBUSY:
- 			return "EBUSY";
- 		case ECHILD:
- 			return "ECHILD";
- #ifdef ECONNABORTED
- 		case ECONNABORTED:
- 			return "ECONNABORTED";
- #endif
- 		case ECONNREFUSED:
- 			return "ECONNREFUSED";
- #ifdef ECONNRESET
- 		case ECONNRESET:
- 			return "ECONNRESET";
- #endif
- 		case EDEADLK:
- 			return "EDEADLK";
- 		case EDOM:
- 			return "EDOM";
- 		case EEXIST:
- 			return "EEXIST";
- 		case EFAULT:
- 			return "EFAULT";
- 		case EFBIG:
- 			return "EFBIG";
- #ifdef EHOSTUNREACH
- 		case EHOSTUNREACH:
- 			return "EHOSTUNREACH";
- #endif
- 		case EIDRM:
- 			return "EIDRM";
- 		case EINPROGRESS:
- 			return "EINPROGRESS";
- 		case EINTR:
- 			return "EINTR";
- 		case EINVAL:
- 			return "EINVAL";
- 		case EIO:
- 			return "EIO";
- #ifdef EISCONN
- 		case EISCONN:
- 			return "EISCONN";
- #endif
- 		case EISDIR:
- 			return "EISDIR";
- #ifdef ELOOP
- 		case ELOOP:
- 			return "ELOOP";
- #endif
- 		case EMFILE:
- 			return "EMFILE";
- 		case EMLINK:
- 			return "EMLINK";
- 		case EMSGSIZE:
- 			return "EMSGSIZE";
- 		case ENAMETOOLONG:
- 			return "ENAMETOOLONG";
- 		case ENFILE:
- 			return "ENFILE";
- 		case ENOBUFS:
- 			return "ENOBUFS";
- 		case ENODEV:
- 			return "ENODEV";
- 		case ENOENT:
- 			return "ENOENT";
- 		case ENOEXEC:
- 			return "ENOEXEC";
- 		case ENOMEM:
- 			return "ENOMEM";
- 		case ENOSPC:
- 			return "ENOSPC";
- 		case ENOSYS:
- 			return "ENOSYS";
- #ifdef ENOTCONN
- 		case ENOTCONN:
- 			return "ENOTCONN";
- #endif
- 		case ENOTDIR:
- 			return "ENOTDIR";
- #if defined(ENOTEMPTY) && (ENOTEMPTY != EEXIST) /* same code on AIX */
- 		case ENOTEMPTY:
- 			return "ENOTEMPTY";
- #endif
- #ifdef ENOTSOCK
- 		case ENOTSOCK:
- 			return "ENOTSOCK";
- #endif
- #ifdef ENOTSUP
- 		case ENOTSUP:
- 			return "ENOTSUP";
- #endif
- 		case ENOTTY:
- 			return "ENOTTY";
- 		case ENXIO:
- 			return "ENXIO";
- #if defined(EOPNOTSUPP) && (!defined(ENOTSUP) || (EOPNOTSUPP != ENOTSUP))
- 		case EOPNOTSUPP:
- 			return "EOPNOTSUPP";
- #endif
- #ifdef EOVERFLOW
- 		case EOVERFLOW:
- 			return "EOVERFLOW";
- #endif
- 		case EPERM:
- 			return "EPERM";
- 		case EPIPE:
- 			return "EPIPE";
- 		case EPROTONOSUPPORT:
- 			return "EPROTONOSUPPORT";
- 		case ERANGE:
- 			return "ERANGE";
- #ifdef EROFS
- 		case EROFS:
- 			return "EROFS";
- #endif
- 		case ESRCH:
- 			return "ESRCH";
- #ifdef ETIMEDOUT
- 		case ETIMEDOUT:
- 			return "ETIMEDOUT";
- #endif
- #ifdef ETXTBSY
- 		case ETXTBSY:
- 			return "ETXTBSY";
- #endif
- #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
- 		case EWOULDBLOCK:
- 			return "EWOULDBLOCK";
- #endif
- 		case EXDEV:
- 			return "EXDEV";
- 	}
- 
- 	return NULL;
- }
- 
- 
- /*
   * error_severity --- get string representing elevel
   *
   * The string is not localized here, but we mark the strings for translation
--- 3382,3387 ----
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 827574e..2861b1f 100644
*** a/src/include/pg_config.h.in
--- b/src/include/pg_config.h.in
***************
*** 519,527 ****
  /* Define to 1 if you have the <stdlib.h> header file. */
  #undef HAVE_STDLIB_H
  
- /* Define to 1 if you have the `strerror' function. */
- #undef HAVE_STRERROR
- 
  /* Define to 1 if you have the `strerror_r' function. */
  #undef HAVE_STRERROR_R
  
--- 519,524 ----
diff --git a/src/include/pg_config.h.win32 b/src/include/pg_config.h.win32
index 46ce49d..4c68fa8 100644
*** a/src/include/pg_config.h.win32
--- b/src/include/pg_config.h.win32
***************
*** 390,400 ****
  /* Define to 1 if you have the <stdlib.h> header file. */
  #define HAVE_STDLIB_H 1
  
- /* Define to 1 if you have the `strerror' function. */
- #ifndef HAVE_STRERROR
- #define HAVE_STRERROR 1
- #endif
- 
  /* Define to 1 if you have the `strerror_r' function. */
  /* #undef HAVE_STRERROR_R */
  
--- 390,395 ----
diff --git a/src/include/port.h b/src/include/port.h
index 74a9dc4..dae80cb 100644
*** a/src/include/port.h
--- b/src/include/port.h
*************** extern int	pg_printf(const char *fmt,...
*** 189,194 ****
--- 189,198 ----
  #endif
  #endif							/* USE_REPL_SNPRINTF */
  
+ /* Replace strerror() with our own, somewhat more robust wrapper */
+ extern char *pg_strerror(int errnum);
+ #define strerror pg_strerror
+ 
  /* Portable prompt handling */
  extern void simple_prompt(const char *prompt, char *destination, size_t destlen,
  			  bool echo);
diff --git a/src/include/port/win32_port.h b/src/include/port/win32_port.h
index b398cd3..360dbdf 100644
*** a/src/include/port/win32_port.h
--- b/src/include/port/win32_port.h
*************** extern int	pgwin32_safestat(const char *
*** 322,329 ****
   * Supplement to <errno.h>.
   *
   * We redefine network-related Berkeley error symbols as the corresponding WSA
!  * constants.  This allows elog.c to recognize them as being in the Winsock
!  * error code range and pass them off to pgwin32_socket_strerror(), since
   * Windows' version of plain strerror() won't cope.  Note that this will break
   * if these names are used for anything else besides Windows Sockets errors.
   * See TranslateSocketError() when changing this list.
--- 322,329 ----
   * Supplement to <errno.h>.
   *
   * We redefine network-related Berkeley error symbols as the corresponding WSA
!  * constants. This allows strerror.c to recognize them as being in the Winsock
!  * error code range and pass them off to win32_socket_strerror(), since
   * Windows' version of plain strerror() won't cope.  Note that this will break
   * if these names are used for anything else besides Windows Sockets errors.
   * See TranslateSocketError() when changing this list.
*************** int			pgwin32_connect(SOCKET s, const st
*** 456,463 ****
  int			pgwin32_select(int nfds, fd_set *readfs, fd_set *writefds, fd_set *exceptfds, const struct timeval *timeout);
  int			pgwin32_recv(SOCKET s, char *buf, int len, int flags);
  int			pgwin32_send(SOCKET s, const void *buf, int len, int flags);
- 
- const char *pgwin32_socket_strerror(int err);
  int			pgwin32_waitforsinglesocket(SOCKET s, int what, int timeout);
  
  extern int	pgwin32_noblock;
--- 456,461 ----
diff --git a/src/interfaces/ecpg/compatlib/.gitignore b/src/interfaces/ecpg/compatlib/.gitignore
index ad5ba13..8b9aa95 100644
*** a/src/interfaces/ecpg/compatlib/.gitignore
--- b/src/interfaces/ecpg/compatlib/.gitignore
***************
*** 2,5 ****
--- 2,6 ----
  /blibecpg_compatdll.def
  /exports.list
  /snprintf.c
+ /strerror.c
  /strnlen.c
diff --git a/src/interfaces/ecpg/compatlib/Makefile b/src/interfaces/ecpg/compatlib/Makefile
index ebfd895..b7bd162 100644
*** a/src/interfaces/ecpg/compatlib/Makefile
--- b/src/interfaces/ecpg/compatlib/Makefile
*************** SHLIB_EXPORTS = exports.txt
*** 31,37 ****
  # Need to recompile any libpgport object files
  LIBS := $(filter-out -lpgport, $(LIBS))
  
! OBJS= informix.o $(filter snprintf.o strnlen.o, $(LIBOBJS)) $(WIN32RES)
  
  PKG_CONFIG_REQUIRES_PRIVATE = libecpg libpgtypes
  
--- 31,37 ----
  # Need to recompile any libpgport object files
  LIBS := $(filter-out -lpgport, $(LIBS))
  
! OBJS= informix.o strerror.o $(filter snprintf.o strnlen.o, $(LIBOBJS)) $(WIN32RES)
  
  PKG_CONFIG_REQUIRES_PRIVATE = libecpg libpgtypes
  
*************** submake-pgtypeslib:
*** 48,54 ****
  # Shared library stuff
  include $(top_srcdir)/src/Makefile.shlib
  
! snprintf.c strnlen.c: % : $(top_srcdir)/src/port/%
  	rm -f $@ && $(LN_S) $< .
  
  install: all installdirs install-lib
--- 48,54 ----
  # Shared library stuff
  include $(top_srcdir)/src/Makefile.shlib
  
! snprintf.c strerror.c strnlen.c: % : $(top_srcdir)/src/port/%
  	rm -f $@ && $(LN_S) $< .
  
  install: all installdirs install-lib
*************** installdirs: installdirs-lib
*** 58,63 ****
  uninstall: uninstall-lib
  
  clean distclean: clean-lib
! 	rm -f $(OBJS) snprintf.c strnlen.c
  
  maintainer-clean: distclean maintainer-clean-lib
--- 58,63 ----
  uninstall: uninstall-lib
  
  clean distclean: clean-lib
! 	rm -f $(OBJS) snprintf.c strerror.c strnlen.c
  
  maintainer-clean: distclean maintainer-clean-lib
diff --git a/src/interfaces/ecpg/ecpglib/.gitignore b/src/interfaces/ecpg/ecpglib/.gitignore
index 1619e97..545c106 100644
*** a/src/interfaces/ecpg/ecpglib/.gitignore
--- b/src/interfaces/ecpg/ecpglib/.gitignore
***************
*** 4,9 ****
--- 4,10 ----
  /path.c
  /pgstrcasecmp.c
  /snprintf.c
+ /strerror.c
  /strlcpy.c
  /strnlen.c
  /thread.c
diff --git a/src/interfaces/ecpg/ecpglib/Makefile b/src/interfaces/ecpg/ecpglib/Makefile
index d25d248..005d25a 100644
*** a/src/interfaces/ecpg/ecpglib/Makefile
--- b/src/interfaces/ecpg/ecpglib/Makefile
*************** override CFLAGS += $(PTHREAD_CFLAGS)
*** 26,32 ****
  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 strnlen.o win32setlocale.o isinf.o, $(LIBOBJS)) \
  	$(WIN32RES)
  
--- 26,32 ----
  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 strerror.o \
  	$(filter snprintf.o strlcpy.o strnlen.o win32setlocale.o isinf.o, $(LIBOBJS)) \
  	$(WIN32RES)
  
*************** include $(top_srcdir)/src/Makefile.shlib
*** 57,63 ****
  # necessarily use the same object files as the backend uses. Instead,
  # symlink the source files in here and build our own object file.
  
! path.c pgstrcasecmp.c snprintf.c strlcpy.c strnlen.c thread.c win32setlocale.c isinf.c: % : $(top_srcdir)/src/port/%
  	rm -f $@ && $(LN_S) $< .
  
  misc.o: misc.c $(top_builddir)/src/port/pg_config_paths.h
--- 57,63 ----
  # necessarily use the same object files as the backend uses. Instead,
  # symlink the source files in here and build our own object file.
  
! path.c pgstrcasecmp.c snprintf.c strerror.c strlcpy.c strnlen.c thread.c win32setlocale.c isinf.c: % : $(top_srcdir)/src/port/%
  	rm -f $@ && $(LN_S) $< .
  
  misc.o: misc.c $(top_builddir)/src/port/pg_config_paths.h
*************** uninstall: uninstall-lib
*** 74,79 ****
  
  clean distclean: clean-lib
  	rm -f $(OBJS)
! 	rm -f path.c pgstrcasecmp.c snprintf.c strlcpy.c strnlen.c thread.c win32setlocale.c isinf.c
  
  maintainer-clean: distclean maintainer-clean-lib
--- 74,79 ----
  
  clean distclean: clean-lib
  	rm -f $(OBJS)
! 	rm -f path.c pgstrcasecmp.c snprintf.c strerror.c strlcpy.c strnlen.c thread.c win32setlocale.c isinf.c
  
  maintainer-clean: distclean maintainer-clean-lib
diff --git a/src/interfaces/ecpg/pgtypeslib/.gitignore b/src/interfaces/ecpg/pgtypeslib/.gitignore
index d5f0fae..b3fae08 100644
*** a/src/interfaces/ecpg/pgtypeslib/.gitignore
--- b/src/interfaces/ecpg/pgtypeslib/.gitignore
***************
*** 4,8 ****
--- 4,9 ----
  /pgstrcasecmp.c
  /rint.c
  /snprintf.c
+ /strerror.c
  /string.c
  /strnlen.c
diff --git a/src/interfaces/ecpg/pgtypeslib/Makefile b/src/interfaces/ecpg/pgtypeslib/Makefile
index 29264ce..18b2402 100644
*** a/src/interfaces/ecpg/pgtypeslib/Makefile
--- b/src/interfaces/ecpg/pgtypeslib/Makefile
*************** SHLIB_LINK += $(filter -lm, $(LIBS))
*** 30,36 ****
  SHLIB_EXPORTS = exports.txt
  
  OBJS= numeric.o datetime.o common.o dt_common.o timestamp.o interval.o \
! 	pgstrcasecmp.o \
  	$(filter rint.o snprintf.o strnlen.o, $(LIBOBJS)) \
  	string.o \
  	$(WIN32RES)
--- 30,36 ----
  SHLIB_EXPORTS = exports.txt
  
  OBJS= numeric.o datetime.o common.o dt_common.o timestamp.o interval.o \
! 	pgstrcasecmp.o strerror.o \
  	$(filter rint.o snprintf.o strnlen.o, $(LIBOBJS)) \
  	string.o \
  	$(WIN32RES)
*************** include $(top_srcdir)/src/Makefile.shlib
*** 45,51 ****
  # necessarily use the same object files as the backend uses. Instead,
  # symlink the source files in here and build our own object file.
  
! pgstrcasecmp.c rint.c snprintf.c strnlen.c: % : $(top_srcdir)/src/port/%
  	rm -f $@ && $(LN_S) $< .
  
  string.c: % : $(top_srcdir)/src/common/%
--- 45,51 ----
  # necessarily use the same object files as the backend uses. Instead,
  # symlink the source files in here and build our own object file.
  
! pgstrcasecmp.c rint.c snprintf.c strerror.c strnlen.c: % : $(top_srcdir)/src/port/%
  	rm -f $@ && $(LN_S) $< .
  
  string.c: % : $(top_srcdir)/src/common/%
*************** installdirs: installdirs-lib
*** 58,63 ****
  uninstall: uninstall-lib
  
  clean distclean: clean-lib
! 	rm -f $(OBJS) pgstrcasecmp.c rint.c snprintf.c strnlen.c string.c
  
  maintainer-clean: distclean maintainer-clean-lib
--- 58,63 ----
  uninstall: uninstall-lib
  
  clean distclean: clean-lib
! 	rm -f $(OBJS) pgstrcasecmp.c rint.c snprintf.c strerror.c strnlen.c string.c
  
  maintainer-clean: distclean maintainer-clean-lib
diff --git a/src/interfaces/libpq/Makefile b/src/interfaces/libpq/Makefile
index abe0a50..9af7cc0 100644
*** a/src/interfaces/libpq/Makefile
--- b/src/interfaces/libpq/Makefile
*************** OBJS=	fe-auth.o fe-auth-scram.o fe-conne
*** 36,44 ****
  	libpq-events.o
  # libpgport C files we always use
  OBJS += chklocale.o inet_net_ntop.o noblock.o pgstrcasecmp.o pqsignal.o \
! 	thread.o
  # libpgport C files that are needed if identified by configure
! OBJS += $(filter crypt.o getaddrinfo.o getpeereid.o inet_aton.o open.o system.o snprintf.o strerror.o strlcpy.o strnlen.o win32error.o win32setlocale.o, $(LIBOBJS))
  
  ifeq ($(enable_strong_random), yes)
  OBJS += pg_strong_random.o
--- 36,44 ----
  	libpq-events.o
  # libpgport C files we always use
  OBJS += chklocale.o inet_net_ntop.o noblock.o pgstrcasecmp.o pqsignal.o \
! 	strerror.o thread.o
  # libpgport C files that are needed if identified by configure
! OBJS += $(filter crypt.o getaddrinfo.o getpeereid.o inet_aton.o open.o system.o snprintf.o strlcpy.o strnlen.o win32error.o win32setlocale.o, $(LIBOBJS))
  
  ifeq ($(enable_strong_random), yes)
  OBJS += pg_strong_random.o
diff --git a/src/pl/plpython/plpython.h b/src/pl/plpython/plpython.h
index 5c2e6a8..6cc323a 100644
*** a/src/pl/plpython/plpython.h
--- b/src/pl/plpython/plpython.h
***************
*** 27,33 ****
   */
  #undef _POSIX_C_SOURCE
  #undef _XOPEN_SOURCE
- #undef HAVE_STRERROR
  #undef HAVE_TZNAME
  
  /*
--- 27,32 ----
diff --git a/src/port/Makefile b/src/port/Makefile
index d7467fb..b3a10ba 100644
*** a/src/port/Makefile
--- b/src/port/Makefile
*************** LIBS += $(PTHREAD_LIBS)
*** 33,39 ****
  OBJS = $(LIBOBJS) $(PG_CRC32C_OBJS) chklocale.o erand48.o inet_net_ntop.o \
  	noblock.o path.o pgcheckdir.o pgmkdirp.o pgsleep.o \
  	pgstrcasecmp.o pqsignal.o \
! 	qsort.o qsort_arg.o quotes.o sprompt.o tar.o thread.o
  
  ifeq ($(enable_strong_random), yes)
  OBJS += pg_strong_random.o
--- 33,39 ----
  OBJS = $(LIBOBJS) $(PG_CRC32C_OBJS) chklocale.o erand48.o inet_net_ntop.o \
  	noblock.o path.o pgcheckdir.o pgmkdirp.o pgsleep.o \
  	pgstrcasecmp.o pqsignal.o \
! 	qsort.o qsort_arg.o quotes.o sprompt.o strerror.o tar.o thread.o
  
  ifeq ($(enable_strong_random), yes)
  OBJS += pg_strong_random.o
diff --git a/src/port/strerror.c b/src/port/strerror.c
index e92ebc9..e3393eb 100644
*** a/src/port/strerror.c
--- b/src/port/strerror.c
***************
*** 1,30 ****
! /* src/port/strerror.c */
! 
! /*
!  * strerror - map error number to descriptive string
   *
!  * This version is obviously somewhat Unix-specific.
   *
!  * based on code by Henry Spencer
!  * modified for ANSI by D'Arcy J.M. Cain
   */
- 
  #include "c.h"
  
  
! extern const char *const sys_errlist[];
! extern int	sys_nerr;
  
! const char *
! strerror(int errnum)
  {
! 	static char buf[24];
  
! 	if (errnum < 0 || errnum > sys_nerr)
  	{
! 		sprintf(buf, _("unrecognized error %d"), errnum);
! 		return buf;
  	}
  
! 	return sys_errlist[errnum];
  }
--- 1,285 ----
! /*-------------------------------------------------------------------------
   *
!  * strerror.c
!  *	  Replacement for standard strerror() function
   *
!  * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
!  * Portions Copyright (c) 1994, Regents of the University of California
!  *
!  *
!  * IDENTIFICATION
!  *	  src/port/strerror.c
!  *
!  *-------------------------------------------------------------------------
   */
  #include "c.h"
  
+ /*
+  * Within this file, "strerror" means the platform's function not pg_strerror
+  */
+ #undef strerror
  
! static char *get_errno_symbol(int errnum);
! #ifdef WIN32
! static char *win32_socket_strerror(int errnum);
! #endif
  
! 
! /*
!  * A slightly cleaned-up version of strerror()
!  */
! char *
! pg_strerror(int errnum)
  {
! 	/* this buffer is only used if strerror() and get_errno_symbol() fail */
! 	static char errorstr_buf[48];
! 	char	   *str;
  
! 	/* If it's a Windows Winsock error, that needs special handling */
! #ifdef WIN32
! 	/* Winsock error code range, per WinError.h */
! 	if (errnum >= 10000 && errnum <= 11999)
! 		return win32_socket_strerror(errnum);
! #endif
! 
! 	/* Try the platform's strerror() */
! 	str = strerror(errnum);
! 
! 	/*
! 	 * Some strerror()s return an empty string for out-of-range errno.  This
! 	 * is ANSI C spec compliant, but not exactly useful.  Also, we may get
! 	 * back strings of question marks if libc cannot transcode the message to
! 	 * the codeset specified by LC_CTYPE.  If we get nothing useful, first try
! 	 * get_errno_symbol(), and if that fails, print the numeric errno.
! 	 */
! 	if (str == NULL || *str == '\0' || *str == '?')
! 		str = get_errno_symbol(errnum);
! 
! 	if (str == NULL)
  	{
! 		snprintf(errorstr_buf, sizeof(errorstr_buf),
! 		/*------
! 		  translator: This string will be truncated at 47
! 		  characters expanded. */
! 				 _("operating system error %d"), errnum);
! 		str = errorstr_buf;
  	}
  
! 	return str;
  }
+ 
+ /*
+  * Returns a symbol (e.g. "ENOENT") for an errno code.
+  * Returns NULL if the code is unrecognized.
+  */
+ static char *
+ get_errno_symbol(int errnum)
+ {
+ 	switch (errnum)
+ 	{
+ 		case E2BIG:
+ 			return "E2BIG";
+ 		case EACCES:
+ 			return "EACCES";
+ #ifdef EADDRINUSE
+ 		case EADDRINUSE:
+ 			return "EADDRINUSE";
+ #endif
+ #ifdef EADDRNOTAVAIL
+ 		case EADDRNOTAVAIL:
+ 			return "EADDRNOTAVAIL";
+ #endif
+ 		case EAFNOSUPPORT:
+ 			return "EAFNOSUPPORT";
+ #ifdef EAGAIN
+ 		case EAGAIN:
+ 			return "EAGAIN";
+ #endif
+ #ifdef EALREADY
+ 		case EALREADY:
+ 			return "EALREADY";
+ #endif
+ 		case EBADF:
+ 			return "EBADF";
+ #ifdef EBADMSG
+ 		case EBADMSG:
+ 			return "EBADMSG";
+ #endif
+ 		case EBUSY:
+ 			return "EBUSY";
+ 		case ECHILD:
+ 			return "ECHILD";
+ #ifdef ECONNABORTED
+ 		case ECONNABORTED:
+ 			return "ECONNABORTED";
+ #endif
+ 		case ECONNREFUSED:
+ 			return "ECONNREFUSED";
+ #ifdef ECONNRESET
+ 		case ECONNRESET:
+ 			return "ECONNRESET";
+ #endif
+ 		case EDEADLK:
+ 			return "EDEADLK";
+ 		case EDOM:
+ 			return "EDOM";
+ 		case EEXIST:
+ 			return "EEXIST";
+ 		case EFAULT:
+ 			return "EFAULT";
+ 		case EFBIG:
+ 			return "EFBIG";
+ #ifdef EHOSTUNREACH
+ 		case EHOSTUNREACH:
+ 			return "EHOSTUNREACH";
+ #endif
+ 		case EIDRM:
+ 			return "EIDRM";
+ 		case EINPROGRESS:
+ 			return "EINPROGRESS";
+ 		case EINTR:
+ 			return "EINTR";
+ 		case EINVAL:
+ 			return "EINVAL";
+ 		case EIO:
+ 			return "EIO";
+ #ifdef EISCONN
+ 		case EISCONN:
+ 			return "EISCONN";
+ #endif
+ 		case EISDIR:
+ 			return "EISDIR";
+ #ifdef ELOOP
+ 		case ELOOP:
+ 			return "ELOOP";
+ #endif
+ 		case EMFILE:
+ 			return "EMFILE";
+ 		case EMLINK:
+ 			return "EMLINK";
+ 		case EMSGSIZE:
+ 			return "EMSGSIZE";
+ 		case ENAMETOOLONG:
+ 			return "ENAMETOOLONG";
+ 		case ENFILE:
+ 			return "ENFILE";
+ 		case ENOBUFS:
+ 			return "ENOBUFS";
+ 		case ENODEV:
+ 			return "ENODEV";
+ 		case ENOENT:
+ 			return "ENOENT";
+ 		case ENOEXEC:
+ 			return "ENOEXEC";
+ 		case ENOMEM:
+ 			return "ENOMEM";
+ 		case ENOSPC:
+ 			return "ENOSPC";
+ 		case ENOSYS:
+ 			return "ENOSYS";
+ #ifdef ENOTCONN
+ 		case ENOTCONN:
+ 			return "ENOTCONN";
+ #endif
+ 		case ENOTDIR:
+ 			return "ENOTDIR";
+ #if defined(ENOTEMPTY) && (ENOTEMPTY != EEXIST) /* same code on AIX */
+ 		case ENOTEMPTY:
+ 			return "ENOTEMPTY";
+ #endif
+ #ifdef ENOTSOCK
+ 		case ENOTSOCK:
+ 			return "ENOTSOCK";
+ #endif
+ #ifdef ENOTSUP
+ 		case ENOTSUP:
+ 			return "ENOTSUP";
+ #endif
+ 		case ENOTTY:
+ 			return "ENOTTY";
+ 		case ENXIO:
+ 			return "ENXIO";
+ #if defined(EOPNOTSUPP) && (!defined(ENOTSUP) || (EOPNOTSUPP != ENOTSUP))
+ 		case EOPNOTSUPP:
+ 			return "EOPNOTSUPP";
+ #endif
+ #ifdef EOVERFLOW
+ 		case EOVERFLOW:
+ 			return "EOVERFLOW";
+ #endif
+ 		case EPERM:
+ 			return "EPERM";
+ 		case EPIPE:
+ 			return "EPIPE";
+ 		case EPROTONOSUPPORT:
+ 			return "EPROTONOSUPPORT";
+ 		case ERANGE:
+ 			return "ERANGE";
+ #ifdef EROFS
+ 		case EROFS:
+ 			return "EROFS";
+ #endif
+ 		case ESRCH:
+ 			return "ESRCH";
+ #ifdef ETIMEDOUT
+ 		case ETIMEDOUT:
+ 			return "ETIMEDOUT";
+ #endif
+ #ifdef ETXTBSY
+ 		case ETXTBSY:
+ 			return "ETXTBSY";
+ #endif
+ #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
+ 		case EWOULDBLOCK:
+ 			return "EWOULDBLOCK";
+ #endif
+ 		case EXDEV:
+ 			return "EXDEV";
+ 	}
+ 
+ 	return NULL;
+ }
+ 
+ 
+ #ifdef WIN32
+ 
+ /*
+  * Windows' strerror() doesn't know the Winsock codes, so handle them this way
+  */
+ static char *
+ win32_socket_strerror(int errnum)
+ {
+ 	static char wserrbuf[256];
+ 	static HANDLE handleDLL = INVALID_HANDLE_VALUE;
+ 
+ 	if (handleDLL == INVALID_HANDLE_VALUE)
+ 	{
+ 		handleDLL = LoadLibraryEx("netmsg.dll", NULL,
+ 								  DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE);
+ 		if (handleDLL == NULL)
+ 		{
+ 			/* just treat this as an unrecognized error ... */
+ 			sprintf(wserrbuf, "unrecognized winsock error %d", errnum);
+ 			return wserrbuf;
+ 		}
+ 	}
+ 
+ 	ZeroMemory(&wserrbuf, sizeof(wserrbuf));
+ 	if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS |
+ 					  FORMAT_MESSAGE_FROM_SYSTEM |
+ 					  FORMAT_MESSAGE_FROM_HMODULE,
+ 					  handleDLL,
+ 					  errnum,
+ 					  MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
+ 					  wserrbuf,
+ 					  sizeof(wserrbuf) - 1,
+ 					  NULL) == 0)
+ 	{
+ 		/* Failed to get id */
+ 		sprintf(wserrbuf, "unrecognized winsock error %d", errnum);
+ 	}
+ 
+ 	return wserrbuf;
+ }
+ 
+ #endif							/* WIN32 */
diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm
index 4543d87..24e9ddf 100644
*** a/src/tools/msvc/Mkvcbuild.pm
--- b/src/tools/msvc/Mkvcbuild.pm
*************** sub mkvcbuild
*** 98,104 ****
  	  erand48.c snprintf.c strlcat.c strlcpy.c dirmod.c noblock.c path.c
  	  pg_strong_random.c pgcheckdir.c pgmkdirp.c pgsleep.c pgstrcasecmp.c
  	  pqsignal.c mkdtemp.c qsort.c qsort_arg.c quotes.c system.c
! 	  sprompt.c tar.c thread.c getopt.c getopt_long.c dirent.c
  	  win32env.c win32error.c win32security.c win32setlocale.c);
  
  	push(@pgportfiles, 'rint.c') if ($vsVersion < '12.00');
--- 98,104 ----
  	  erand48.c snprintf.c strlcat.c strlcpy.c dirmod.c noblock.c path.c
  	  pg_strong_random.c pgcheckdir.c pgmkdirp.c pgsleep.c pgstrcasecmp.c
  	  pqsignal.c mkdtemp.c qsort.c qsort_arg.c quotes.c system.c
! 	  sprompt.c strerror.c tar.c thread.c getopt.c getopt_long.c dirent.c
  	  win32env.c win32error.c win32security.c win32setlocale.c);
  
  	push(@pgportfiles, 'rint.c') if ($vsVersion < '12.00');
