From 69bcd718dfd510750a83e4191b20d9ba3bfcd0fb Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Fri, 18 Jan 2019 15:06:26 -0500
Subject: [PATCH] Use our own getopt() on OpenBSD.

Recent OpenBSD (at least 5.9 and up) has a version of getopt(3)
that will not cope with the "-:" spec we use to accept double-dash
options in postgres.c and postmaster.c.  Admittedly, that's a hack
because POSIX only requires getopt() to allow alphanumeric option
characters.  I have no desire to find another way, however, so
let's just do what we were already doing on Solaris: force use
of our own src/port/getopt.c implementation.

In passing, improve some of the comments around said implementation.

Per buildfarm and local testing.  Back-patch to all supported branches.

Discussion: https://postgr.es/m/30197.1547835700@sss.pgh.pa.us
---
 configure               |  6 +++---
 configure.in            |  6 +++---
 src/include/pg_getopt.h | 10 ++++++++++
 src/port/getopt.c       | 11 +++++------
 4 files changed, 21 insertions(+), 12 deletions(-)

diff --git a/configure b/configure
index 5e4204ae930..67ba8b677ac 100755
--- a/configure
+++ b/configure
@@ -15912,9 +15912,9 @@ esac
 
 fi
 
-# Solaris' getopt() doesn't do what we want for long options, so always use
-# our version on that platform.
-if test "$PORTNAME" = "solaris"; then
+# On OpenBSD and Solaris, getopt() doesn't do what we want for long options
+# (i.e., allow '-' as a flag character), so use our version on those platforms.
+if test "$PORTNAME" = "openbsd" -o "$PORTNAME" = "solaris"; then
   case " $LIBOBJS " in
   *" getopt.$ac_objext "* ) ;;
   *) LIBOBJS="$LIBOBJS getopt.$ac_objext"
diff --git a/configure.in b/configure.in
index 774ebe391f3..0fc0fb3cfe3 100644
--- a/configure.in
+++ b/configure.in
@@ -1738,9 +1738,9 @@ else
   AC_LIBOBJ(getopt_long)
 fi
 
-# Solaris' getopt() doesn't do what we want for long options, so always use
-# our version on that platform.
-if test "$PORTNAME" = "solaris"; then
+# On OpenBSD and Solaris, getopt() doesn't do what we want for long options
+# (i.e., allow '-' as a flag character), so use our version on those platforms.
+if test "$PORTNAME" = "openbsd" -o "$PORTNAME" = "solaris"; then
   AC_LIBOBJ(getopt)
 fi
 
diff --git a/src/include/pg_getopt.h b/src/include/pg_getopt.h
index bb5d2344401..639a1613c13 100644
--- a/src/include/pg_getopt.h
+++ b/src/include/pg_getopt.h
@@ -1,4 +1,13 @@
 /*
+ * Postgres files that use getopt(3) always include this file.
+ * We must cope with three different scenarios:
+ * 1. We're using the platform's getopt(), and we should just import the
+ *    appropriate declarations.
+ * 2. The platform lacks getopt(), and we must declare everything.
+ * 3. The platform has getopt(), but we're not using it because we don't
+ *    like its behavior.  The declarations we make here must be compatible
+ *    with both the platform's getopt() and our src/port/getopt.c.
+ *
  * Portions Copyright (c) 1987, 1993, 1994
  * The Regents of the University of California.  All rights reserved.
  *
@@ -39,6 +48,7 @@ extern int	optopt;
 extern int	optreset;
 #endif
 
+/* Provide getopt() declaration if the platform doesn't have it */
 #ifndef HAVE_GETOPT
 extern int	getopt(int nargc, char *const *nargv, const char *ostr);
 #endif
diff --git a/src/port/getopt.c b/src/port/getopt.c
index 10f4228d7c9..207c2836d35 100644
--- a/src/port/getopt.c
+++ b/src/port/getopt.c
@@ -1,7 +1,5 @@
 /* src/port/getopt.c */
 
-/* This is used by psql under Win32 */
-
 /*
  * Copyright (c) 1987, 1993, 1994
  *	The Regents of the University of California.  All rights reserved.
@@ -40,10 +38,11 @@ static char sccsid[] = "@(#)getopt.c	8.3 (Berkeley) 4/27/95";
 
 
 /*
- * On some versions of Solaris, opterr and friends are defined in core libc
- * rather than in a separate getopt module.  Define these variables only
- * if configure found they aren't there by default.  (We assume that testing
- * opterr is sufficient for all of these.)
+ * On OpenBSD and some versions of Solaris, opterr and friends are defined in
+ * core libc rather than in a separate getopt module.  Define these variables
+ * only if configure found they aren't there by default; otherwise, this
+ * module and its callers will just use libc's variables.  (We assume that
+ * testing opterr is sufficient for all of these.)
  */
 #ifndef HAVE_INT_OPTERR