summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--regress/lib/libc/Makefile4
-rw-r--r--regress/lib/libc/getopt/Makefile10
-rw-r--r--regress/lib/libc/getopt/getopt-test.c59
-rw-r--r--regress/lib/libc/getopt/getopt.sh103
4 files changed, 174 insertions, 2 deletions
diff --git a/regress/lib/libc/Makefile b/regress/lib/libc/Makefile
index b1a55f1c1f2..3d0712f951e 100644
--- a/regress/lib/libc/Makefile
+++ b/regress/lib/libc/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.54 2020/01/13 15:35:57 bluhm Exp $
+# $OpenBSD: Makefile,v 1.55 2020/03/23 03:01:21 schwarze Exp $
SUBDIR+= _setjmp
SUBDIR+= alloca arc4random-fork atexit
@@ -7,7 +7,7 @@ SUBDIR+= cephes cxa-atexit
SUBDIR+= db dirname
SUBDIR+= env explicit_bzero
SUBDIR+= fmemopen fnmatch fpclassify fread
-SUBDIR+= gcvt getaddrinfo getcap getopt_long glob
+SUBDIR+= gcvt getaddrinfo getcap getopt getopt_long glob
SUBDIR+= hsearch
SUBDIR+= ieeefp ifnameindex
SUBDIR+= ldexp locale longjmp
diff --git a/regress/lib/libc/getopt/Makefile b/regress/lib/libc/getopt/Makefile
new file mode 100644
index 00000000000..bdafc965fe5
--- /dev/null
+++ b/regress/lib/libc/getopt/Makefile
@@ -0,0 +1,10 @@
+# $OpenBSD: Makefile,v 1.1 2020/03/23 03:01:21 schwarze Exp $
+
+REGRESS_TARGETS = getopt
+PROG = getopt-test
+MAN =
+
+getopt: ${PROG}
+ sh ${.CURDIR}/getopt.sh
+
+.include <bsd.regress.mk>
diff --git a/regress/lib/libc/getopt/getopt-test.c b/regress/lib/libc/getopt/getopt-test.c
new file mode 100644
index 00000000000..40901dcfcfc
--- /dev/null
+++ b/regress/lib/libc/getopt/getopt-test.c
@@ -0,0 +1,59 @@
+/* $OpenBSD: getopt-test.c,v 1.1 2020/03/23 03:01:21 schwarze Exp $ */
+/*
+ * Copyright (c) 2020 Ingo Schwarze <schwarze@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+/*
+ * Process command line options and arguments according to the
+ * optstring in the environment variable OPTS. Write:
+ * OPT(c) for an option "-c" without an option argument
+ * OPT(carg) for an option "-c" with an option argument "arg"
+ * ARG(arg) for a non-option argument "arg"
+ * NONE(arg) for a non-option argument "arg" processed with OPTS =~ ^-
+ * ERR(?c) for an invalid option "-c", or one lacking an argument
+ * ERR(:c) for an option "-c" lacking an argument while OPTS =~ ^:
+ */
+int
+main(int argc, char *argv[])
+{
+ char *optstring;
+ int ch;
+
+ if ((optstring = getenv("OPTS")) == NULL)
+ optstring = "";
+
+ opterr = 0;
+ while ((ch = getopt(argc, argv, optstring)) != -1) {
+ switch (ch) {
+ case '\1':
+ printf("NONE(%s)", optarg);
+ break;
+ case ':':
+ case '?':
+ printf("ERR(%c%c)", ch, optopt);
+ break;
+ default:
+ printf("OPT(%c%s)", ch, optarg == NULL ? "" : optarg);
+ break;
+ }
+ }
+ while (optind < argc)
+ printf("ARG(%s)", argv[optind++]);
+ putchar('\n');
+ return 0;
+}
diff --git a/regress/lib/libc/getopt/getopt.sh b/regress/lib/libc/getopt/getopt.sh
new file mode 100644
index 00000000000..97668fc262c
--- /dev/null
+++ b/regress/lib/libc/getopt/getopt.sh
@@ -0,0 +1,103 @@
+#!/bin/sh
+#
+# $OpenBSD: getopt.sh,v 1.1 2020/03/23 03:01:21 schwarze Exp $
+#
+# Copyright (c) 2020 Ingo Schwarze <schwarze@openbsd.org>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+# Run ./getopt-test once.
+# Function arguments:
+# 1. optstring argument for getopt(3)
+# 2. space-separated command line arguments
+# 3. expected output from ./getopt-test
+test1_getopt()
+{
+ result=$(OPTS=$1 ./getopt-test $2)
+ test "$result" == "$3" && return
+ echo "OPTS=$1 ./getopt-test $2"
+ echo "expected: $3"
+ echo "result: $result"
+ irc=1
+}
+
+# Test both without and with the optstring modifier "+",
+# verifying that it makes no difference.
+test2_getopt()
+{
+ test1_getopt "$1" "$2" "$3"
+ test1_getopt "+$1" "$2" "$3"
+}
+
+# Also test with the GNU "-" optstring modifier,
+# veryfying that it only changes ARG() to NONE().
+# This test function is inadequate in two situations:
+# a) options follow non-option arguments that terminate option processing
+# b) or any arguments follow explicit "--".
+# In these cases, use test2_getopt() plus a separate test1_getopt(-...).
+test3_getopt()
+{
+ test2_getopt "$1" "$2" "$3"
+ test1_getopt "-$1" "$2" $(echo $3 | sed s/ARG/NONE/g)
+}
+
+irc=0
+
+# isolated options without arguments
+test3_getopt ax '-a -x arg' 'OPT(a)OPT(x)ARG(arg)'
+test3_getopt ax '-a -y arg' 'OPT(a)ERR(?y)ARG(arg)'
+test1_getopt :ax '-a -y arg' 'OPT(a)ERR(?y)ARG(arg)'
+
+# grouped options without arguments
+test3_getopt ax '-ax arg' 'OPT(a)OPT(x)ARG(arg)'
+test3_getopt ax '-ay arg' 'OPT(a)ERR(?y)ARG(arg)'
+test1_getopt :ax '-ay arg' 'OPT(a)ERR(?y)ARG(arg)'
+
+# non-option arguments terminating option processing
+test2_getopt ax '-a arg -x' 'OPT(a)ARG(arg)ARG(-x)'
+test1_getopt -ax '-a arg1 -x arg2' 'OPT(a)NONE(arg1)OPT(x)NONE(arg2)'
+test2_getopt ax '-a -- -x' 'OPT(a)ARG(-x)'
+test1_getopt -ax '-a -- -x' 'OPT(a)ARG(-x)'
+test2_getopt ax '-a - -x' 'OPT(a)ARG(-)ARG(-x)'
+test1_getopt -ax '-a - -x arg' 'OPT(a)NONE(-)OPT(x)NONE(arg)'
+
+# the '-' option only works when isolated
+test3_getopt a- '-a - -x arg' 'OPT(a)OPT(-)ERR(?x)ARG(arg)'
+test1_getopt :a- '-a - -x arg' 'OPT(a)OPT(-)ERR(?x)ARG(arg)'
+test1_getopt --a '-a - -x arg' 'OPT(a)OPT(-)ERR(?x)NONE(arg)'
+test3_getopt ax '-a-x arg' 'OPT(a)ERR(?-)OPT(x)ARG(arg)'
+test3_getopt a-x '-a-x arg' 'OPT(a)ERR(?-)OPT(x)ARG(arg)'
+
+# the ':' option never works
+test1_getopt ::a '-:a arg' 'ERR(?:)OPT(a)ARG(arg)'
+test1_getopt :::a '-: arg -a' 'ERR(?:)ARG(arg)ARG(-a)'
+
+# isolated options with arguments
+test3_getopt o: '-o' 'ERR(?o)'
+test1_getopt :o: '-o' 'ERR(:o)'
+test3_getopt o:x '-o arg -x arg' 'OPT(oarg)OPT(x)ARG(arg)'
+test3_getopt o::x '-oarg -x arg' 'OPT(oarg)OPT(x)ARG(arg)'
+test2_getopt o::x '-o arg -x' 'OPT(o)ARG(arg)ARG(-x)'
+test1_getopt -o::x '-o arg1 -x arg2' 'OPT(o)NONE(arg1)OPT(x)NONE(arg2)'
+test3_getopt o:x '-o -- -x arg' 'OPT(o--)OPT(x)ARG(arg)'
+
+# grouped options with arguments
+test3_getopt ao: '-ao' 'OPT(a)ERR(?o)'
+test1_getopt :ao: '-ao' 'OPT(a)ERR(:o)'
+test3_getopt ao:x '-ao arg -x arg' 'OPT(a)OPT(oarg)OPT(x)ARG(arg)'
+test3_getopt ao::x '-aoarg -x arg' 'OPT(a)OPT(oarg)OPT(x)ARG(arg)'
+test2_getopt ao::x '-ao arg -x' 'OPT(a)OPT(o)ARG(arg)ARG(-x)'
+test1_getopt -ao::x '-ao arg1 -x arg2' 'OPT(a)OPT(o)NONE(arg1)OPT(x)NONE(arg2)'
+test3_getopt ao:x '-ao -- -x arg' 'OPT(a)OPT(o--)OPT(x)ARG(arg)'
+
+exit $irc