about summary refs log tree commit diff
path: root/posix/getopt.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>1997-01-28 03:59:29 +0000
committerUlrich Drepper <drepper@redhat.com>1997-01-28 03:59:29 +0000
commit831372e7c1bb907f9f2c3d78909b15717b8ac095 (patch)
treecaaa80503af0be017a6a88df30dcf295cdc2e63c /posix/getopt.c
parentbdf289b22254f7eb10989ccd933cfd9ee7b8da92 (diff)
downloadglibc-831372e7c1bb907f9f2c3d78909b15717b8ac095.tar.gz
glibc-831372e7c1bb907f9f2c3d78909b15717b8ac095.tar.xz
glibc-831372e7c1bb907f9f2c3d78909b15717b8ac095.zip
update from main archive 970127 cvs/libc-970128
1997-01-28 04:23  Ulrich Drepper  <drepper@cygnus.com>
	* version.h (VERSION): Bump to 2.0.1.
	* posix/getopt.c: Handle another problem introduced by the
	nonoption_flags array.  We must be able to work with reordered
	argv arrays.  Reported by Andreas Schwab.
1997-01-28 02:38  Ulrich Drepper  <drepper@cygnus.com>
	* sysdeps/unix/sysv/linux/i386/clone.S: Correct handling of new
1997-01-27 17:34  Thorsten Kukuk <kukuk@weber.uni-paderborn.de>
	* nis/rpcsvc/yp_prot.h: Correct definitions and types in file so
	that it works with yp.h.
1997-01-27 13:28  Ulrich Drepper  <drepper@cygnus.com>
	* malloc/malloc.h (__malloc_initialized) [_LIBC]: Define as
	__libc_malloc_initialized so that this variable is not shared with
	other users of GNU malloc.
	Suggested by Martin von Loewis <martin@mira.isdn.cs.tu-berlin.de>.
	* mcheck.h: Correct typo.  Use malloc/ instead of new-malloc/.
	* sysdeps/i386/Makefile (CFLAGS-dl-load.c, CFLAGS-dl-reloc.c): New
	variables to prevent warnings.
	* sysdeps/i386/dl-machine.h (fixup): Add prototype and declare
	using attribute regparm.
	(ELF_MACHINE_RUNTIME_TRAMPOLINE): Rewrite so that no register
	is changed by the resolver code.
1997-01-14 14:20  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
	* malloc/malloc.c (weak_variable): Define.
	(__malloc_initialize_hook, __free_hook, __malloc_hook, __realloc_hook,
	__memalign_hook): Make them weak definitions.
1997-01-26 11:35  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
	* sysdeps/unix/sysv/linux/getdents.c: Don't write beyond buffer
	limits, correctly take structure padding into account, use correct
	offset when resetting the stream, change heuristic to assume an
	average name length of 14 characters.
1997-01-25 18:06  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
	* sysdeps/unix/sysv/linux/alpha/termbits.h: Protect against multiple
	inclusion.
See ChangeLog.6 for earlier changes.
Diffstat (limited to 'posix/getopt.c')
-rw-r--r--posix/getopt.c71
1 files changed, 63 insertions, 8 deletions
diff --git a/posix/getopt.c b/posix/getopt.c
index eac576b83e..78021bb977 100644
--- a/posix/getopt.c
+++ b/posix/getopt.c
@@ -253,7 +253,8 @@ static int last_nonopt;
 /* 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 char *nonoption_flags;
+static int nonoption_flags_max_len;
 static int nonoption_flags_len;
 
 static int original_argc;
@@ -272,6 +273,16 @@ store_args (int argc, char *const *argv)
   original_argv = argv;
 }
 text_set_element (__libc_subinit, store_args);
+
+# define SWAP_FLAGS(ch1, ch2) \
+  if (nonoption_flags_len > 0)						      \
+    {									      \
+      char __tmp = nonoption_flags[ch1];				      \
+      nonoption_flags[ch1] = nonoption_flags[ch2];			      \
+      nonoption_flags[ch2] = __tmp;					      \
+    }
+#else
+# define SWAP_FLAGS(ch1, ch2)
 #endif
 
 /* Exchange two adjacent subsequences of ARGV.
@@ -301,6 +312,28 @@ exchange (argv)
      It leaves the longer segment in the right place overall,
      but it consists of two parts that need to be swapped next.  */
 
+#ifdef _LIBC
+  /* First make sure the handling of the `nonoption_flags' string can
+     work normally.  Our top argument must be in the range of the
+     string.  */
+  if (nonoption_flags_len != 0 && top >= nonoption_flags_max_len)
+    {
+      /* We must extend the array.  The user plays games with us and
+	 presents new arguments.  */
+      char *new_str = malloc (top + 1);
+      if (new_str == NULL)
+	nonoption_flags_len = nonoption_flags_max_len = 0;
+      else
+	{
+	  memcpy (new_str, nonoption_flags, nonoption_flags_max_len);
+	  memset (&new_str[nonoption_flags_max_len], '\0',
+		  top + 1 - nonoption_flags_max_len);
+	  nonoption_flags_max_len = top + 1;
+	  nonoption_flags = new_str;
+	}
+    }
+#endif
+
   while (top > middle && middle > bottom)
     {
       if (top - middle > middle - bottom)
@@ -315,6 +348,7 @@ exchange (argv)
 	      tem = argv[bottom + i];
 	      argv[bottom + i] = argv[top - (middle - bottom) + i];
 	      argv[top - (middle - bottom) + i] = tem;
+	      SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
 	    }
 	  /* Exclude the moved bottom segment from further swapping.  */
 	  top -= len;
@@ -331,6 +365,7 @@ exchange (argv)
 	      tem = argv[bottom + i];
 	      argv[bottom + i] = argv[middle + i];
 	      argv[middle + i] = tem;
+	      SWAP_FLAGS (bottom + i, middle + i);
 	    }
 	  /* Exclude the moved top segment from further swapping.  */
 	  bottom += len;
@@ -389,13 +424,33 @@ _getopt_initialize (argc, argv, optstring)
 	 command it runs, specifying which ARGV elements are the results of
 	 file name wildcard expansion and therefore should not be
 	 considered as options.  */
-      char var[100];
-      sprintf (var, "_%d_GNU_nonoption_argv_flags_", getpid ());
-      nonoption_flags = getenv (var);
-      if (nonoption_flags == NULL)
-	nonoption_flags_len = 0;
-      else
-	nonoption_flags_len = strlen (nonoption_flags);
+
+      if (nonoption_flags_max_len == 0)
+	{
+	  char var[100];
+	  const char *orig_str;
+	  sprintf (var, "_%d_GNU_nonoption_argv_flags_", getpid ());
+	  orig_str = getenv (var);
+	  if (orig_str == NULL || orig_str[0] == '\0')
+	    nonoption_flags_max_len = -1;
+	  else
+	    {
+	      int len = nonoption_flags_max_len = strlen (orig_str);
+	      if (nonoption_flags_max_len < argc)
+		nonoption_flags_max_len = argc;
+	      nonoption_flags = (char *) malloc (nonoption_flags_max_len);
+	      if (nonoption_flags == NULL)
+		nonoption_flags_max_len = -1;
+	      else
+		{
+		  memcpy (nonoption_flags, orig_str, len);
+		  memset (&nonoption_flags[len], '\0',
+			  nonoption_flags_max_len - len);
+		}
+	    }
+	}
+
+      nonoption_flags_len = nonoption_flags_max_len;
     }
   else
     nonoption_flags_len = 0;