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>
