getopt bugs

Corinna Vinschen
Tue Dec 1 09:42:00 GMT 2009

[Moving this discussion to cygwin-developers]

On Nov 30 19:14, Eric Blake wrote:
> Corinna Vinschen <corinna-cygwin <at>> writes:
> > I disagree.  Or rather, I agree with the BSD sources here.  The in-order
> > scanning of the arguments should only be supported if POSIXLY_CORRECT is
> > not set.  I don't see the special allowance for a leading dash in optstring
> > anywhere in the POSIX getopt man pages.
> POSIX explicitly states that:
> "All option characters allowed by Utility Syntax Guideline 3 are allowed in 
> optstring. The implementation may accept other characters as an extension."

Maybe I'm just dense, but I understood this differently.  The allowed
option characters per this guideline are letters and digits from the
ASCII range.  So the above sentence explicitely allows to define the set
of option characters with other characters not from this range.  From
the above sentence I never had assumed that the idea was to allow other
characters to extend functionality.  Go figure.

> "-" is not allowed by Utility Syntax Guideline 3.  Therefore, its use in 
> optstring is an extension.  And per glibc definition (which BSD later copied), 
> this particular extension means for in-order processing, regardless of 
> POSIXLY_CORRECT.  BSD is wrong for not copying glibc's extension correctly when 
> they followed glibc by implementing the same leading - extension.
> The same goes for "+" [...]
> The same also goes for "::" [...]
> [...]
> [1] See these posts and others in the same thread:
> in particular, the FreeBSD guy stated "I see -- would you have a test-case, 
> that detects this difference? Getopt_long was introduced into *BSD for the sake 
> of compatibility with GNU software -- any incompatibilities in semantics are a 
> bug, which should be fixed. It can not be fixed, however, if it is not 
> reported..."

Well, ok, you have a point there.  We have three choices:

- Fix the existing OpenBSD code in Cygwin to reevaluate POSIXLY_CORRECT
  when optind is set to 0.  It's an easy fix, it only requires to
  reorder the start of the getopt_internal function very slightly.

- Switch from the OpenBSD to the NetBSD sources.

- Keep everything as it is for Cygwin 1.7.1.

One choice we don't have:

- Switch from the OpenBSD to the FreeBSD sources.  The FreeBSD getopt
  sources still have the advertisement clause, unfortunately.

I tend to the first choice with a rather strong option to the third.

A patch for the first choice might look like this (untested):

	* libc/getopt.c (getopt_internal): Reevaluate POSIXLY_CORRECT
	if optind is set to 0.  Handle a leading '-' in options independently
	of posixly_correct.

Index: libc/getopt.c
RCS file: /cvs/src/src/winsup/cygwin/libc/getopt.c,v
retrieving revision 1.12
diff -u -p -r1.12 getopt.c
--- libc/getopt.c	13 Jan 2009 09:58:43 -0000	1.12
+++ libc/getopt.c	1 Dec 2009 09:41:06 -0000
@@ -307,12 +307,12 @@ getopt_internal(int nargc, char * const 
 	 * Disable GNU extensions if POSIXLY_CORRECT is set or options
 	 * string begins with a '+'.
-	if (posixly_correct == -1)
+	if (posixly_correct == -1 || optind == 0)
 		posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
-	if (posixly_correct || *options == '+')
-		flags &= ~FLAG_PERMUTE;
-	else if (*options == '-')
+	if (*options == '-')
 		flags |= FLAG_ALLARGS;
+	else if (posixly_correct || *options == '+')
+		flags &= ~FLAG_PERMUTE;
 	if (*options == '+' || *options == '-')
Care to test it?


Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Project Co-Leader          cygwin AT cygwin DOT com
Red Hat

More information about the Cygwin-developers mailing list