summary refs log tree commit diff
path: root/posix/getopt.c
diff options
context:
space:
mode:
Diffstat (limited to 'posix/getopt.c')
-rw-r--r--posix/getopt.c37
1 files changed, 31 insertions, 6 deletions
diff --git a/posix/getopt.c b/posix/getopt.c
index 01adee0fe5..a5fb9921a7 100644
--- a/posix/getopt.c
+++ b/posix/getopt.c
@@ -52,7 +52,15 @@
    program understand `configure --with-gnu-libc' and omit the object files,
    it is simpler to just do this in the source for each such file.  */
 
-#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
+#define GETOPT_INTERFACE_VERSION 1
+#if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2
+#include <gnu-versions.h>
+#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
+#define ELIDE_CODE
+#endif
+#endif
+
+#ifndef ELIDE_CODE
 
 
 /* This needs to come after some library #include
@@ -124,8 +132,14 @@ char *optarg = NULL;
    Otherwise, `optind' communicates from one call to the next
    how much of ARGV has been scanned so far.  */
 
-/* XXX 1003.2 says this must be 1 before any call.  */
-int optind = 0;
+/* 1003.2 says this must be 1 before any call.  */
+int optind = 1;
+
+/* Formerly, initialization of getopt depended on optind==0, which
+   causes problems with re-calling getopt as programs generally don't
+   know that. */
+
+int __getopt_initialized = 0;
 
 /* The next char to be scanned in the option-element
    in which the last option character we returned was found.
@@ -431,10 +445,11 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
 {
   optarg = NULL;
 
-  if (optind == 0)
+  if (!__getopt_initialized)
     {
       optstring = _getopt_initialize (optstring);
       optind = 1;		/* Don't scan ARGV[0], the program name.  */
+      __getopt_initialized = 1;
     }
 
   /* Test whether ARGV[optind] points to a non-option argument.
@@ -500,6 +515,11 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
 	     that we previously skipped, so the caller will digest them.  */
 	  if (first_nonopt != last_nonopt)
 	    optind = first_nonopt;
+
+	  /* Before we can be provide the next result we must be
+	     reinitialized.  */
+	  __getopt_initialized = 0;
+
 	  return EOF;
 	}
 
@@ -509,7 +529,12 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
       if (NONOPTION_P)
 	{
 	  if (ordering == REQUIRE_ORDER)
-	    return EOF;
+	    {
+	      /* Before we can be provide the next result we must be
+		 reinitialized.  */
+	      __getopt_initialized = 0;
+	      return EOF;
+	    }
 	  optarg = argv[optind++];
 	  return 1;
 	}
@@ -880,7 +905,7 @@ getopt (argc, argv, optstring)
 			   0);
 }
 
-#endif	/* _LIBC or not __GNU_LIBRARY__.  */
+#endif	/* Not ELIDE_CODE.  */
 
 #ifdef TEST