From 61b53695fbbedb7fa9d394e71bf2affdc494e6b0 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Thu, 16 Dec 2010 16:22:05 -0500
Subject: [PATCH] Remove optreset from src/port/ implementations of getopt and
 getopt_long.

We don't actually need optreset, because we can easily fix the code to
ensure that it's cleanly restartable after having completed a scan over the
argv array; which is the only case we need to restart in.  Getting rid of
it avoids a class of interactions with the system libraries and allows
reversion of my change of yesterday in postmaster.c and postgres.c.

Back-patch to 8.4.  Before that the getopt code was a bit different anyway.
---
 src/backend/postmaster/postmaster.c |  5 ++---
 src/backend/tcop/postgres.c         |  5 ++---
 src/include/getopt_long.h           |  1 -
 src/port/getopt.c                   | 20 +++++++++++---------
 src/port/getopt_long.c              | 20 +++++++++++---------
 5 files changed, 26 insertions(+), 25 deletions(-)

diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 50d064407b2..2b12b1704cc 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -313,8 +313,7 @@ extern char *optarg;
 extern int	optind,
 			opterr;
 
-/* If not HAVE_GETOPT, we are using src/port/getopt.c, which has optreset */
-#if defined(HAVE_INT_OPTRESET) || !defined(HAVE_GETOPT)
+#ifdef HAVE_INT_OPTRESET
 extern int	optreset;			/* might not be declared by system headers */
 #endif
 
@@ -752,7 +751,7 @@ PostmasterMain(int argc, char *argv[])
 	 * getopt(3) library so that it will work correctly in subprocesses.
 	 */
 	optind = 1;
-#if defined(HAVE_INT_OPTRESET) || !defined(HAVE_GETOPT)
+#ifdef HAVE_INT_OPTRESET
 	optreset = 1;				/* some systems need this too */
 #endif
 
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 7657458693f..ff2e9bd0aaa 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -78,8 +78,7 @@
 extern char *optarg;
 extern int	optind;
 
-/* If not HAVE_GETOPT, we are using src/port/getopt.c, which has optreset */
-#if defined(HAVE_INT_OPTRESET) || !defined(HAVE_GETOPT)
+#ifdef HAVE_INT_OPTRESET
 extern int	optreset;			/* might not be declared by system headers */
 #endif
 
@@ -3443,7 +3442,7 @@ process_postgres_switches(int argc, char *argv[], GucContext ctx)
 	 * or when this function is called a second time with another array.
 	 */
 	optind = 1;
-#if defined(HAVE_INT_OPTRESET) || !defined(HAVE_GETOPT)
+#ifdef HAVE_INT_OPTRESET
 	optreset = 1;				/* some systems need this too */
 #endif
 
diff --git a/src/include/getopt_long.h b/src/include/getopt_long.h
index 3b05fadb388..0589ae67ca1 100644
--- a/src/include/getopt_long.h
+++ b/src/include/getopt_long.h
@@ -18,7 +18,6 @@ extern int	opterr;
 extern int	optind;
 extern int	optopt;
 extern char *optarg;
-extern int	optreset;
 
 #ifndef HAVE_STRUCT_OPTION
 
diff --git a/src/port/getopt.c b/src/port/getopt.c
index 90c882c1fd8..aacfbc3e540 100644
--- a/src/port/getopt.c
+++ b/src/port/getopt.c
@@ -41,7 +41,7 @@ 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 except optreset.)
+ * opterr is sufficient for all of these.)
  */
 #ifndef HAVE_INT_OPTERR
 
@@ -57,12 +57,6 @@ extern int	optopt;
 extern char *optarg;
 #endif
 
-#ifndef HAVE_INT_OPTRESET
-int			optreset;			/* reset getopt */
-#else
-extern int	optreset;
-#endif
-
 #define BADCH	(int)'?'
 #define BADARG	(int)':'
 #define EMSG	""
@@ -70,6 +64,12 @@ extern int	optreset;
 /*
  * getopt
  *	Parse argc/argv argument vector.
+ *
+ * This implementation does not use optreset.  Instead, we guarantee that
+ * it can be restarted on a new argv array after a previous call returned -1,
+ * if the caller resets optind to 1 before the first call of the new series.
+ * (Internally, this means we must be sure to reset "place" to EMSG before
+ * returning -1.)
  */
 int
 getopt(nargc, nargv, ostr)
@@ -80,9 +80,8 @@ const char *ostr;
 	static char *place = EMSG;	/* option letter processing */
 	char	   *oli;			/* option letter list index */
 
-	if (optreset || !*place)
+	if (!*place)
 	{							/* update scanning pointer */
-		optreset = 0;
 		if (optind >= nargc || *(place = nargv[optind]) != '-')
 		{
 			place = EMSG;
@@ -102,7 +101,10 @@ const char *ostr;
 		 * if the user didn't specify '-' as an option, assume it means -1.
 		 */
 		if (optopt == (int) '-')
+		{
+			place = EMSG;
 			return -1;
+		}
 		if (!*place)
 			++optind;
 		if (opterr && *ostr != ':')
diff --git a/src/port/getopt_long.c b/src/port/getopt_long.c
index 418cce7c8ba..d624216ad03 100644
--- a/src/port/getopt_long.c
+++ b/src/port/getopt_long.c
@@ -38,17 +38,21 @@
 
 #include "getopt_long.h"
 
-#ifndef HAVE_INT_OPTRESET
-int			optreset;
-
-/* else the "extern" was provided by getopt_long.h */
-#endif
-
 #define BADCH	'?'
 #define BADARG	':'
 #define EMSG	""
 
 
+/*
+ * getopt_long
+ *	Parse argc/argv argument vector, with long options.
+ *
+ * This implementation does not use optreset.  Instead, we guarantee that
+ * it can be restarted on a new argv array after a previous call returned -1,
+ * if the caller resets optind to 1 before the first call of the new series.
+ * (Internally, this means we must be sure to reset "place" to EMSG before
+ * returning -1.)
+ */
 int
 getopt_long(int argc, char *const argv[],
 			const char *optstring,
@@ -57,10 +61,8 @@ getopt_long(int argc, char *const argv[],
 	static char *place = EMSG;	/* option letter processing */
 	char	   *oli;			/* option letter list index */
 
-	if (optreset || !*place)
+	if (!*place)
 	{							/* update scanning pointer */
-		optreset = 0;
-
 		if (optind >= argc)
 		{
 			place = EMSG;
-- 
GitLab