about 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.c45
1 files changed, 38 insertions, 7 deletions
diff --git a/posix/getopt.c b/posix/getopt.c
index a5fb9921a7..ac6ebe0cc0 100644
--- a/posix/getopt.c
+++ b/posix/getopt.c
@@ -3,7 +3,7 @@
    "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
    before changing it!
 
-   Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 1996
+   Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97
    	Free Software Foundation, Inc.
 
    This file is part of the GNU C Library.  Its master source is NOT part of
@@ -249,12 +249,31 @@ extern int strlen (const char *);
 static int first_nonopt;
 static int last_nonopt;
 
+#ifdef _LIBC
 /* Bash 2.0 gives us an environment variable containing flags
    indicating ARGV elements that should not be considered arguments.  */
 
 static const char *nonoption_flags;
 static int nonoption_flags_len;
 
+static int original_argc;
+static char *const *original_argv;
+
+/* Make sure the environment variable bash 2.0 puts in the environment
+   is valid for the getopt call we must make sure that the ARGV passed
+   to getopt is that one passed to the process.  */
+static void store_args (int argc, char *const *argv) __attribute__ ((unused));
+static void
+store_args (int argc, char *const *argv)
+{
+  /* XXX This is no good solution.  We should rather copy the args so
+     that we can compare them later.  But we must not use malloc(3).  */
+  original_argc = argc;
+  original_argv = argv;
+}
+text_set_element (__libc_subinit, store_args);
+#endif
+
 /* Exchange two adjacent subsequences of ARGV.
    One subsequence is elements [first_nonopt,last_nonopt)
    which contains all the non-options that have been skipped so far.
@@ -327,10 +346,12 @@ exchange (argv)
 /* Initialize the internal data when the first call is made.  */
 
 #if defined (__STDC__) && __STDC__
-static const char *_getopt_initialize (const char *);
+static const char *_getopt_initialize (int, char *const *, const char *);
 #endif
 static const char *
-_getopt_initialize (optstring)
+_getopt_initialize (argc, argv, optstring)
+     int argc;
+     char *const *argv;
      const char *optstring;
 {
   /* Start processing options with ARGV-element 1 (since ARGV-element 0
@@ -360,7 +381,9 @@ _getopt_initialize (optstring)
   else
     ordering = PERMUTE;
 
-  if (posixly_correct == NULL)
+#ifdef _LIBC
+  if (posixly_correct == NULL
+      && argc == original_argc && argv == original_argv)
     {
       /* Bash 2.0 puts a special variable in the environment for each
 	 command it runs, specifying which ARGV elements are the results of
@@ -374,6 +397,9 @@ _getopt_initialize (optstring)
       else
 	nonoption_flags_len = strlen (nonoption_flags);
     }
+  else
+    nonoption_flags_len = 0;
+#endif
 
   return optstring;
 }
@@ -445,19 +471,24 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
 {
   optarg = NULL;
 
-  if (!__getopt_initialized)
+  if (!__getopt_initialized || optind == 0)
     {
-      optstring = _getopt_initialize (optstring);
+      optstring = _getopt_initialize (argc, argv, optstring);
       optind = 1;		/* Don't scan ARGV[0], the program name.  */
       __getopt_initialized = 1;
     }
 
   /* Test whether ARGV[optind] points to a non-option argument.
      Either it does not have option syntax, or there is an environment flag
-     from the shell indicating it is not an option.  */
+     from the shell indicating it is not an option.  The later information
+     is only used when the used in the GNU libc.  */
+#ifdef _LIBC
 #define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0'	      \
 		     || (optind < nonoption_flags_len			      \
 			 && nonoption_flags[optind] == '1'))
+#else
+#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0')
+#endif
 
   if (nextchar == NULL || *nextchar == '\0')
     {