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>