Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 27 Nov 2000 17:52:17 -0800 (PST)
From:      anand@blandings.com
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   misc/23148: getopt(3) works non-intuitively?
Message-ID:  <200011280152.eAS1qHo59965@wooster.jumpdata.com>

next in thread | raw e-mail | index | archive | help

>Number:         23148
>Category:       misc
>Synopsis:       getopt(3) works non-intuitively?
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Nov 27 18:00:05 PST 2000
>Closed-Date:
>Last-Modified:
>Originator:     Anand Ranganathan
>Release:        FreeBSD 4.2-RELEASE i386
>Organization:
>Environment:

	FreeBSD 4.2-RELEASE i386

>Description:

	The getopt(3) man page says:
The interpretation of op-
tions in the argument list may be cancelled by the option `--' (double
dash) which causes getopt() to signal the end of argument processing and
return -1.

        And fair enough, the getopt function seems to conform to this
description. However, this includes the option '--' not occuring by itself
(e.g., if the program were passed the argument --foo in the GNU style by
mistake), or if -- were inferred by an option of the form -abcd-

Both of these occurences are treated by the getopt function to be the
option --, whereas it seems intuitively to be an occurence of the option
'-' and not an occurence of --.


>How-To-Repeat:

Consider the following program:

#include <unistd.h>

int
main(int argc, char *argv[])
{
        char ch;
        while ((ch = getopt(argc, argv, "abc")) != -1) {
                switch (ch) {
                case 'a':
                        printf("-a\n");
                        break;
                case 'b':
                        printf("-b\n");
                        break;
                case 'c':
                        printf("-c\n");
                        break;
                default:
                        printf("huh\n");
                        break;
                }
        }
        return 0;
}

If you were to compile and run this program:
229 wooster:/usr/tmp> ./a.out -f
a.out: illegal option -- f
huh
230 wooster:/usr/tmp> ./a.out -af
-a
a.out: illegal option -- f
huh
231 wooster:/usr/tmp> ./a.out -a-f
-a
232 wooster:/usr/tmp> ./a.out --foo
233 wooster:/usr/tmp> 

This gets weirder still when you use a standard program called ls with
gnu-style arguments. e.g.,

239 wooster:tmp/foo> touch bar baz
240 wooster:tmp/foo> ls
bar     baz
241 wooster:tmp/foo> ls --color
bar     baz
242 wooster:tmp/foo> ls --foobarbaz
bar     baz
243 wooster:tmp/foo> 

Essentially, getopt considers --color to be an occurence of --, but
swallows the --color option.

With the fix that I'm supplying below, the same program given above works
like so:

245 wooster:/usr/tmp> ./a.out -f
a.out: illegal option -- f
huh
246 wooster:/usr/tmp> ./a.out -af
-a
a.out: illegal option -- f
huh
247 wooster:/usr/tmp> ./a.out -a-f
-a
a.out: illegal option -- -
huh
a.out: illegal option -- f
huh
248 wooster:/usr/tmp> ./a.out --foo
a.out: illegal option -- -
huh
a.out: illegal option -- f
huh
a.out: illegal option -- o
huh
a.out: illegal option -- o
huh
249 wooster:/usr/tmp> ./a.out -- foo
250 wooster:/usr/tmp> 

To me this seems more intuitive.

>Fix:

This patch to /usr/src/lib/libc/stdlib/getopt.c changes the way getopt
works to the description that I supplied:

--- getopt.c.orig	Mon Nov 27 15:27:57 2000
+++ getopt.c	Mon Nov 27 16:29:31 2000
@@ -73,7 +73,7 @@
 			place = EMSG;
 			return (-1);
 		}
-		if (place[1] && *++place == '-') {	/* found "--" */
+		if (place[1] && *++place == '-' && !place[1]) {	/* found "--" */
 			++optind;
 			place = EMSG;
 			return (-1);
@@ -81,12 +81,6 @@
 	}					/* option letter okay? */
 	if ((optopt = (int)*place++) == (int)':' ||
 	    !(oli = strchr(ostr, optopt))) {
-		/*
-		 * if the user didn't specify '-' as an option,
-		 * assume it means -1.
-		 */
-		if (optopt == (int)'-')
-			return (-1);
 		if (!*place)
 			++optind;
 		if (opterr && *ostr != ':' && optopt != BADCH)



>Release-Note:
>Audit-Trail:
>Unformatted:
 Anand Ranganathan


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200011280152.eAS1qHo59965>