From 0ea23439e30b2add8b59fc2da3d3c74cd8f6da2a Mon Sep 17 00:00:00 2001 From: schwarze <> Date: Wed, 27 May 2020 22:25:09 +0000 Subject: This patch fixes one bug and one instance of undesirable behaviour. The bug, present since 4.4BSD, was that a trailing dash in an option group, when the dash is not permitted as an option letter, resulted in the whole option group being returned as an argument, even though the previous option in the group was already parsed as an option: OPTS=abc ./getopt-test -a- -c arg ===>> OPT(a)ARG(-a-)ARG(-c)ARG(arg). Instead, treat the dash as an invalid option and continue parsing options: ===>> OPT(a)ERR(?-)OPT(c)ARG(arg). The undesirable behaviour was that allowing the dash as an option letter only allowed isolated dashes ("-") and trailing dashes in groups ("-a-"), but neither middle dashes in groups ("-a-b"), even though that already partially worked in 4.4BSD, nor leading dashes in groups ("--a"), even though that works on all other BSDs and on glibc. Also, while POSIX does not require that the dash can be used as an option letter at all, arguably, it encourages that letters either be fully supported or not supported at all. It is dubious whether supporting an option letter in some positions but not in others can be considered conforming. This patch makes OpenBSD behaviour identical to FreeBSD and NetBSD, improves compatibility with glibc (except that glibc does not support isolated "-"), improves compatibility with DragonFly (except that DragonFly is buggy when the dash option letter can take an optional argument but that argument is not present), improves compatibility with Illumos and Solaris 11 (except those do not support "-" and mishandle "--a"), and restores 4.4BSD behaviour for "-a-b". In no respect i'm aware of is compatibility with any other systems reduced. For the full rationale, see my mail to tech@ on 30 Mar 2020 14:26:41 +0200. Part of the problem was originally reported by an anonymous coward on tech@ on 12 Mar 2020 03:40:24 +0200, additional analysis was contributed by martijn@, and then the OP sent the final version of the patch i'm now committing on 17 Mar 2020 19:17:56 +0200. No licensing problem here because after the commit, the file does not contain a single word written by the OP. Also, the OP told me in private mail that he intends to publish the patch under the ISC license already contained in the file and that he wishes to be known by the pseudonym "0xef967c36". OK martijn@, and no objection when shown on tech@, but commit delayed to stay clear of the release. --- src/lib/libc/stdlib/getopt_long.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/lib/libc/stdlib/getopt_long.c b/src/lib/libc/stdlib/getopt_long.c index 48c26601ae..0de50457c2 100644 --- a/src/lib/libc/stdlib/getopt_long.c +++ b/src/lib/libc/stdlib/getopt_long.c @@ -1,4 +1,4 @@ -/* $OpenBSD: getopt_long.c,v 1.31 2020/03/30 12:52:58 martijn Exp $ */ +/* $OpenBSD: getopt_long.c,v 1.32 2020/05/27 22:25:09 schwarze Exp $ */ /* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ /* @@ -418,15 +418,7 @@ start: } if ((optchar = (int)*place++) == (int)':' || - (optchar == (int)'-' && *place != '\0') || (oli = strchr(options, optchar)) == NULL) { - /* - * If the user specified "-" and '-' isn't listed in - * options, return -1 (non-option) as per POSIX. - * Otherwise, it is an unknown option character (or ':'). - */ - if (optchar == (int)'-' && *place == '\0') - return (-1); if (!*place) ++optind; if (PRINT_ERROR) -- cgit v1.2.3-55-g6feb