summaryrefslogtreecommitdiffstats
path: root/tools/regression/lib/libc
diff options
context:
space:
mode:
Diffstat (limited to 'tools/regression/lib/libc')
-rw-r--r--tools/regression/lib/libc/gen/Makefile11
-rw-r--r--tools/regression/lib/libc/gen/test-fpclassify.c75
-rw-r--r--tools/regression/lib/libc/gen/test-wordexp.c174
-rw-r--r--tools/regression/lib/libc/locale/Makefile25
-rw-r--r--tools/regression/lib/libc/locale/test-btowc.c72
-rw-r--r--tools/regression/lib/libc/locale/test-btowc.t10
-rw-r--r--tools/regression/lib/libc/locale/test-iswctype.c101
-rw-r--r--tools/regression/lib/libc/locale/test-iswctype.t10
-rw-r--r--tools/regression/lib/libc/locale/test-mblen.c114
-rw-r--r--tools/regression/lib/libc/locale/test-mblen.t10
-rw-r--r--tools/regression/lib/libc/locale/test-mbrlen.c129
-rw-r--r--tools/regression/lib/libc/locale/test-mbrlen.t10
-rw-r--r--tools/regression/lib/libc/locale/test-mbrtowc.c163
-rw-r--r--tools/regression/lib/libc/locale/test-mbrtowc.t10
-rw-r--r--tools/regression/lib/libc/locale/test-mbsnrtowcs.c194
-rw-r--r--tools/regression/lib/libc/locale/test-mbsnrtowcs.t10
-rw-r--r--tools/regression/lib/libc/locale/test-mbsrtowcs.c150
-rw-r--r--tools/regression/lib/libc/locale/test-mbsrtowcs.t10
-rw-r--r--tools/regression/lib/libc/locale/test-mbstowcs.c112
-rw-r--r--tools/regression/lib/libc/locale/test-mbstowcs.t10
-rw-r--r--tools/regression/lib/libc/locale/test-mbtowc.c124
-rw-r--r--tools/regression/lib/libc/locale/test-mbtowc.t10
-rw-r--r--tools/regression/lib/libc/locale/test-towctrans.c91
-rw-r--r--tools/regression/lib/libc/locale/test-towctrans.t10
-rw-r--r--tools/regression/lib/libc/locale/test-wcrtomb.c134
-rw-r--r--tools/regression/lib/libc/locale/test-wcrtomb.t10
-rw-r--r--tools/regression/lib/libc/locale/test-wcsnrtombs.c194
-rw-r--r--tools/regression/lib/libc/locale/test-wcsnrtombs.t10
-rw-r--r--tools/regression/lib/libc/locale/test-wcsrtombs.c155
-rw-r--r--tools/regression/lib/libc/locale/test-wcsrtombs.t10
-rw-r--r--tools/regression/lib/libc/locale/test-wcstombs.c129
-rw-r--r--tools/regression/lib/libc/locale/test-wcstombs.t10
-rw-r--r--tools/regression/lib/libc/locale/test-wctomb.c112
-rw-r--r--tools/regression/lib/libc/locale/test-wctomb.t10
-rw-r--r--tools/regression/lib/libc/net/Makefile12
-rw-r--r--tools/regression/lib/libc/net/test-ether.c235
-rw-r--r--tools/regression/lib/libc/net/test-ether.t10
-rw-r--r--tools/regression/lib/libc/net/test-eui64.h55
-rw-r--r--tools/regression/lib/libc/net/test-eui64_aton.c73
-rw-r--r--tools/regression/lib/libc/net/test-eui64_aton.t10
-rw-r--r--tools/regression/lib/libc/net/test-eui64_line.c81
-rw-r--r--tools/regression/lib/libc/net/test-eui64_line.t10
-rw-r--r--tools/regression/lib/libc/net/test-eui64_ntoa.c54
-rw-r--r--tools/regression/lib/libc/net/test-eui64_ntoa.t10
-rw-r--r--tools/regression/lib/libc/nss/Makefile12
-rw-r--r--tools/regression/lib/libc/nss/README203
-rw-r--r--tools/regression/lib/libc/nss/mach94
-rw-r--r--tools/regression/lib/libc/nss/test-getaddr.c538
-rw-r--r--tools/regression/lib/libc/nss/test-getaddr.t33
-rw-r--r--tools/regression/lib/libc/nss/test-getgr.c534
-rw-r--r--tools/regression/lib/libc/nss/test-getgr.t29
-rw-r--r--tools/regression/lib/libc/nss/test-gethostby.c1105
-rw-r--r--tools/regression/lib/libc/nss/test-gethostby.t113
-rw-r--r--tools/regression/lib/libc/nss/test-getproto.c536
-rw-r--r--tools/regression/lib/libc/nss/test-getproto.t29
-rw-r--r--tools/regression/lib/libc/nss/test-getpw.c489
-rw-r--r--tools/regression/lib/libc/nss/test-getpw.t29
-rw-r--r--tools/regression/lib/libc/nss/test-getrpc.c535
-rw-r--r--tools/regression/lib/libc/nss/test-getrpc.t29
-rw-r--r--tools/regression/lib/libc/nss/test-getserv.c551
-rw-r--r--tools/regression/lib/libc/nss/test-getserv.t29
-rw-r--r--tools/regression/lib/libc/nss/test-getusershell.c235
-rw-r--r--tools/regression/lib/libc/nss/test-getusershell.t22
-rw-r--r--tools/regression/lib/libc/nss/testutil.h334
-rw-r--r--tools/regression/lib/libc/regex/Makefile11
-rw-r--r--tools/regression/lib/libc/resolv/Makefile15
-rw-r--r--tools/regression/lib/libc/resolv/mach92
-rw-r--r--tools/regression/lib/libc/resolv/resolv.c330
-rw-r--r--tools/regression/lib/libc/resolv/resolv.t24
-rw-r--r--tools/regression/lib/libc/stdio/Makefile12
-rw-r--r--tools/regression/lib/libc/stdio/test-perror.c107
-rw-r--r--tools/regression/lib/libc/stdio/test-perror.t10
-rw-r--r--tools/regression/lib/libc/stdio/test-printfloat.c341
-rw-r--r--tools/regression/lib/libc/stdio/test-printfloat.t10
-rw-r--r--tools/regression/lib/libc/stdio/test-scanfloat.c293
-rw-r--r--tools/regression/lib/libc/stdio/test-scanfloat.t10
-rw-r--r--tools/regression/lib/libc/stdlib/Makefile13
-rw-r--r--tools/regression/lib/libc/stdlib/test-heapsort.c66
-rw-r--r--tools/regression/lib/libc/stdlib/test-heapsort.t10
-rw-r--r--tools/regression/lib/libc/stdlib/test-mergesort.c66
-rw-r--r--tools/regression/lib/libc/stdlib/test-mergesort.t10
-rw-r--r--tools/regression/lib/libc/stdlib/test-qsort.c66
-rw-r--r--tools/regression/lib/libc/stdlib/test-qsort.t10
-rw-r--r--tools/regression/lib/libc/stdlib/test-sort.h269
-rw-r--r--tools/regression/lib/libc/string/Makefile15
-rw-r--r--tools/regression/lib/libc/string/test-strerror.c130
-rw-r--r--tools/regression/lib/libc/string/test-strerror.t10
87 files changed, 10358 insertions, 0 deletions
diff --git a/tools/regression/lib/libc/gen/Makefile b/tools/regression/lib/libc/gen/Makefile
new file mode 100644
index 0000000..140b789
--- /dev/null
+++ b/tools/regression/lib/libc/gen/Makefile
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+TESTS= test-fpclassify test-wordexp
+
+.PHONY: tests
+tests: ${TESTS}
+ for p in ${TESTS}; do ${.OBJDIR}/$$p; done
+
+.PHONY: clean
+clean:
+ -rm -f ${TESTS}
diff --git a/tools/regression/lib/libc/gen/test-fpclassify.c b/tools/regression/lib/libc/gen/test-fpclassify.c
new file mode 100644
index 0000000..8431fe8
--- /dev/null
+++ b/tools/regression/lib/libc/gen/test-fpclassify.c
@@ -0,0 +1,75 @@
+/*-
+ * Copyright (c) 2003 Mike Barcroft <mike@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <assert.h>
+#include <math.h>
+#include <stdlib.h>
+
+int
+main(void)
+{
+
+ assert(fpclassify((float)0) == FP_ZERO);
+ assert(fpclassify((float)-0.0) == FP_ZERO);
+ assert(fpclassify((float)1) == FP_NORMAL);
+ assert(fpclassify((float)1000) == FP_NORMAL);
+#ifndef __alpha__
+ assert(fpclassify(0x1.2p-150f) == FP_SUBNORMAL);
+#endif
+ assert(fpclassify(HUGE_VALF) == FP_INFINITE);
+ assert(fpclassify((float)HUGE_VAL) == FP_INFINITE);
+ assert(fpclassify((float)HUGE_VALL) == FP_INFINITE);
+ assert(fpclassify(NAN) == FP_NAN);
+
+ assert(fpclassify((double)0) == FP_ZERO);
+ assert(fpclassify((double)-0) == FP_ZERO);
+ assert(fpclassify((double)1) == FP_NORMAL);
+ assert(fpclassify((double)1000) == FP_NORMAL);
+#ifndef __alpha__
+ assert(fpclassify(0x1.2p-1075) == FP_SUBNORMAL);
+#endif
+ assert(fpclassify(HUGE_VAL) == FP_INFINITE);
+ assert(fpclassify((double)HUGE_VALF) == FP_INFINITE);
+ assert(fpclassify((double)HUGE_VALL) == FP_INFINITE);
+ assert(fpclassify((double)NAN) == FP_NAN);
+
+ assert(fpclassify((long double)0) == FP_ZERO);
+ assert(fpclassify((long double)-0.0) == FP_ZERO);
+ assert(fpclassify((long double)1) == FP_NORMAL);
+ assert(fpclassify((long double)1000) == FP_NORMAL);
+#ifndef __alpha__
+ assert(fpclassify(0x1.2p-16383L) == FP_SUBNORMAL);
+#endif
+ assert(fpclassify(HUGE_VALL) == FP_INFINITE);
+ assert(fpclassify((long double)HUGE_VALF) == FP_INFINITE);
+ assert(fpclassify((long double)HUGE_VAL) == FP_INFINITE);
+ assert(fpclassify((long double)NAN) == FP_NAN);
+
+ printf("PASS fpclassify()\n");
+ exit(0);
+}
diff --git a/tools/regression/lib/libc/gen/test-wordexp.c b/tools/regression/lib/libc/gen/test-wordexp.c
new file mode 100644
index 0000000..49490d8
--- /dev/null
+++ b/tools/regression/lib/libc/gen/test-wordexp.c
@@ -0,0 +1,174 @@
+/*-
+ * Copyright (c) 2003 Tim J. Robbins
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Test program for wordexp() and wordfree() as specified by
+ * IEEE Std. 1003.1-2001.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wordexp.h>
+
+int
+main(int argc, char *argv[])
+{
+ wordexp_t we;
+ int r;
+
+ /* Test that the macros are there. */
+ (void)(WRDE_APPEND + WRDE_DOOFS + WRDE_NOCMD + WRDE_REUSE +
+ WRDE_SHOWERR + WRDE_UNDEF);
+ (void)(WRDE_BADCHAR + WRDE_BADVAL + WRDE_CMDSUB + WRDE_NOSPACE +
+ WRDE_SYNTAX);
+
+ /* Simple test. */
+ r = wordexp("hello world", &we, 0);
+ assert(r == 0);
+ assert(we.we_wordc == 2);
+ assert(strcmp(we.we_wordv[0], "hello") == 0);
+ assert(strcmp(we.we_wordv[1], "world") == 0);
+ assert(we.we_wordv[2] == NULL);
+ wordfree(&we);
+
+ /* WRDE_DOOFS */
+ we.we_offs = 3;
+ r = wordexp("hello world", &we, WRDE_DOOFS);
+ assert(r == 0);
+ assert(we.we_wordc == 2);
+ assert(we.we_wordv[0] == NULL);
+ assert(we.we_wordv[1] == NULL);
+ assert(we.we_wordv[2] == NULL);
+ assert(strcmp(we.we_wordv[3], "hello") == 0);
+ assert(strcmp(we.we_wordv[4], "world") == 0);
+ assert(we.we_wordv[5] == NULL);
+ wordfree(&we);
+
+ /* WRDE_REUSE */
+ r = wordexp("hello world", &we, 0);
+ r = wordexp("hello world", &we, WRDE_REUSE);
+ assert(r == 0);
+ assert(we.we_wordc == 2);
+ assert(strcmp(we.we_wordv[0], "hello") == 0);
+ assert(strcmp(we.we_wordv[1], "world") == 0);
+ assert(we.we_wordv[2] == NULL);
+ wordfree(&we);
+
+ /* WRDE_APPEND */
+ r = wordexp("this is", &we, 0);
+ assert(r == 0);
+ r = wordexp("a test", &we, WRDE_APPEND);
+ assert(r == 0);
+ assert(we.we_wordc == 4);
+ assert(strcmp(we.we_wordv[0], "this") == 0);
+ assert(strcmp(we.we_wordv[1], "is") == 0);
+ assert(strcmp(we.we_wordv[2], "a") == 0);
+ assert(strcmp(we.we_wordv[3], "test") == 0);
+ assert(we.we_wordv[4] == NULL);
+ wordfree(&we);
+
+ /* WRDE_DOOFS + WRDE_APPEND */
+ we.we_offs = 2;
+ r = wordexp("this is", &we, WRDE_DOOFS);
+ assert(r == 0);
+ r = wordexp("a test", &we, WRDE_APPEND|WRDE_DOOFS);
+ assert(r == 0);
+ r = wordexp("of wordexp", &we, WRDE_APPEND|WRDE_DOOFS);
+ assert(r == 0);
+ assert(we.we_wordc == 6);
+ assert(we.we_wordv[0] == NULL);
+ assert(we.we_wordv[1] == NULL);
+ assert(strcmp(we.we_wordv[2], "this") == 0);
+ assert(strcmp(we.we_wordv[3], "is") == 0);
+ assert(strcmp(we.we_wordv[4], "a") == 0);
+ assert(strcmp(we.we_wordv[5], "test") == 0);
+ assert(strcmp(we.we_wordv[6], "of") == 0);
+ assert(strcmp(we.we_wordv[7], "wordexp") == 0);
+ assert(we.we_wordv[8] == NULL);
+ wordfree(&we);
+
+ /* WRDE_UNDEF */
+ r = wordexp("${dont_set_me}", &we, WRDE_UNDEF);
+ assert(r == WRDE_BADVAL);
+
+ /* WRDE_NOCMD */
+ r = wordexp("`date`", &we, WRDE_NOCMD);
+ assert(r == WRDE_CMDSUB);
+ r = wordexp("\"`date`\"", &we, WRDE_NOCMD);
+ assert(r == WRDE_CMDSUB);
+ r = wordexp("$(date)", &we, WRDE_NOCMD);
+ assert(r == WRDE_CMDSUB);
+ r = wordexp("\"$(date)\"", &we, WRDE_NOCMD);
+ assert(r == WRDE_CMDSUB);
+ r = wordexp("$((3+5))", &we, WRDE_NOCMD);
+ assert(r == 0);
+ r = wordexp("\\$\\(date\\)", &we, WRDE_NOCMD|WRDE_REUSE);
+ assert(r == 0);
+ r = wordexp("'`date`'", &we, WRDE_NOCMD|WRDE_REUSE);
+ assert(r == 0);
+ r = wordexp("'$(date)'", &we, WRDE_NOCMD|WRDE_REUSE);
+ assert(r == 0);
+ wordfree(&we);
+
+ /* WRDE_BADCHAR */
+ r = wordexp("'\n|&;<>(){}'", &we, 0);
+ assert(r == 0);
+ r = wordexp("\"\n|&;<>(){}\"", &we, WRDE_REUSE);
+ assert(r == 0);
+ r = wordexp("\\\n\\|\\&\\;\\<\\>\\(\\)\\{\\}", &we, WRDE_REUSE);
+ assert(r == 0);
+ wordfree(&we);
+ r = wordexp("test \n test", &we, 0);
+ assert(r == WRDE_BADCHAR);
+ r = wordexp("test | test", &we, 0);
+ assert(r == WRDE_BADCHAR);
+ r = wordexp("test & test", &we, 0);
+ assert(r == WRDE_BADCHAR);
+ r = wordexp("test ; test", &we, 0);
+ assert(r == WRDE_BADCHAR);
+ r = wordexp("test > test", &we, 0);
+ assert(r == WRDE_BADCHAR);
+ r = wordexp("test < test", &we, 0);
+ assert(r == WRDE_BADCHAR);
+ r = wordexp("test ( test", &we, 0);
+ assert(r == WRDE_BADCHAR);
+ r = wordexp("test ) test", &we, 0);
+ assert(r == WRDE_BADCHAR);
+ r = wordexp("test { test", &we, 0);
+ assert(r == WRDE_BADCHAR);
+ r = wordexp("test } test", &we, 0);
+ assert(r == WRDE_BADCHAR);
+
+ printf("PASS wordexp()\n");
+ printf("PASS wordfree()\n");
+
+ return (0);
+}
diff --git a/tools/regression/lib/libc/locale/Makefile b/tools/regression/lib/libc/locale/Makefile
new file mode 100644
index 0000000..5fb9a94
--- /dev/null
+++ b/tools/regression/lib/libc/locale/Makefile
@@ -0,0 +1,25 @@
+# $FreeBSD$
+
+TESTS= test-mbrtowc \
+ test-wcrtomb \
+ test-mbsnrtowcs \
+ test-mbsrtowcs \
+ test-wcsnrtombs \
+ test-wcsrtombs \
+ test-btowc \
+ test-mbrlen \
+ test-mbtowc \
+ test-wctomb \
+ test-mbstowcs \
+ test-wcstombs \
+ test-mblen \
+ test-iswctype \
+ test-towctrans
+
+.PHONY: tests
+tests: ${TESTS}
+ for p in ${TESTS}; do ${.OBJDIR}/$$p; done
+
+.PHONY: clean
+clean:
+ -rm -f ${TESTS}
diff --git a/tools/regression/lib/libc/locale/test-btowc.c b/tools/regression/lib/libc/locale/test-btowc.c
new file mode 100644
index 0000000..9ed4582
--- /dev/null
+++ b/tools/regression/lib/libc/locale/test-btowc.c
@@ -0,0 +1,72 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Test program for btowc() and wctob() as specified by IEEE Std. 1003.1-2001
+ * and ISO/IEC 9899:1999.
+ *
+ * The function is tested in the "C" and "ja_JP.eucJP" locales.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <wchar.h>
+
+int
+main(int argc, char *argv[])
+{
+ int i;
+
+ printf("1..2\n");
+
+ /*
+ * C/POSIX locale.
+ */
+ assert(btowc(EOF) == WEOF);
+ assert(wctob(WEOF) == EOF);
+ for (i = 0; i < UCHAR_MAX; i++)
+ assert(btowc(i) == (wchar_t)i && i == (int)wctob(i));
+
+ /*
+ * Japanese (EUC) locale.
+ */
+
+ assert(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0);
+ assert(MB_CUR_MAX > 1);
+ assert(btowc('A') == L'A' && wctob(L'A') == 'A');
+ assert(btowc(0xa3) == WEOF && wctob(0xa3c1) == EOF);
+
+ printf("ok 1 - btowc()\n");
+ printf("ok 2 - wctob()\n");
+
+ return (0);
+}
diff --git a/tools/regression/lib/libc/locale/test-btowc.t b/tools/regression/lib/libc/locale/test-btowc.t
new file mode 100644
index 0000000..8bdfd03
--- /dev/null
+++ b/tools/regression/lib/libc/locale/test-btowc.t
@@ -0,0 +1,10 @@
+#!/bin/sh
+# $FreeBSD$
+
+cd `dirname $0`
+
+executable=`basename $0 .t`
+
+make $executable 2>&1 > /dev/null
+
+exec ./$executable
diff --git a/tools/regression/lib/libc/locale/test-iswctype.c b/tools/regression/lib/libc/locale/test-iswctype.c
new file mode 100644
index 0000000..ca9621a
--- /dev/null
+++ b/tools/regression/lib/libc/locale/test-iswctype.c
@@ -0,0 +1,101 @@
+/*-
+ * Copyright (c) 2003 Tim J. Robbins
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Test program for wctype() and iswctype() as specified by
+ * IEEE Std. 1003.1-2001 and ISO/IEC 9899:1999.
+ *
+ * The functions are tested in the "C" and "ja_JP.eucJP" locales.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <locale.h>
+#include <stdio.h>
+#include <wchar.h>
+#include <wctype.h>
+
+int
+main(int argc, char *argv[])
+{
+ wctype_t t;
+ int i, j;
+ struct {
+ const char *name;
+ int (*func)(wint_t);
+ } cls[] = {
+ { "alnum", iswalnum },
+ { "alpha", iswalpha },
+ { "blank", iswblank },
+ { "cntrl", iswcntrl },
+ { "digit", iswdigit },
+ { "graph", iswgraph },
+ { "lower", iswlower },
+ { "print", iswprint },
+ { "punct", iswpunct },
+ { "space", iswspace },
+ { "upper", iswupper },
+ { "xdigit", iswxdigit }
+ };
+
+ printf("1..2\n");
+
+ /*
+ * C/POSIX locale.
+ */
+ for (i = 0; i < sizeof(cls) / sizeof(*cls); i++) {
+ t = wctype(cls[i].name);
+ assert(t != 0);
+ for (j = 0; j < 256; j++)
+ assert(cls[i].func(j) == iswctype(j, t));
+ }
+ t = wctype("elephant");
+ assert(t == 0);
+ for (i = 0; i < 256; i++)
+ assert(iswctype(i, t) == 0);
+
+ /*
+ * Japanese (EUC) locale.
+ */
+ assert(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0);
+ for (i = 0; i < sizeof(cls) / sizeof(*cls); i++) {
+ t = wctype(cls[i].name);
+ assert(t != 0);
+ for (j = 0; j < 65536; j++)
+ assert(cls[i].func(j) == iswctype(j, t));
+ }
+ t = wctype("elephant");
+ assert(t == 0);
+ for (i = 0; i < 65536; i++)
+ assert(iswctype(i, t) == 0);
+
+ printf("ok 1 - iswctype()\n");
+ printf("ok 2 - wctype()\n");
+
+ return (0);
+}
diff --git a/tools/regression/lib/libc/locale/test-iswctype.t b/tools/regression/lib/libc/locale/test-iswctype.t
new file mode 100644
index 0000000..8bdfd03
--- /dev/null
+++ b/tools/regression/lib/libc/locale/test-iswctype.t
@@ -0,0 +1,10 @@
+#!/bin/sh
+# $FreeBSD$
+
+cd `dirname $0`
+
+executable=`basename $0 .t`
+
+make $executable 2>&1 > /dev/null
+
+exec ./$executable
diff --git a/tools/regression/lib/libc/locale/test-mblen.c b/tools/regression/lib/libc/locale/test-mblen.c
new file mode 100644
index 0000000..dd07359
--- /dev/null
+++ b/tools/regression/lib/libc/locale/test-mblen.c
@@ -0,0 +1,114 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Test program for mblen(), as specified by IEEE Std. 1003.1-2001 and
+ * ISO/IEC 9899:1990.
+ *
+ * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and
+ * "ja_JP.eucJP". Other encodings are not tested.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int
+main(int argc, char *argv[])
+{
+ size_t len;
+ char buf[MB_LEN_MAX + 1];
+
+ /*
+ * C/POSIX locale.
+ */
+
+ printf("1..1\n");
+
+ assert(MB_CUR_MAX == 1);
+
+ /* No shift states in C locale. */
+ assert(mblen(NULL, 0) == 0);
+
+ /* Null wide character. */
+ memset(buf, 0xcc, sizeof(buf));
+ buf[0] = '\0';
+ assert(mblen(buf, 1) == 0);
+
+ /* Latin letter A. */
+ buf[0] = 'A';
+ assert(mblen(buf, 1) == 1);
+
+ /* Incomplete character sequence. */
+ buf[0] = '\0';
+ assert(mblen(buf, 0) == -1);
+ assert(mblen(NULL, 0) == 0);
+
+ /*
+ * Japanese (EUC) locale.
+ */
+
+ assert(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0);
+ assert(MB_CUR_MAX > 1);
+
+ /* No shift states in EUC. */
+ assert(mblen(NULL, 0) == 0);
+
+ /* Null wide character. */
+ memset(buf, 0xcc, sizeof(buf));
+ buf[0] = '\0';
+ assert(mblen(buf, 1) == 0);
+
+ /* Latin letter A. */
+ buf[0] = 'A';
+ assert(mblen(buf, 1) == 1);
+
+ /* Incomplete character sequence. */
+ buf[0] = '\0';
+ assert(mblen(buf, 0) == -1);
+ assert(mblen(NULL, 0) == 0);
+
+ /* Incomplete character sequence (truncated double-byte). */
+ memset(buf, 0xcc, sizeof(buf));
+ buf[0] = 0xa3;
+ buf[1] = 0x00;
+ assert(mblen(buf, 1) == -1);
+ assert(mblen(NULL, 0) == 0);
+
+ /* Same as above, but complete. */
+ buf[1] = 0xc1;
+ assert(mblen(buf, 2) == 2);
+
+ printf("ok 1 - mblen()\n");
+
+ return (0);
+}
diff --git a/tools/regression/lib/libc/locale/test-mblen.t b/tools/regression/lib/libc/locale/test-mblen.t
new file mode 100644
index 0000000..8bdfd03
--- /dev/null
+++ b/tools/regression/lib/libc/locale/test-mblen.t
@@ -0,0 +1,10 @@
+#!/bin/sh
+# $FreeBSD$
+
+cd `dirname $0`
+
+executable=`basename $0 .t`
+
+make $executable 2>&1 > /dev/null
+
+exec ./$executable
diff --git a/tools/regression/lib/libc/locale/test-mbrlen.c b/tools/regression/lib/libc/locale/test-mbrlen.c
new file mode 100644
index 0000000..3198a77
--- /dev/null
+++ b/tools/regression/lib/libc/locale/test-mbrlen.c
@@ -0,0 +1,129 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Test program for mbrlen(), as specified by IEEE Std. 1003.1-2001 and
+ * ISO/IEC 9899:1999.
+ *
+ * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and
+ * "ja_JP.eucJP". Other encodings are not tested.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+int
+main(int argc, char *argv[])
+{
+ mbstate_t s;
+ size_t len;
+ char buf[MB_LEN_MAX + 1];
+
+ /*
+ * C/POSIX locale.
+ */
+
+ printf("1..1\n");
+
+ assert(MB_CUR_MAX == 1);
+
+ /* Null wide character, internal state. */
+ memset(buf, 0xcc, sizeof(buf));
+ buf[0] = 0;
+ assert(mbrlen(buf, 1, NULL) == 0);
+
+ /* Null wide character. */
+ memset(&s, 0, sizeof(s));
+ assert(mbrlen(buf, 1, &s) == 0);
+
+ /* Latin letter A, internal state. */
+ assert(mbrlen(NULL, 0, NULL) == 0);
+ buf[0] = 'A';
+ assert(mbrlen(buf, 1, NULL) == 1);
+
+ /* Latin letter A. */
+ memset(&s, 0, sizeof(s));
+ assert(mbrlen(buf, 1, &s) == 1);
+
+ /* Incomplete character sequence. */
+ memset(&s, 0, sizeof(s));
+ assert(mbrlen(buf, 0, &s) == (size_t)-2);
+
+ /*
+ * Japanese (EUC) locale.
+ */
+
+ assert(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0);
+ assert(MB_CUR_MAX > 1);
+
+ /* Null wide character, internal state. */
+ assert(mbrlen(NULL, 0, NULL) == 0);
+ memset(buf, 0xcc, sizeof(buf));
+ buf[0] = 0;
+ assert(mbrlen(buf, 1, NULL) == 0);
+
+ /* Null wide character. */
+ memset(&s, 0, sizeof(s));
+ assert(mbrlen(buf, 1, &s) == 0);
+
+ /* Latin letter A, internal state. */
+ assert(mbrlen(NULL, 0, NULL) == 0);
+ buf[0] = 'A';
+ assert(mbrlen(buf, 1, NULL) == 1);
+
+ /* Latin letter A. */
+ memset(&s, 0, sizeof(s));
+ assert(mbrlen(buf, 1, &s) == 1);
+
+ /* Incomplete character sequence (zero length). */
+ memset(&s, 0, sizeof(s));
+ assert(mbrlen(buf, 0, &s) == (size_t)-2);
+
+ /* Incomplete character sequence (truncated double-byte). */
+ memset(buf, 0xcc, sizeof(buf));
+ buf[0] = 0xa3;
+ buf[1] = 0x00;
+ memset(&s, 0, sizeof(s));
+ assert(mbrlen(buf, 1, &s) == (size_t)-2);
+
+ /* Same as above, but complete. */
+ buf[1] = 0xc1;
+ memset(&s, 0, sizeof(s));
+ assert(mbrlen(buf, 2, &s) == 2);
+
+ printf("ok 1 - mbrlen()\n");
+
+ return (0);
+}
diff --git a/tools/regression/lib/libc/locale/test-mbrlen.t b/tools/regression/lib/libc/locale/test-mbrlen.t
new file mode 100644
index 0000000..8bdfd03
--- /dev/null
+++ b/tools/regression/lib/libc/locale/test-mbrlen.t
@@ -0,0 +1,10 @@
+#!/bin/sh
+# $FreeBSD$
+
+cd `dirname $0`
+
+executable=`basename $0 .t`
+
+make $executable 2>&1 > /dev/null
+
+exec ./$executable
diff --git a/tools/regression/lib/libc/locale/test-mbrtowc.c b/tools/regression/lib/libc/locale/test-mbrtowc.c
new file mode 100644
index 0000000..e9a2ea0
--- /dev/null
+++ b/tools/regression/lib/libc/locale/test-mbrtowc.c
@@ -0,0 +1,163 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Test program for mbrtowc(), as specified by IEEE Std. 1003.1-2001 and
+ * ISO/IEC 9899:1999.
+ *
+ * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and
+ * "ja_JP.eucJP". Other encodings are not tested.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+int
+main(int argc, char *argv[])
+{
+ mbstate_t s;
+ size_t len;
+ wchar_t wc;
+ char buf[MB_LEN_MAX + 1];
+
+ /*
+ * C/POSIX locale.
+ */
+
+ printf("1..1\n");
+
+ assert(MB_CUR_MAX == 1);
+
+ /* Null wide character, internal state. */
+ memset(buf, 0xcc, sizeof(buf));
+ buf[0] = 0;
+ assert(mbrtowc(&wc, buf, 1, NULL) == 0);
+ assert(wc == 0);
+
+ /* Null wide character. */
+ memset(&s, 0, sizeof(s));
+ assert(mbrtowc(&wc, buf, 1, &s) == 0);
+ assert(wc == 0);
+
+ /* Latin letter A, internal state. */
+ assert(mbrtowc(NULL, 0, 0, NULL) == 0);
+ buf[0] = 'A';
+ assert(mbrtowc(&wc, buf, 1, NULL) == 1);
+ assert(wc == L'A');
+
+ /* Latin letter A. */
+ memset(&s, 0, sizeof(s));
+ assert(mbrtowc(&wc, buf, 1, &s) == 1);
+ assert(wc == L'A');
+
+ /* Incomplete character sequence. */
+ wc = L'z';
+ memset(&s, 0, sizeof(s));
+ assert(mbrtowc(&wc, buf, 0, &s) == (size_t)-2);
+ assert(wc == L'z');
+
+ /* Check that mbrtowc() doesn't access the buffer when n == 0. */
+ wc = L'z';
+ memset(&s, 0, sizeof(s));
+ buf[0] = '\0';
+ assert(mbrtowc(&wc, buf, 0, &s) == (size_t)-2);
+ assert(wc == L'z');
+
+ /*
+ * Japanese (EUC) locale.
+ */
+
+ assert(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0);
+ assert(MB_CUR_MAX > 1);
+
+ /* Null wide character, internal state. */
+ assert(mbrtowc(NULL, 0, 0, NULL) == 0);
+ memset(buf, 0xcc, sizeof(buf));
+ buf[0] = 0;
+ assert(mbrtowc(&wc, buf, 1, NULL) == 0);
+ assert(wc == 0);
+
+ /* Null wide character. */
+ memset(&s, 0, sizeof(s));
+ assert(mbrtowc(&wc, buf, 1, &s) == 0);
+ assert(wc == 0);
+
+ /* Latin letter A, internal state. */
+ assert(mbrtowc(NULL, 0, 0, NULL) == 0);
+ buf[0] = 'A';
+ assert(mbrtowc(&wc, buf, 1, NULL) == 1);
+ assert(wc == L'A');
+
+ /* Latin letter A. */
+ memset(&s, 0, sizeof(s));
+ assert(mbrtowc(&wc, buf, 1, &s) == 1);
+ assert(wc == L'A');
+
+ /* Incomplete character sequence (zero length). */
+ wc = L'z';
+ memset(&s, 0, sizeof(s));
+ assert(mbrtowc(&wc, buf, 0, &s) == (size_t)-2);
+ assert(wc == L'z');
+
+ /* Incomplete character sequence (truncated double-byte). */
+ memset(buf, 0xcc, sizeof(buf));
+ buf[0] = 0xa3;
+ buf[1] = 0x00;
+ memset(&s, 0, sizeof(s));
+ wc = 0;
+ assert(mbrtowc(&wc, buf, 1, &s) == (size_t)-2);
+
+ /* Same as above, but complete. */
+ buf[1] = 0xc1;
+ memset(&s, 0, sizeof(s));
+ wc = 0;
+ assert(mbrtowc(&wc, buf, 2, &s) == 2);
+ assert(wc == 0xa3c1);
+
+ /* Test restarting behaviour. */
+ memset(buf, 0xcc, sizeof(buf));
+ buf[0] = 0xa3;
+ memset(&s, 0, sizeof(s));
+ wc = 0;
+ assert(mbrtowc(&wc, buf, 1, &s) == (size_t)-2);
+ assert(wc == 0);
+ buf[0] = 0xc1;
+ assert(mbrtowc(&wc, buf, 1, &s) == 1);
+ assert(wc == 0xa3c1);
+
+ printf("ok 1 - mbrtowc()\n");
+
+ return (0);
+}
diff --git a/tools/regression/lib/libc/locale/test-mbrtowc.t b/tools/regression/lib/libc/locale/test-mbrtowc.t
new file mode 100644
index 0000000..8bdfd03
--- /dev/null
+++ b/tools/regression/lib/libc/locale/test-mbrtowc.t
@@ -0,0 +1,10 @@
+#!/bin/sh
+# $FreeBSD$
+
+cd `dirname $0`
+
+executable=`basename $0 .t`
+
+make $executable 2>&1 > /dev/null
+
+exec ./$executable
diff --git a/tools/regression/lib/libc/locale/test-mbsnrtowcs.c b/tools/regression/lib/libc/locale/test-mbsnrtowcs.c
new file mode 100644
index 0000000..585dd4e
--- /dev/null
+++ b/tools/regression/lib/libc/locale/test-mbsnrtowcs.c
@@ -0,0 +1,194 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Test program for mbsnrtowcs().
+ *
+ * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and
+ * "ja_JP.eucJP". Other encodings are not tested.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+int
+main(int argc, char *argv[])
+{
+ char srcbuf[128];
+ wchar_t dstbuf[128];
+ char *src;
+ mbstate_t s;
+
+ /*
+ * C/POSIX locale.
+ */
+
+ printf("1..1\n");
+
+ /* Simple null terminated string. */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "hello");
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ assert(mbsnrtowcs(dstbuf, (const char **)&src, 6, sizeof(dstbuf) /
+ sizeof(*dstbuf), &s) == 5);
+ assert(wcscmp(dstbuf, L"hello") == 0);
+ assert(dstbuf[6] == 0xcccc);
+ assert(src == NULL);
+
+ /* Simple null terminated string, stopping early. */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "hello");
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ assert(mbsnrtowcs(dstbuf, (const char **)&src, 4, sizeof(dstbuf) /
+ sizeof(*dstbuf), &s) == 4);
+ assert(wmemcmp(dstbuf, L"hell", 4) == 0);
+ assert(dstbuf[5] == 0xcccc);
+ assert(src == srcbuf + 4);
+
+ /* Not enough space in destination buffer. */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "hello");
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ assert(mbsnrtowcs(dstbuf, (const char **)&src, 6, 4, &s) == 4);
+ assert(wmemcmp(dstbuf, L"hell", 4) == 0);
+ assert(dstbuf[5] == 0xcccc);
+ assert(src == srcbuf + 4);
+
+ /* Null terminated string, internal dest. buffer */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "hello");
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ assert(mbsnrtowcs(NULL, (const char **)&src, 6, 0, &s) == 5);
+
+ /* Null terminated string, internal dest. buffer, stopping early */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "hello");
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ assert(mbsnrtowcs(NULL, (const char **)&src, 4, 0, &s) == 4);
+
+ /* Null terminated string, internal state. */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "hello");
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ src = srcbuf;
+ assert(mbsnrtowcs(dstbuf, (const char **)&src, 6, sizeof(dstbuf) /
+ sizeof(*dstbuf), NULL) == 5);
+ assert(wcscmp(dstbuf, L"hello") == 0);
+ assert(dstbuf[6] == 0xcccc);
+ assert(src == NULL);
+
+ /* Null terminated string, internal state, internal dest. buffer. */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "hello");
+ src = srcbuf;
+ assert(mbsnrtowcs(NULL, (const char **)&src, 6, 0, NULL) == 5);
+
+ /* Empty source buffer. */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ srcbuf[0] = '\0';
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ assert(mbsnrtowcs(dstbuf, (const char **)&src, 1, 1, &s) == 0);
+ assert(dstbuf[0] == 0);
+ assert(dstbuf[1] == 0xcccc);
+ assert(src == NULL);
+
+ /* Zero length destination buffer. */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "hello");
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ assert(mbsnrtowcs(dstbuf, (const char **)&src, 1, 0, &s) == 0);
+ assert(dstbuf[0] == 0xcccc);
+ assert(src == srcbuf);
+
+ /* Zero length source buffer. */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ assert(mbsnrtowcs(dstbuf, (const char **)&src, 0, 1, &s) == 0);
+ assert(dstbuf[0] == 0xcccc);
+ assert(src == srcbuf);
+
+ /*
+ * Japanese (EUC) locale.
+ */
+
+ assert(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0);
+ assert(MB_CUR_MAX > 1);
+
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "\xA3\xC1 B \xA3\xC3");
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ assert(mbsnrtowcs(dstbuf, (const char **)&src, 8, sizeof(dstbuf) /
+ sizeof(*dstbuf), &s) == 5);
+ assert(dstbuf[0] == 0xA3C1 && dstbuf[1] == 0x20 && dstbuf[2] == 0x42 &&
+ dstbuf[3] == 0x20 && dstbuf[4] == 0xA3C3 && dstbuf[5] == 0);
+ assert(src == NULL);
+
+ /* Partial character. */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "\xA3\xC1 B \xA3\xC3");
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ assert(mbsnrtowcs(dstbuf, (const char **)&src, 6, sizeof(dstbuf) /
+ sizeof(*dstbuf), &s) == 4);
+ assert(src == srcbuf + 6);
+ assert(!mbsinit(&s));
+ assert(mbsnrtowcs(dstbuf, (const char **)&src, 1, sizeof(dstbuf) /
+ sizeof(*dstbuf), &s) == 1);
+ assert(src == srcbuf + 7);
+ assert(mbsnrtowcs(dstbuf, (const char **)&src, 1, sizeof(dstbuf) /
+ sizeof(*dstbuf), &s) == 0);
+ assert(src == NULL);
+
+ printf("ok 1 - mbsnrtowcs()\n");
+
+ return (0);
+}
diff --git a/tools/regression/lib/libc/locale/test-mbsnrtowcs.t b/tools/regression/lib/libc/locale/test-mbsnrtowcs.t
new file mode 100644
index 0000000..8bdfd03
--- /dev/null
+++ b/tools/regression/lib/libc/locale/test-mbsnrtowcs.t
@@ -0,0 +1,10 @@
+#!/bin/sh
+# $FreeBSD$
+
+cd `dirname $0`
+
+executable=`basename $0 .t`
+
+make $executable 2>&1 > /dev/null
+
+exec ./$executable
diff --git a/tools/regression/lib/libc/locale/test-mbsrtowcs.c b/tools/regression/lib/libc/locale/test-mbsrtowcs.c
new file mode 100644
index 0000000..dd6a7e1
--- /dev/null
+++ b/tools/regression/lib/libc/locale/test-mbsrtowcs.c
@@ -0,0 +1,150 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Test program for mbsrtowcs(), as specified by IEEE Std. 1003.1-2001 and
+ * ISO/IEC 9899:1999.
+ *
+ * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and
+ * "ja_JP.eucJP". Other encodings are not tested.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+int
+main(int argc, char *argv[])
+{
+ char srcbuf[128];
+ wchar_t dstbuf[128];
+ char *src;
+ mbstate_t s;
+
+ /*
+ * C/POSIX locale.
+ */
+
+ printf("1..1\n");
+
+ /* Simple null terminated string. */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "hello");
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ assert(mbsrtowcs(dstbuf, (const char **)&src, sizeof(dstbuf) /
+ sizeof(*dstbuf), &s) == 5);
+ assert(wcscmp(dstbuf, L"hello") == 0);
+ assert(dstbuf[6] == 0xcccc);
+ assert(src == NULL);
+
+ /* Not enough space in destination buffer. */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "hello");
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ assert(mbsrtowcs(dstbuf, (const char **)&src, 4, &s) == 4);
+ assert(wmemcmp(dstbuf, L"hell", 4) == 0);
+ assert(dstbuf[5] == 0xcccc);
+ assert(src == srcbuf + 4);
+
+ /* Null terminated string, internal dest. buffer */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "hello");
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ assert(mbsrtowcs(NULL, (const char **)&src, 0, &s) == 5);
+
+ /* Null terminated string, internal state. */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "hello");
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ src = srcbuf;
+ assert(mbsrtowcs(dstbuf, (const char **)&src, sizeof(dstbuf) /
+ sizeof(*dstbuf), NULL) == 5);
+ assert(wcscmp(dstbuf, L"hello") == 0);
+ assert(dstbuf[6] == 0xcccc);
+ assert(src == NULL);
+
+ /* Null terminated string, internal state, internal dest. buffer. */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "hello");
+ src = srcbuf;
+ assert(mbsrtowcs(NULL, (const char **)&src, 0, NULL) == 5);
+
+ /* Empty source buffer. */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ srcbuf[0] = '\0';
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ assert(mbsrtowcs(dstbuf, (const char **)&src, 1, &s) == 0);
+ assert(dstbuf[0] == 0);
+ assert(dstbuf[1] == 0xcccc);
+ assert(src == NULL);
+
+ /* Zero length destination buffer. */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "hello");
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ assert(mbsrtowcs(dstbuf, (const char **)&src, 0, &s) == 0);
+ assert(dstbuf[0] == 0xcccc);
+ assert(src == srcbuf);
+
+ /*
+ * Japanese (EUC) locale.
+ */
+
+ assert(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0);
+ assert(MB_CUR_MAX > 1);
+
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "\xA3\xC1 B \xA3\xC3");
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ assert(mbsrtowcs(dstbuf, (const char **)&src, sizeof(dstbuf) /
+ sizeof(*dstbuf), &s) == 5);
+ assert(dstbuf[0] == 0xA3C1 && dstbuf[1] == 0x20 && dstbuf[2] == 0x42 &&
+ dstbuf[3] == 0x20 && dstbuf[4] == 0xA3C3 && dstbuf[5] == 0);
+ assert(src == NULL);
+
+ printf("ok 1 - mbsrtowcs()\n");
+
+ return (0);
+}
diff --git a/tools/regression/lib/libc/locale/test-mbsrtowcs.t b/tools/regression/lib/libc/locale/test-mbsrtowcs.t
new file mode 100644
index 0000000..8bdfd03
--- /dev/null
+++ b/tools/regression/lib/libc/locale/test-mbsrtowcs.t
@@ -0,0 +1,10 @@
+#!/bin/sh
+# $FreeBSD$
+
+cd `dirname $0`
+
+executable=`basename $0 .t`
+
+make $executable 2>&1 > /dev/null
+
+exec ./$executable
diff --git a/tools/regression/lib/libc/locale/test-mbstowcs.c b/tools/regression/lib/libc/locale/test-mbstowcs.c
new file mode 100644
index 0000000..18039dd
--- /dev/null
+++ b/tools/regression/lib/libc/locale/test-mbstowcs.c
@@ -0,0 +1,112 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Test program for mbstowcs(), as specified by IEEE Std. 1003.1-2001 and
+ * ISO/IEC 9899:1999.
+ *
+ * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and
+ * "ja_JP.eucJP". Other encodings are not tested.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+int
+main(int argc, char *argv[])
+{
+ char srcbuf[128];
+ wchar_t dstbuf[128];
+
+ /*
+ * C/POSIX locale.
+ */
+
+ printf("1..1\n");
+
+ /* Simple null terminated string. */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "hello");
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ assert(mbstowcs(dstbuf, srcbuf, sizeof(dstbuf) / sizeof(*dstbuf)) == 5);
+ assert(wcscmp(dstbuf, L"hello") == 0);
+ assert(dstbuf[6] == 0xcccc);
+
+ /* Not enough space in destination buffer. */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "hello");
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ assert(mbstowcs(dstbuf, srcbuf, 4) == 4);
+ assert(wmemcmp(dstbuf, L"hell", 4) == 0);
+ assert(dstbuf[5] == 0xcccc);
+
+ /* Null terminated string, internal dest. buffer (XSI extension) */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "hello");
+ assert(mbstowcs(NULL, srcbuf, 0) == 5);
+
+ /* Empty source buffer. */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ srcbuf[0] = '\0';
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ assert(mbstowcs(dstbuf, srcbuf, 1) == 0);
+ assert(dstbuf[0] == 0);
+ assert(dstbuf[1] == 0xcccc);
+
+ /* Zero length destination buffer. */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "hello");
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ assert(mbstowcs(dstbuf, srcbuf, 0) == 0);
+ assert(dstbuf[0] == 0xcccc);
+
+ /*
+ * Japanese (EUC) locale.
+ */
+
+ assert(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0);
+ assert(MB_CUR_MAX > 1);
+
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "\xA3\xC1 B \xA3\xC3");
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ assert(mbstowcs(dstbuf, srcbuf, sizeof(dstbuf) / sizeof(*dstbuf)) == 5);
+ assert(dstbuf[0] == 0xA3C1 && dstbuf[1] == 0x20 && dstbuf[2] == 0x42 &&
+ dstbuf[3] == 0x20 && dstbuf[4] == 0xA3C3 && dstbuf[5] == 0);
+
+ printf("ok 1 - mbstowcs()\n");
+
+ return (0);
+}
diff --git a/tools/regression/lib/libc/locale/test-mbstowcs.t b/tools/regression/lib/libc/locale/test-mbstowcs.t
new file mode 100644
index 0000000..8bdfd03
--- /dev/null
+++ b/tools/regression/lib/libc/locale/test-mbstowcs.t
@@ -0,0 +1,10 @@
+#!/bin/sh
+# $FreeBSD$
+
+cd `dirname $0`
+
+executable=`basename $0 .t`
+
+make $executable 2>&1 > /dev/null
+
+exec ./$executable
diff --git a/tools/regression/lib/libc/locale/test-mbtowc.c b/tools/regression/lib/libc/locale/test-mbtowc.c
new file mode 100644
index 0000000..5ee070c
--- /dev/null
+++ b/tools/regression/lib/libc/locale/test-mbtowc.c
@@ -0,0 +1,124 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Test program for mbtowc(), as specified by IEEE Std. 1003.1-2001 and
+ * ISO/IEC 9899:1990.
+ *
+ * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and
+ * "ja_JP.eucJP". Other encodings are not tested.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int
+main(int argc, char *argv[])
+{
+ size_t len;
+ wchar_t wc;
+ char buf[MB_LEN_MAX + 1];
+
+ /*
+ * C/POSIX locale.
+ */
+
+ printf("1..1\n");
+
+ assert(MB_CUR_MAX == 1);
+
+ /* No shift states in C locale. */
+ assert(mbtowc(NULL, NULL, 0) == 0);
+
+ /* Null wide character. */
+ wc = 0xcccc;
+ memset(buf, 0, sizeof(buf));
+ assert(mbtowc(&wc, buf, 1) == 0);
+ assert(wc == 0);
+
+ /* Latin letter A. */
+ buf[0] = 'A';
+ assert(mbtowc(&wc, buf, 1) == 1);
+ assert(wc == L'A');
+
+ /* Incomplete character sequence. */
+ wc = L'z';
+ buf[0] = '\0';
+ assert(mbtowc(&wc, buf, 0) == -1);
+ assert(wc == L'z');
+ assert(mbtowc(NULL, NULL, 0) == 0);
+
+ /*
+ * Japanese (EUC) locale.
+ */
+
+ assert(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0);
+ assert(MB_CUR_MAX > 1);
+
+ /* Null wide character */
+ memset(buf, 0xcc, sizeof(buf));
+ buf[0] = 0;
+ wc = 0xcccc;
+ assert(mbtowc(&wc, buf, 1) == 0);
+ assert(wc == 0);
+
+ /* Latin letter A. */
+ buf[0] = 'A';
+ assert(mbtowc(&wc, buf, 1) == 1);
+ assert(wc == L'A');
+
+ /* Incomplete character sequence (zero length). */
+ wc = L'z';
+ buf[0] = '\0';
+ assert(mbtowc(&wc, buf, 0) == -1);
+ assert(wc == L'z');
+ assert(mbtowc(NULL, NULL, 0) == 0);
+
+ /* Incomplete character sequence (truncated double-byte). */
+ memset(buf, 0xcc, sizeof(buf));
+ buf[0] = 0xa3;
+ buf[1] = 0x00;
+ wc = L'z';
+ assert(mbtowc(&wc, buf, 1) == -1);
+ assert(wc == L'z');
+ assert(mbtowc(NULL, NULL, 0) == 0);
+
+ /* Same as above, but complete. */
+ buf[1] = 0xc1;
+ assert(mbtowc(&wc, buf, 2) == 2);
+ assert(wc == 0xa3c1);
+
+ printf("ok 1 - mbtowc()\n");
+
+ return (0);
+}
diff --git a/tools/regression/lib/libc/locale/test-mbtowc.t b/tools/regression/lib/libc/locale/test-mbtowc.t
new file mode 100644
index 0000000..8bdfd03
--- /dev/null
+++ b/tools/regression/lib/libc/locale/test-mbtowc.t
@@ -0,0 +1,10 @@
+#!/bin/sh
+# $FreeBSD$
+
+cd `dirname $0`
+
+executable=`basename $0 .t`
+
+make $executable 2>&1 > /dev/null
+
+exec ./$executable
diff --git a/tools/regression/lib/libc/locale/test-towctrans.c b/tools/regression/lib/libc/locale/test-towctrans.c
new file mode 100644
index 0000000..6c0e428
--- /dev/null
+++ b/tools/regression/lib/libc/locale/test-towctrans.c
@@ -0,0 +1,91 @@
+/*-
+ * Copyright (c) 2003 Tim J. Robbins
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Test program for wctrans() and towctrans() as specified by
+ * IEEE Std. 1003.1-2001 and ISO/IEC 9899:1999.
+ *
+ * The functions are tested in the "C" and "ja_JP.eucJP" locales.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <locale.h>
+#include <stdio.h>
+#include <wchar.h>
+#include <wctype.h>
+
+int
+main(int argc, char *argv[])
+{
+ wctype_t t;
+ int i, j;
+ struct {
+ const char *name;
+ wint_t (*func)(wint_t);
+ } tran[] = {
+ { "tolower", towlower },
+ { "toupper", towupper },
+ };
+
+ printf("1..2\n");
+
+ /*
+ * C/POSIX locale.
+ */
+ for (i = 0; i < sizeof(tran) / sizeof(*tran); i++) {
+ t = wctrans(tran[i].name);
+ assert(t != 0);
+ for (j = 0; j < 256; j++)
+ assert(tran[i].func(j) == towctrans(j, t));
+ }
+ t = wctrans("elephant");
+ assert(t == 0);
+ for (i = 0; i < 256; i++)
+ assert(towctrans(i, t) == i);
+
+ /*
+ * Japanese (EUC) locale.
+ */
+ assert(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0);
+ for (i = 0; i < sizeof(tran) / sizeof(*tran); i++) {
+ t = wctrans(tran[i].name);
+ assert(t != 0);
+ for (j = 0; j < 65536; j++)
+ assert(tran[i].func(j) == towctrans(j, t));
+ }
+ t = wctrans("elephant");
+ assert(t == 0);
+ for (i = 0; i < 65536; i++)
+ assert(towctrans(i, t) == i);
+
+ printf("ok 1 - towctrans()\n");
+ printf("ok 2 - wctrans()\n");
+
+ return (0);
+}
diff --git a/tools/regression/lib/libc/locale/test-towctrans.t b/tools/regression/lib/libc/locale/test-towctrans.t
new file mode 100644
index 0000000..8bdfd03
--- /dev/null
+++ b/tools/regression/lib/libc/locale/test-towctrans.t
@@ -0,0 +1,10 @@
+#!/bin/sh
+# $FreeBSD$
+
+cd `dirname $0`
+
+executable=`basename $0 .t`
+
+make $executable 2>&1 > /dev/null
+
+exec ./$executable
diff --git a/tools/regression/lib/libc/locale/test-wcrtomb.c b/tools/regression/lib/libc/locale/test-wcrtomb.c
new file mode 100644
index 0000000..d7ec029
--- /dev/null
+++ b/tools/regression/lib/libc/locale/test-wcrtomb.c
@@ -0,0 +1,134 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Test program for wcrtomb(), as specified by IEEE Std. 1003.1-2001 and
+ * ISO/IEC 9899:1999.
+ *
+ * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and
+ * "ja_JP.eucJP". Other encodings are not tested.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+int
+main(int argc, char *argv[])
+{
+ mbstate_t s;
+ size_t len;
+ char buf[MB_LEN_MAX + 1];
+
+ /*
+ * C/POSIX locale.
+ */
+
+ printf("1..1\n");
+
+ assert(MB_CUR_MAX == 1);
+
+ /*
+ * If the buffer argument is NULL, wc is implicitly L'\0',
+ * wcrtomb() resets its internal state.
+ */
+ assert(wcrtomb(NULL, L'\0', NULL) == 1);
+ assert(wcrtomb(NULL, UCHAR_MAX + 1, NULL) == 1);
+
+ /* Null wide character. */
+ memset(&s, 0, sizeof(s));
+ memset(buf, 0xcc, sizeof(buf));
+ len = wcrtomb(buf, L'\0', &s);
+ assert(len == 1);
+ assert((unsigned char)buf[0] == 0 && (unsigned char)buf[1] == 0xcc);
+
+ /* Latin letter A, internal state. */
+ assert(wcrtomb(NULL, L'\0', NULL) == 1);
+ assert(wcrtomb(NULL, L'A', NULL) == 1);
+
+ /* Latin letter A. */
+ memset(&s, 0, sizeof(s));
+ memset(buf, 0xcc, sizeof(buf));
+ len = wcrtomb(buf, L'A', &s);
+ assert(len == 1);
+ assert((unsigned char)buf[0] == 'A' && (unsigned char)buf[1] == 0xcc);
+
+ /* Invalid code. */
+ assert(wcrtomb(buf, UCHAR_MAX + 1, NULL) == (size_t)-1);
+ assert(errno == EILSEQ);
+
+ /*
+ * Japanese (EUC) locale.
+ */
+
+ assert(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0);
+ assert(MB_CUR_MAX == 3);
+
+ /*
+ * If the buffer argument is NULL, wc is implicitly L'\0',
+ * wcrtomb() resets its internal state.
+ */
+ assert(wcrtomb(NULL, L'\0', NULL) == 1);
+
+ /* Null wide character. */
+ memset(&s, 0, sizeof(s));
+ memset(buf, 0xcc, sizeof(buf));
+ len = wcrtomb(buf, L'\0', &s);
+ assert(len == 1);
+ assert((unsigned char)buf[0] == 0 && (unsigned char)buf[1] == 0xcc);
+
+ /* Latin letter A, internal state. */
+ assert(wcrtomb(NULL, L'\0', NULL) == 1);
+ assert(wcrtomb(NULL, L'A', NULL) == 1);
+
+ /* Latin letter A. */
+ memset(&s, 0, sizeof(s));
+ memset(buf, 0xcc, sizeof(buf));
+ len = wcrtomb(buf, L'A', &s);
+ assert(len == 1);
+ assert((unsigned char)buf[0] == 'A' && (unsigned char)buf[1] == 0xcc);
+
+ /* Full width letter A. */
+ memset(&s, 0, sizeof(s));
+ memset(buf, 0xcc, sizeof(buf));
+ len = wcrtomb(buf, 0xa3c1, &s);
+ assert(len == 2);
+ assert((unsigned char)buf[0] == 0xa3 &&
+ (unsigned char)buf[1] == 0xc1 &&
+ (unsigned char)buf[2] == 0xcc);
+
+ printf("ok 1 - wcrtomb()\n");
+
+ return (0);
+}
diff --git a/tools/regression/lib/libc/locale/test-wcrtomb.t b/tools/regression/lib/libc/locale/test-wcrtomb.t
new file mode 100644
index 0000000..8bdfd03
--- /dev/null
+++ b/tools/regression/lib/libc/locale/test-wcrtomb.t
@@ -0,0 +1,10 @@
+#!/bin/sh
+# $FreeBSD$
+
+cd `dirname $0`
+
+executable=`basename $0 .t`
+
+make $executable 2>&1 > /dev/null
+
+exec ./$executable
diff --git a/tools/regression/lib/libc/locale/test-wcsnrtombs.c b/tools/regression/lib/libc/locale/test-wcsnrtombs.c
new file mode 100644
index 0000000..2290cac
--- /dev/null
+++ b/tools/regression/lib/libc/locale/test-wcsnrtombs.c
@@ -0,0 +1,194 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Test program for wcsnrtombs().
+ *
+ * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and
+ * "ja_JP.eucJP". Other encodings are not tested.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+int
+main(int argc, char *argv[])
+{
+ wchar_t srcbuf[128];
+ char dstbuf[128];
+ wchar_t *src;
+ mbstate_t s;
+
+ /*
+ * C/POSIX locale.
+ */
+
+ printf("1..1\n");
+
+ /* Simple null terminated string. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ assert(wcsnrtombs(dstbuf, (const wchar_t **)&src, 6, sizeof(dstbuf),
+ &s) == 5);
+ assert(strcmp(dstbuf, "hello") == 0);
+ assert((unsigned char)dstbuf[6] == 0xcc);
+ assert(src == NULL);
+
+ /* Simple null terminated string, stopping early. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ assert(wcsnrtombs(dstbuf, (const wchar_t **)&src, 4, sizeof(dstbuf),
+ &s) == 4);
+ assert(memcmp(dstbuf, "hell", 4) == 0);
+ assert((unsigned char)dstbuf[5] == 0xcc);
+ assert(src == srcbuf + 4);
+
+ /* Not enough space in destination buffer. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ assert(wcsnrtombs(dstbuf, (const wchar_t **)&src, 6, 4,
+ &s) == 4);
+ assert(memcmp(dstbuf, "hell", 4) == 0);
+ assert((unsigned char)dstbuf[5] == 0xcc);
+ assert(src == srcbuf + 4);
+
+ /* Null terminated string, internal dest. buffer */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ assert(wcsnrtombs(NULL, (const wchar_t **)&src, 6, sizeof(dstbuf),
+ &s) == 5);
+
+ /* Null terminated string, internal dest. buffer, stopping early. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ assert(wcsnrtombs(NULL, (const wchar_t **)&src, 4, sizeof(dstbuf),
+ &s) == 4);
+
+ /* Null terminated string, internal state. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ src = srcbuf;
+ assert(wcsnrtombs(dstbuf, (const wchar_t **)&src, 6, sizeof(dstbuf),
+ NULL) == 5);
+ assert(strcmp(dstbuf, "hello") == 0);
+ assert((unsigned char)dstbuf[6] == 0xcc);
+ assert(src == NULL);
+
+ /* Null terminated string, internal state, internal dest. buffer. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ src = srcbuf;
+ assert(wcsnrtombs(NULL, (const wchar_t **)&src, 6, 0, NULL) == 5);
+
+ /* Empty source buffer. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ srcbuf[0] = L'\0';
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ assert(wcsnrtombs(dstbuf, (const wchar_t **)&src, 1, sizeof(dstbuf),
+ &s) == 0);
+ assert(dstbuf[0] == L'\0');
+
+ /* Zero length destination buffer. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ assert(wcsnrtombs(dstbuf, (const wchar_t **)&src, 6, 0, &s) == 0);
+ assert((unsigned char)dstbuf[0] == 0xcc);
+
+ /* Zero length source buffer. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ assert(wcsnrtombs(dstbuf, (const wchar_t **)&src, 0, sizeof(dstbuf),
+ &s) == 0);
+ assert((unsigned char)dstbuf[0] == 0xcc);
+ assert(src == srcbuf);
+
+ /*
+ * Japanese (EUC) locale.
+ */
+
+ assert(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0);
+ assert(MB_CUR_MAX > 1);
+
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ srcbuf[0] = 0xA3C1;
+ srcbuf[1] = 0x0020;
+ srcbuf[2] = 0x0042;
+ srcbuf[3] = 0x0020;
+ srcbuf[4] = 0xA3C3;
+ srcbuf[5] = 0x0000;
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ assert(wcsnrtombs(dstbuf, (const wchar_t **)&src, 6, sizeof(dstbuf),
+ &s) == 7);
+ assert(strcmp(dstbuf, "\xA3\xC1 B \xA3\xC3") == 0);
+ assert((unsigned char)dstbuf[8] == 0xcc);
+ assert(src == NULL);
+
+ /* Stopping early. */
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ assert(wcsnrtombs(dstbuf, (const wchar_t **)&src, 6, 6,
+ &s) == 5);
+ assert(memcmp(dstbuf, "\xA3\xC1 B ", 5) == 0);
+ assert((unsigned char)dstbuf[5] == 0xcc);
+ assert(src == srcbuf + 4);
+
+ printf("ok 1 - wcsnrtombs()\n");
+
+ return (0);
+}
diff --git a/tools/regression/lib/libc/locale/test-wcsnrtombs.t b/tools/regression/lib/libc/locale/test-wcsnrtombs.t
new file mode 100644
index 0000000..8bdfd03
--- /dev/null
+++ b/tools/regression/lib/libc/locale/test-wcsnrtombs.t
@@ -0,0 +1,10 @@
+#!/bin/sh
+# $FreeBSD$
+
+cd `dirname $0`
+
+executable=`basename $0 .t`
+
+make $executable 2>&1 > /dev/null
+
+exec ./$executable
diff --git a/tools/regression/lib/libc/locale/test-wcsrtombs.c b/tools/regression/lib/libc/locale/test-wcsrtombs.c
new file mode 100644
index 0000000..48fe366
--- /dev/null
+++ b/tools/regression/lib/libc/locale/test-wcsrtombs.c
@@ -0,0 +1,155 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Test program for wcsrtombs(), as specified by IEEE Std. 1003.1-2001 and
+ * ISO/IEC 9899:1999.
+ *
+ * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and
+ * "ja_JP.eucJP". Other encodings are not tested.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+int
+main(int argc, char *argv[])
+{
+ wchar_t srcbuf[128];
+ char dstbuf[128];
+ wchar_t *src;
+ mbstate_t s;
+
+ /*
+ * C/POSIX locale.
+ */
+
+ printf("1..1\n");
+
+ /* Simple null terminated string. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ assert(wcsrtombs(dstbuf, (const wchar_t **)&src, sizeof(dstbuf),
+ &s) == 5);
+ assert(strcmp(dstbuf, "hello") == 0);
+ assert((unsigned char)dstbuf[6] == 0xcc);
+ assert(src == NULL);
+
+ /* Not enough space in destination buffer. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ assert(wcsrtombs(dstbuf, (const wchar_t **)&src, 4,
+ &s) == 4);
+ assert(memcmp(dstbuf, "hell", 4) == 0);
+ assert((unsigned char)dstbuf[5] == 0xcc);
+ assert(src == srcbuf + 4);
+
+ /* Null terminated string, internal dest. buffer */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ assert(wcsrtombs(NULL, (const wchar_t **)&src, sizeof(dstbuf),
+ &s) == 5);
+
+ /* Null terminated string, internal state. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ src = srcbuf;
+ assert(wcsrtombs(dstbuf, (const wchar_t **)&src, sizeof(dstbuf),
+ NULL) == 5);
+ assert(strcmp(dstbuf, "hello") == 0);
+ assert((unsigned char)dstbuf[6] == 0xcc);
+ assert(src == NULL);
+
+ /* Null terminated string, internal state, internal dest. buffer. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ src = srcbuf;
+ assert(wcsrtombs(NULL, (const wchar_t **)&src, 0, NULL) == 5);
+
+ /* Empty source buffer. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ srcbuf[0] = L'\0';
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ assert(wcsrtombs(dstbuf, (const wchar_t **)&src, sizeof(dstbuf),
+ &s) == 0);
+ assert(dstbuf[0] == L'\0');
+
+ /* Zero length destination buffer. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ assert(wcsrtombs(dstbuf, (const wchar_t **)&src, 0, &s) == 0);
+ assert((unsigned char)dstbuf[0] == 0xcc);
+
+ /*
+ * Japanese (EUC) locale.
+ */
+
+ assert(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0);
+ assert(MB_CUR_MAX > 1);
+
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ srcbuf[0] = 0xA3C1;
+ srcbuf[1] = 0x0020;
+ srcbuf[2] = 0x0042;
+ srcbuf[3] = 0x0020;
+ srcbuf[4] = 0xA3C3;
+ srcbuf[5] = 0x0000;
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ assert(wcsrtombs(dstbuf, (const wchar_t **)&src, sizeof(dstbuf),
+ &s) == 7);
+ assert(strcmp(dstbuf, "\xA3\xC1 B \xA3\xC3") == 0);
+ assert((unsigned char)dstbuf[8] == 0xcc);
+ assert(src == NULL);
+
+ printf("ok 1 - wcsrtombs()\n");
+
+ return (0);
+}
diff --git a/tools/regression/lib/libc/locale/test-wcsrtombs.t b/tools/regression/lib/libc/locale/test-wcsrtombs.t
new file mode 100644
index 0000000..8bdfd03
--- /dev/null
+++ b/tools/regression/lib/libc/locale/test-wcsrtombs.t
@@ -0,0 +1,10 @@
+#!/bin/sh
+# $FreeBSD$
+
+cd `dirname $0`
+
+executable=`basename $0 .t`
+
+make $executable 2>&1 > /dev/null
+
+exec ./$executable
diff --git a/tools/regression/lib/libc/locale/test-wcstombs.c b/tools/regression/lib/libc/locale/test-wcstombs.c
new file mode 100644
index 0000000..f4a5770
--- /dev/null
+++ b/tools/regression/lib/libc/locale/test-wcstombs.c
@@ -0,0 +1,129 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Test program for wcstombs(), as specified by IEEE Std. 1003.1-2001 and
+ * ISO/IEC 9899:1999.
+ *
+ * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and
+ * "ja_JP.eucJP". Other encodings are not tested.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+int
+main(int argc, char *argv[])
+{
+ wchar_t srcbuf[128];
+ char dstbuf[128];
+
+ /*
+ * C/POSIX locale.
+ */
+
+ printf("1..1\n");
+
+ /* Simple null terminated string. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ assert(wcstombs(dstbuf, srcbuf, sizeof(dstbuf)) == 5);
+ assert(strcmp(dstbuf, "hello") == 0);
+ assert((unsigned char)dstbuf[6] == 0xcc);
+
+ /* Not enough space in destination buffer. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ assert(wcstombs(dstbuf, srcbuf, 4) == 4);
+ assert(memcmp(dstbuf, "hell", 4) == 0);
+ assert((unsigned char)dstbuf[5] == 0xcc);
+
+ /* Null terminated string, internal dest. buffer */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ assert(wcstombs(NULL, srcbuf, sizeof(dstbuf)) == 5);
+
+ /* Null terminated string, internal state. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ assert(wcstombs(dstbuf, srcbuf, sizeof(dstbuf)) == 5);
+ assert(strcmp(dstbuf, "hello") == 0);
+ assert((unsigned char)dstbuf[6] == 0xcc);
+
+ /* Null terminated string, internal state, internal dest. buffer. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ assert(wcstombs(NULL, srcbuf, 0) == 5);
+
+ /* Empty source buffer. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ srcbuf[0] = L'\0';
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ assert(wcstombs(dstbuf, srcbuf, sizeof(dstbuf)) == 0);
+ assert(dstbuf[0] == L'\0');
+
+ /* Zero length destination buffer. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ assert(wcstombs(dstbuf, srcbuf, 0) == 0);
+ assert((unsigned char)dstbuf[0] == 0xcc);
+
+ /*
+ * Japanese (EUC) locale.
+ */
+
+ assert(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0);
+ assert(MB_CUR_MAX > 1);
+
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ srcbuf[0] = 0xA3C1;
+ srcbuf[1] = 0x0020;
+ srcbuf[2] = 0x0042;
+ srcbuf[3] = 0x0020;
+ srcbuf[4] = 0xA3C3;
+ srcbuf[5] = 0x0000;
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ assert(wcstombs(dstbuf, srcbuf, sizeof(dstbuf)) == 7);
+ assert(strcmp(dstbuf, "\xA3\xC1 B \xA3\xC3") == 0);
+ assert((unsigned char)dstbuf[8] == 0xcc);
+
+ printf("ok 1 - wcstombs()\n");
+
+ return (0);
+}
diff --git a/tools/regression/lib/libc/locale/test-wcstombs.t b/tools/regression/lib/libc/locale/test-wcstombs.t
new file mode 100644
index 0000000..8bdfd03
--- /dev/null
+++ b/tools/regression/lib/libc/locale/test-wcstombs.t
@@ -0,0 +1,10 @@
+#!/bin/sh
+# $FreeBSD$
+
+cd `dirname $0`
+
+executable=`basename $0 .t`
+
+make $executable 2>&1 > /dev/null
+
+exec ./$executable
diff --git a/tools/regression/lib/libc/locale/test-wctomb.c b/tools/regression/lib/libc/locale/test-wctomb.c
new file mode 100644
index 0000000..d55b3db
--- /dev/null
+++ b/tools/regression/lib/libc/locale/test-wctomb.c
@@ -0,0 +1,112 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Test program for wctomb(), as specified by IEEE Std. 1003.1-2001 and
+ * ISO/IEC 9899:1999.
+ *
+ * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and
+ * "ja_JP.eucJP". Other encodings are not tested.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int
+main(int argc, char *argv[])
+{
+ size_t len;
+ char buf[MB_LEN_MAX + 1];
+
+ /*
+ * C/POSIX locale.
+ */
+
+ printf("1..1\n");
+
+ assert(MB_CUR_MAX == 1);
+
+ /* No shift states in C locale. */
+ assert(wctomb(NULL, L'\0') == 0);
+
+ /* Null wide character. */
+ memset(buf, 0xcc, sizeof(buf));
+ len = wctomb(buf, L'\0');
+ assert(len == 1);
+ assert((unsigned char)buf[0] == 0 && (unsigned char)buf[1] == 0xcc);
+
+ /* Latin letter A. */
+ memset(buf, 0xcc, sizeof(buf));
+ len = wctomb(buf, L'A');
+ assert(len == 1);
+ assert((unsigned char)buf[0] == 'A' && (unsigned char)buf[1] == 0xcc);
+
+ /* Invalid code. */
+ assert(wctomb(buf, UCHAR_MAX + 1) == -1);
+ assert(wctomb(NULL, 0) == 0);
+
+ /*
+ * Japanese (EUC) locale.
+ */
+
+ assert(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0);
+ assert(MB_CUR_MAX == 3);
+
+ /* No shift states in EUC encoding. */
+ assert(wctomb(NULL, L'\0') == 0);
+
+ /* Null wide character. */
+ memset(buf, 0xcc, sizeof(buf));
+ len = wctomb(buf, L'\0');
+ assert(len == 1);
+ assert((unsigned char)buf[0] == 0 && (unsigned char)buf[1] == 0xcc);
+
+ /* Latin letter A. */
+ memset(buf, 0xcc, sizeof(buf));
+ len = wctomb(buf, L'A');
+ assert(len == 1);
+ assert((unsigned char)buf[0] == 'A' && (unsigned char)buf[1] == 0xcc);
+
+ /* Full width letter A. */
+ memset(buf, 0xcc, sizeof(buf));
+ len = wctomb(buf, 0xa3c1);
+ assert(len == 2);
+ assert((unsigned char)buf[0] == 0xa3 &&
+ (unsigned char)buf[1] == 0xc1 &&
+ (unsigned char)buf[2] == 0xcc);
+
+ printf("ok 1 - wctomb()\n");
+
+ return (0);
+}
diff --git a/tools/regression/lib/libc/locale/test-wctomb.t b/tools/regression/lib/libc/locale/test-wctomb.t
new file mode 100644
index 0000000..8bdfd03
--- /dev/null
+++ b/tools/regression/lib/libc/locale/test-wctomb.t
@@ -0,0 +1,10 @@
+#!/bin/sh
+# $FreeBSD$
+
+cd `dirname $0`
+
+executable=`basename $0 .t`
+
+make $executable 2>&1 > /dev/null
+
+exec ./$executable
diff --git a/tools/regression/lib/libc/net/Makefile b/tools/regression/lib/libc/net/Makefile
new file mode 100644
index 0000000..a61741b
--- /dev/null
+++ b/tools/regression/lib/libc/net/Makefile
@@ -0,0 +1,12 @@
+# $FreeBSD$
+
+TESTS= test-ether test-eui64_aton test-eui64_line test-eui64_ntoa
+CFLAGS+= -g -Wall
+
+.PHONY: tests
+tests: ${TESTS}
+ for p in ${TESTS}; do ${.OBJDIR}/$$p; done
+
+.PHONY: clean
+clean:
+ -rm -f ${TESTS}
diff --git a/tools/regression/lib/libc/net/test-ether.c b/tools/regression/lib/libc/net/test-ether.c
new file mode 100644
index 0000000..7408101
--- /dev/null
+++ b/tools/regression/lib/libc/net/test-ether.c
@@ -0,0 +1,235 @@
+/*-
+ * Copyright (c) 2007 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/types.h>
+
+#include <net/ethernet.h>
+
+#include <stdio.h>
+#include <string.h>
+
+static int testnum;
+
+#define OK() do { \
+ printf("ok %d %s\n", testnum, __func__); \
+ return; \
+} while (0)
+
+#define NOTOK(why) do { \
+ printf("not ok %d %s # %s\n", testnum, __func__, why); \
+ return; \
+} while (0)
+
+#define TODO() NOTOK("TODO")
+
+static const char *ether_line_string =
+ "01:23:45:67:89:ab ether_line_hostname";
+static const char *ether_line_hostname = "ether_line_hostname";
+static const struct ether_addr ether_line_addr = {
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab }
+};
+
+static void
+test_ether_line(void)
+{
+ struct ether_addr e;
+ char hostname[256];
+
+ testnum++;
+ if (ether_line(ether_line_string, &e, hostname) != 0)
+ NOTOK("returned error");
+ if (bcmp(&e, &ether_line_addr, ETHER_ADDR_LEN) != 0)
+ NOTOK("bad address");
+ if (strcmp(hostname, ether_line_hostname) != 0) {
+ printf("hostname: %s\n", hostname);
+ NOTOK("bad hostname");
+ }
+ OK();
+}
+
+static const char *ether_line_bad_1_string = "x";
+
+static void
+test_ether_line_bad_1(void)
+{
+ struct ether_addr e;
+ char hostname[256];
+
+ testnum++;
+ if (ether_line(ether_line_bad_1_string, &e, hostname) == 0)
+ NOTOK("returned success");
+ OK();
+}
+
+static const char *ether_line_bad_2_string = "x x";
+
+static void
+test_ether_line_bad_2(void)
+{
+ struct ether_addr e;
+ char hostname[256];
+
+ testnum++;
+ if (ether_line(ether_line_bad_2_string, &e, hostname) == 0)
+ NOTOK("returned success");
+ OK();
+}
+
+static const char *ether_aton_string = "01:23:45:67:89:ab";
+static const struct ether_addr ether_aton_addr = {
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab }
+};
+
+static void
+test_ether_aton_r(void)
+{
+ struct ether_addr e, *ep;
+
+ testnum++;
+ ep = ether_aton_r(ether_aton_string, &e);
+ if (ep == NULL)
+ NOTOK("returned NULL");
+ if (ep != &e)
+ NOTOK("returned different pointer");
+ if (bcmp(&e, &ether_aton_addr, ETHER_ADDR_LEN) != 0)
+ NOTOK("bad address");
+ OK();
+}
+
+static const char *ether_aton_bad_string = "x";
+
+static void
+test_ether_aton_r_bad(void)
+{
+ struct ether_addr e, *ep;
+
+ testnum++;
+ ep = ether_aton_r(ether_aton_bad_string, &e);
+ if (ep == &e)
+ NOTOK("returned success");
+ if (ep != NULL)
+ NOTOK("returned different pointer");
+ OK();
+}
+
+static void
+test_ether_aton(void)
+{
+ struct ether_addr *ep;
+
+ testnum++;
+ ep = ether_aton(ether_aton_string);
+ if (ep == NULL)
+ NOTOK("returned NULL");
+ if (bcmp(ep, &ether_aton_addr, ETHER_ADDR_LEN) != 0)
+ NOTOK("bad address");
+ OK();
+}
+
+static void
+test_ether_aton_bad(void)
+{
+ struct ether_addr *ep;
+
+ testnum++;
+ ep = ether_aton(ether_aton_bad_string);
+ if (ep != NULL)
+ NOTOK("returned success");
+ OK();
+}
+
+static const char *ether_ntoa_string = "01:23:45:67:89:ab";
+static const struct ether_addr ether_ntoa_addr = {
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab }
+};
+
+static void
+test_ether_ntoa_r(void)
+{
+ char buf[256], *cp;
+
+ testnum++;
+ cp = ether_ntoa_r(&ether_ntoa_addr, buf);
+ if (cp == NULL)
+ NOTOK("returned NULL");
+ if (cp != buf)
+ NOTOK("returned different pointer");
+ if (strcmp(cp, ether_ntoa_string) != 0)
+ NOTOK("bad string");
+ OK();
+}
+
+static void
+test_ether_ntoa(void)
+{
+ char *cp;
+
+ testnum++;
+ cp = ether_ntoa(&ether_ntoa_addr);
+ if (cp == NULL)
+ NOTOK("returned NULL");
+ if (strcmp(cp, ether_ntoa_string) != 0)
+ NOTOK("bad string");
+ OK();
+}
+
+static void
+test_ether_ntohost(void)
+{
+
+ testnum++;
+ TODO();
+}
+
+static void
+test_ether_hostton(void)
+{
+
+ testnum++;
+ TODO();
+}
+
+int
+main(int argc, char *argv[])
+{
+
+ printf("1..11\n");
+
+ test_ether_line();
+ test_ether_line_bad_1();
+ test_ether_line_bad_2();
+ test_ether_aton_r();
+ test_ether_aton_r_bad();
+ test_ether_aton();
+ test_ether_aton_bad();
+ test_ether_ntoa_r();
+ test_ether_ntoa();
+ test_ether_ntohost();
+ test_ether_hostton();
+ return (0);
+}
diff --git a/tools/regression/lib/libc/net/test-ether.t b/tools/regression/lib/libc/net/test-ether.t
new file mode 100644
index 0000000..8bdfd03
--- /dev/null
+++ b/tools/regression/lib/libc/net/test-ether.t
@@ -0,0 +1,10 @@
+#!/bin/sh
+# $FreeBSD$
+
+cd `dirname $0`
+
+executable=`basename $0 .t`
+
+make $executable 2>&1 > /dev/null
+
+exec ./$executable
diff --git a/tools/regression/lib/libc/net/test-eui64.h b/tools/regression/lib/libc/net/test-eui64.h
new file mode 100644
index 0000000..ea82a10
--- /dev/null
+++ b/tools/regression/lib/libc/net/test-eui64.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2004 The Aerospace Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions, and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of The Aerospace Corporation may not be used to endorse or
+ * promote products derived from this software.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AEROSPACE CORPORATION "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AEROSPACE CORPORATION BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _TEST_EUI64_H
+#define _TEST_EUI64_H
+
+struct eui64 test_eui64_id = {{0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77}};
+struct eui64 test_eui64_eui48 = {{0x00,0x11,0x22,0xFF,0xFE,0x33,0x44,0x55}};
+struct eui64 test_eui64_mac48 = {{0x00,0x11,0x22,0xFF,0xFF,0x33,0x44,0x55}};
+
+#define test_eui64_id_ascii "00-11-22-33-44-55-66-77"
+#define test_eui64_id_colon_ascii "00:11:22:33:44:55:66:77"
+#define test_eui64_hex_ascii "0x0011223344556677"
+#define test_eui64_eui48_ascii "00-11-22-ff-fe-33-44-55"
+#define test_eui64_mac48_ascii "00-11-22-ff-fe-33-44-55"
+#define test_eui64_mac_ascii "00-11-22-33-44-55"
+#define test_eui64_mac_colon_ascii "00:11:22:33:44:55"
+#define test_eui64_id_host "id"
+#define test_eui64_eui48_host "eui-48"
+#define test_eui64_mac48_host "mac-48"
+
+#define test_eui64_line_id "00-11-22-33-44-55-66-77 id"
+#define test_eui64_line_id_colon "00:11:22:33:44:55:66:77 id"
+#define test_eui64_line_eui48 "00-11-22-FF-fe-33-44-55 eui-48"
+#define test_eui64_line_mac48 "00-11-22-FF-ff-33-44-55 mac-48"
+#define test_eui64_line_eui48_6byte "00-11-22-33-44-55 eui-48"
+#define test_eui64_line_eui48_6byte_c "00:11:22:33:44:55 eui-48"
+
+#endif /* !_TEST_EUI64_H */
diff --git a/tools/regression/lib/libc/net/test-eui64_aton.c b/tools/regression/lib/libc/net/test-eui64_aton.c
new file mode 100644
index 0000000..e10f985
--- /dev/null
+++ b/tools/regression/lib/libc/net/test-eui64_aton.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2004 The Aerospace Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions, and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of The Aerospace Corporation may not be used to endorse or
+ * promote products derived from this software.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AEROSPACE CORPORATION "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AEROSPACE CORPORATION BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/types.h>
+#include <sys/eui64.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "test-eui64.h"
+
+static int
+test_str( const char *str, const struct eui64 *eui)
+{
+ struct eui64 e;
+ char buf[EUI64_SIZ];
+ static int test = 0;
+
+ test++;
+
+ if (eui64_aton(str, &e) != 0 &&
+ memcmp(&e, &eui, sizeof(struct eui64)) != 0) {
+ printf("not ok %d - : eui64_aton(%s)\n", test, str);
+ eui64_ntoa(&e, buf, sizeof(buf));
+ printf("# got: %s\n", buf);
+ return (0);
+ } else {
+ printf("ok %d - eui64_aton(%s)\n", test, str);
+ return (1);
+ }
+
+}
+
+int
+main(int argc, char **argv)
+{
+
+ printf("1..5\n");
+
+ test_str(test_eui64_id_ascii, &test_eui64_id);
+ test_str(test_eui64_id_colon_ascii, &test_eui64_id);
+ test_str(test_eui64_mac_ascii, &test_eui64_eui48);
+ test_str(test_eui64_mac_colon_ascii, &test_eui64_eui48);
+ test_str(test_eui64_hex_ascii, &test_eui64_id);
+
+ return (0);
+}
diff --git a/tools/regression/lib/libc/net/test-eui64_aton.t b/tools/regression/lib/libc/net/test-eui64_aton.t
new file mode 100644
index 0000000..8bdfd03
--- /dev/null
+++ b/tools/regression/lib/libc/net/test-eui64_aton.t
@@ -0,0 +1,10 @@
+#!/bin/sh
+# $FreeBSD$
+
+cd `dirname $0`
+
+executable=`basename $0 .t`
+
+make $executable 2>&1 > /dev/null
+
+exec ./$executable
diff --git a/tools/regression/lib/libc/net/test-eui64_line.c b/tools/regression/lib/libc/net/test-eui64_line.c
new file mode 100644
index 0000000..714b460
--- /dev/null
+++ b/tools/regression/lib/libc/net/test-eui64_line.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2004 The Aerospace Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions, and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of The Aerospace Corporation may not be used to endorse or
+ * promote products derived from this software.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AEROSPACE CORPORATION "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AEROSPACE CORPORATION BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/types.h>
+#include <sys/eui64.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "test-eui64.h"
+
+static int
+test_line(const char *line, const struct eui64 *eui, const char *host)
+{
+ struct eui64 e;
+ char buf[256];
+ static int test = 0;
+
+ test++;
+
+ if (eui64_line(line, &e, buf, sizeof(buf)) != 0 ||
+ memcmp(&e, eui, sizeof(struct eui64)) != 0 ||
+ strcmp(buf, host) != 0) {
+ printf("not ok %d - eui64_line(\"%s\")\n", test, line);
+ printf("# host = %s\n", buf);
+ eui64_ntoa(&e, buf, sizeof(buf));
+ printf("# e = %s\n", buf);
+ return (0);
+ } else {
+ printf("ok %d - eui64_line(\"%s\")\n", test, line);
+ return (1);
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+
+ printf("1..6\n");
+
+ test_line(test_eui64_line_id, &test_eui64_id,
+ test_eui64_id_host);
+ test_line(test_eui64_line_id_colon, &test_eui64_id,
+ test_eui64_id_host);
+ test_line(test_eui64_line_eui48, &test_eui64_eui48,
+ test_eui64_eui48_host);
+ test_line(test_eui64_line_mac48, &test_eui64_mac48,
+ test_eui64_mac48_host);
+ test_line(test_eui64_line_eui48_6byte, &test_eui64_eui48,
+ test_eui64_eui48_host);
+ test_line(test_eui64_line_eui48_6byte_c, &test_eui64_eui48,
+ test_eui64_eui48_host);
+
+ return (0);
+}
diff --git a/tools/regression/lib/libc/net/test-eui64_line.t b/tools/regression/lib/libc/net/test-eui64_line.t
new file mode 100644
index 0000000..8bdfd03
--- /dev/null
+++ b/tools/regression/lib/libc/net/test-eui64_line.t
@@ -0,0 +1,10 @@
+#!/bin/sh
+# $FreeBSD$
+
+cd `dirname $0`
+
+executable=`basename $0 .t`
+
+make $executable 2>&1 > /dev/null
+
+exec ./$executable
diff --git a/tools/regression/lib/libc/net/test-eui64_ntoa.c b/tools/regression/lib/libc/net/test-eui64_ntoa.c
new file mode 100644
index 0000000..f7582f0
--- /dev/null
+++ b/tools/regression/lib/libc/net/test-eui64_ntoa.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2004 The Aerospace Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions, and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of The Aerospace Corporation may not be used to endorse or
+ * promote products derived from this software.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AEROSPACE CORPORATION "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AEROSPACE CORPORATION BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/types.h>
+#include <sys/eui64.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "test-eui64.h"
+
+int
+main(int argc, char **argv)
+{
+ char a[EUI64_SIZ];
+
+ printf("1..1\n");
+
+ if (eui64_ntoa(&test_eui64_id, a, sizeof(a)) == 0 &&
+ strcmp(a, test_eui64_id_ascii) == 0) {
+ printf("ok 1 - eui64_ntoa\n");
+ return (0);
+ }
+ printf("# a = '%s'\n", a);
+
+ printf("not ok 1 - eui64_ntoa\n");
+ return (0);
+}
diff --git a/tools/regression/lib/libc/net/test-eui64_ntoa.t b/tools/regression/lib/libc/net/test-eui64_ntoa.t
new file mode 100644
index 0000000..8bdfd03
--- /dev/null
+++ b/tools/regression/lib/libc/net/test-eui64_ntoa.t
@@ -0,0 +1,10 @@
+#!/bin/sh
+# $FreeBSD$
+
+cd `dirname $0`
+
+executable=`basename $0 .t`
+
+make $executable 2>&1 > /dev/null
+
+exec ./$executable
diff --git a/tools/regression/lib/libc/nss/Makefile b/tools/regression/lib/libc/nss/Makefile
new file mode 100644
index 0000000..8c8a514
--- /dev/null
+++ b/tools/regression/lib/libc/nss/Makefile
@@ -0,0 +1,12 @@
+# $FreeBSD$
+
+TESTS= test-getaddr test-getgr test-gethostby test-getpw test-getproto\
+ test-getrpc test-getserv test-getusershell
+CFLAGS+= -g -Wall
+
+.PHONY: tests
+tests: ${TESTS}
+
+.PHONY: clean
+clean:
+ -rm -f ${TESTS}
diff --git a/tools/regression/lib/libc/nss/README b/tools/regression/lib/libc/nss/README
new file mode 100644
index 0000000..ba0373d
--- /dev/null
+++ b/tools/regression/lib/libc/nss/README
@@ -0,0 +1,203 @@
+$FreeBSD$
+
+A brief how-to
+--------------
+
+Each nsswitch regression test does 2 kinds of actions:
+1. It runs a series of queries and tests the correctness of results.
+ There are 2 basic criterias which are used for that:
+ - numbers must be in the correct range
+ - certain pointers should not be NULL
+
+2. It makes a snapshot of the results of all queries that were made.
+ The idea of snapshots is to test that nsswitch-related function
+ calls behave equally (i.e. return same results for the same queries)
+ between system upgrades. When the test is executed and the snapshot is
+ already created, the test will compare the result of each query with
+ the appropriate result from the snapshot and will signal if they
+ differ.
+
+In order for nsswitch tests to be as useful as possible you should use
+them in the following way:
+
+Step 1 (before upgrading your system).
+Build the tests with "make" command and execute them with "prove -v"
+command. If there are errors during the execution, then appropriate
+nsswitch functions should be checked. Note, that errors on this state
+can happen only if the particular function return incorrect data.
+
+After the stage 1 a number of "snapshot_[test name]" files will appear
+in your test folder.
+
+Step 2 (after upgrading you system).
+Rebuild the tests with "make clean; make" command and execute them
+again with "prove -v" (check that "snapshot_[test name]" files
+are in the same folder with tests). On this stage regression tests
+will catch not only the correctness errors, but will also determine
+the changes in nsswitch functions behaviour.
+
+In case of the test failure you will get the following message:
+
+To get more details about the error you should do the following:
+Step 1. Run the test alone with debug output enabled.
+Step 2. Mail the snapshot file and the debug test output to the
+freebsd-current@ mailing list.
+
+Example testing session for getpwXXX() family of functions
+----------------------------------------------------------
+1. make
+
+2. prove -v ./test-getpw.t
+
+ test-getpw....1..8
+ ok 1 - getpwnam()
+ ok 2 - getpwuid()
+ ok 3 - getpwent()
+ ok 4 - getpwent() 2-pass
+ ok 5 - building snapshot, if needed
+ ok 6 - getpwnam() snapshot
+ ok 7 - getpwuid() snapshot
+ ok 8 - getpwent() snapshot
+ ok
+ All tests successful.
+ Files=1, Tests=8, 1 wallclock secs ( 0.00 cusr + 0.20 csys = 0.20 CPU)
+
+
+3. Upgrading the system.
+
+4. make clean; make
+
+5. prove -v ./test-getpw.t (suppose that something has gone wrong)
+
+ test-getpw....1..8
+ ok 1 - getpwnam()
+ ok 2 - getpwuid()
+ ok 3 - getpwent()
+ ok 4 - getpwent() 2-pass
+ ok 5 - building snapshot, if needed
+ not ok 6 - getpwnam() snapshot
+ ok 7 - getpwuid() snapshot
+ not ok 8 - getpwent() snapshot
+ FAILED tests 6, 8
+ Failed 2/8 tests, 75.00% okay
+ Failed 1/1 test scripts, 0.00% okay. 2/8 subtests failed, 75.00% okay.
+
+6. We see that test number 6 failed. According to get-getpw.t, this test
+ is executed like this:
+ do_test 6 'getpwnam() snapshot' '-n -s snapshot_pwd'
+
+ To determine why the test has failed, we need to run it in debug mode -
+ it means adding "-d" to the options list.
+
+7. ./test-getpw -dn -s snapshot_pwd
+ ...
+ testing getpwnam() with the following data:
+ toor:*:0:0:0::ne-again Superuser:/root::0:4831
+ testing correctness with the following data:
+ toor:*:0:0:0::Bourne-again Superuser:/root::0:4831
+ correct
+ not ok
+
+8. Here we can see that the data from snapshot (first "toor" line) and
+ the data received from the getpwnam() call (second "toor" line) are
+ different. It is the reason why the test has failed. If you can't
+ (or don't want) to investigate the problem by yourself, mail
+ the test debug output and the snapshot file to the developers list.
+
+Notes on using standalone nsswitch tests
+----------------------------------------
+
+All nsswitch tests have [-d] optional command line argument which enables
+debug output. The debug output can be extremely helpful to determine the
+cause of test failure.
+
+In all nsswitch tests -s <file> command line argument specifies the
+snapshot file. If this file doesn't exist, it would be built during
+test execution. If it already exists then it will be used to check
+the results of particular function calls. This argument is mostly
+optional, but some tests (test-getaddr and test-getusershell) force
+it to be specified.
+
+test-gethostby and test-getaddr require the list of hostnames, that should
+be queried during the test. This list must be specified via -f <file>
+command line argument. Each hostname should occupy exactly one line
+in the file.
+
+Detailed tests description
+--------------------------
+
+./test-getaddr - tests the getaddrinfo() function.
+ Usage: test-getaddr [-d] [-46] [-s <file>] -f <file>
+ -d - enable debug output
+ -4 - force IPv4 usage
+ -6 - force IPv6 usage
+ -s - build/use specified snapshot file
+ -f - use specified hostnames list for testing
+
+./test-getgr
+ Usage: test-getgr -nge2 [-d] [-s <file>]
+ -d - enable debug output
+ -n - test getgrnam(3)
+ -g - test getgrgid(3)
+ -e - test getgrent(3)
+ -2 - test getgrent(3) in 2-pass mode
+ -s - build/use specified snapshot file
+
+./test-gethostby
+ Usage: test-gethostby -na2i [-o] [-d] [-m46] [-s <file>] -f <file>
+ -n - test gethostbyname2(3)
+ -a - test gethostbyaddr(3)
+ -2 - test gethostbyname2(3) results to be equal with getaddrinfo(3)
+ results for the similar query
+ -i - test gethostbyaddr(3) results to be equal with getnameinfo(3)
+ results for the similar query
+ -o - use getipnodebyname(3)/getipnodebyaddr(3) for testing instead of
+ gethostbyname2(3)/gethostbyaddr(3)
+ -d - enable debug output
+ -m - force IPv4-to-IPv6 mapping
+ -4 - force IPv4 usage
+ -6 - force IPv6 usage
+ -s - build/use specified snapshot file
+ -f - use specified hostnames list for testing
+
+./test-getproto
+ Usage: test-getproto -nve2 [-d] [-s <file>]
+ -d - enable debug output
+ -n - test getprotobyname(3)
+ -v - test getprotobynumber(3)
+ -e - test getprotoent(3)
+ -2 - test getprotoent(3) in 2-pass mode
+ -s - build/use specified snapshot file
+
+./test-getpw
+ Usage: test-getpw -nue2 [-d] [-s <file>]
+ -d - enable debug output
+ -n - test getpwnam(3)
+ -u - test getpwuid(3)
+ -e - test getpwent(3)
+ -2 - test getpwent(3) in 2-pass mode
+ -s - build/use snapshot file
+
+./test-getrpc
+ Usage: test-getrpc -nve2 [-d] [-s <file>]
+ -d - enable debug output
+ -n - test getrpcbyname(3)
+ -v - test getrpcbynumber(3)
+ -e - test getrpcent(3)
+ -2 - test getrpcent(3) in 2-pass mode
+ -s - build/use specified snapshot file
+
+./test-getserv
+ Usage: test-getserv -npe2 [-d] [-s <file>]
+ -d - enable debug output
+ -n - test getservbyname(3)
+ -p - test getservbyport(3)
+ -e - test getservent(3)
+ -2 - test getservent(3) in 2-pass mode
+ -s - build/use specified snapshot file
+
+./test-getusershell
+ Usage: test-getusershell [-d] -s <file>
+ -d - enable debug output
+ -s - build/use specified snapshot file
+
diff --git a/tools/regression/lib/libc/nss/mach b/tools/regression/lib/libc/nss/mach
new file mode 100644
index 0000000..d25d8d6
--- /dev/null
+++ b/tools/regression/lib/libc/nss/mach
@@ -0,0 +1,94 @@
+# $FreeBSD$
+localhost
+above.warped.net
+anoncvs.cirr.com
+anoncvs.isc.netbsd.org
+anoncvs.leo.org
+anoncvs.netbsd.lt
+anoncvs.netbsd.ro
+anoncvs.netbsd.se
+antioche.antioche.eu.org
+boulder.tele.dk
+centaurus.4web.cz
+chur.math.ntnu.no
+cnftp.bjpu.edu.cn
+console.netbsd.org
+cvs.fi.netbsd.org
+cvs.mikrolahti.fi
+cvs.netbsd.org
+cvsup-netbsd.leo.org
+cvsup.netbsd.se
+cvsup.pasta.cs.uit.no
+ftp.bitcon.no
+ftp.chg.ru
+ftp.duth.gr
+ftp.estpak.ee
+ftp.fsn.hu
+ftp.funet.fi
+ftp.grondar.za
+ftp.leo.org
+ftp.netbsd.lt
+ftp.netbsd.org
+ftp.nluug.nl
+ftp.plig.org
+ftp.uni-erlangen.de
+ftp.xgate.co.kr
+gd.tuwien.ac.at
+gort.ludd.luth.se
+grappa.unix-ag.uni-kl.de
+info.wins.uva.nl
+irc.warped.net
+knug.youn.co.kr
+lala.iri.co.jp
+mail.jp.netbsd.org
+mail.kr.netbsd.org
+mail.netbsd.org
+melanoma.cs.rmit.edu.au
+mirror.aarnet.edu.au
+mirror.netbsd.com.br
+mirror03.inet.tele.dk
+moon.vub.ac.be
+nbwww.sergei.cc
+net.bsd.cz
+netbsd.3miasto.net
+netbsd.4ka.mipt.ru
+netbsd.apk.od.ua
+netbsd.csie.nctu.edu.tw
+netbsd.enderunix.org
+netbsd.ftp.fu-berlin.de
+netbsd.netlead.com.au
+netbsd.nsysu.edu.tw
+netbsd.pair.com
+netbsd.stevens-tech.edu
+netbsd.triada.bg
+netbsd.unix.net.nz
+netbsd.unixtech.be
+netbsd.vejas.lt
+netbsd.wagener-consulting.lu
+netbsd.zarco.org
+netbsdiso.interoute.net.uk
+netbsdwww.bitcon.no
+netbsdwww.cordef.com.pl
+netbsdwww.cs.rmit.edu.au
+netbsdwww.interoute.net.uk
+news.gw.com
+ns.netbsd.org
+pigu.iri.co.jp
+pluto.cdpa.nsysu.edu.tw
+projects.slowass.net
+server6.pasta.cs.uit.no
+skeleton.phys.spbu.ru
+snoopy.allbsd.org
+spike.allbsd.org
+sundry.netbsd.org
+tanya.sergei.cc
+web-a.fi.gw.com
+web-a.us.gw.com
+web.netbsd.mirror.arhea.net
+www.en.netbsd.de
+www.netbsd.cl
+www.netbsd.nl
+www.netbsd.org
+www.netbsd.ro
+zathras.netbsd.org
+zeppo.rediris.es
diff --git a/tools/regression/lib/libc/nss/test-getaddr.c b/tools/regression/lib/libc/nss/test-getaddr.c
new file mode 100644
index 0000000..046d9db
--- /dev/null
+++ b/tools/regression/lib/libc/nss/test-getaddr.c
@@ -0,0 +1,538 @@
+/*-
+ * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org>
+ * All rights rehted.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <assert.h>
+#include <errno.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stringlist.h>
+#include <unistd.h>
+#include "testutil.h"
+
+enum test_methods {
+ TEST_GETADDRINFO,
+ TEST_BUILD_SNAPSHOT
+};
+
+static int debug = 0;
+static struct addrinfo hints;
+static enum test_methods method = TEST_GETADDRINFO;
+
+DECLARE_TEST_DATA(addrinfo)
+DECLARE_TEST_FILE_SNAPSHOT(addrinfo)
+DECLARE_2PASS_TEST(addrinfo)
+
+static void clone_addrinfo(struct addrinfo *, struct addrinfo const *);
+static int compare_addrinfo(struct addrinfo *, struct addrinfo *, void *);
+static void dump_addrinfo(struct addrinfo *);
+static void free_addrinfo(struct addrinfo *);
+
+static void sdump_addrinfo(struct addrinfo *, char *, size_t);
+
+IMPLEMENT_TEST_DATA(addrinfo)
+IMPLEMENT_TEST_FILE_SNAPSHOT(addrinfo)
+IMPLEMENT_2PASS_TEST(addrinfo)
+
+static void
+clone_addrinfo(struct addrinfo *dest, struct addrinfo const *src)
+{
+ assert(dest != NULL);
+ assert(src != NULL);
+
+ memcpy(dest, src, sizeof(struct addrinfo));
+ if (src->ai_canonname != NULL)
+ dest->ai_canonname = strdup(src->ai_canonname);
+
+ if (src->ai_addr != NULL) {
+ dest->ai_addr = (struct sockaddr *)malloc(src->ai_addrlen);
+ assert(dest->ai_addr != NULL);
+ memcpy(dest->ai_addr, src->ai_addr, src->ai_addrlen);
+ }
+
+ if (src->ai_next != NULL) {
+ dest->ai_next = (struct addrinfo *)malloc(
+ sizeof(struct addrinfo));
+ assert(dest->ai_next != NULL);
+ clone_addrinfo(dest->ai_next, src->ai_next);
+ }
+}
+
+static int
+compare_addrinfo_(struct addrinfo *ai1, struct addrinfo *ai2)
+{
+ if ((ai1 == NULL) || (ai2 == NULL))
+ return (-1);
+
+ if ((ai1->ai_flags != ai2->ai_flags) ||
+ (ai1->ai_family != ai2->ai_family) ||
+ (ai1->ai_socktype != ai2->ai_socktype) ||
+ (ai1->ai_protocol != ai2->ai_protocol) ||
+ (ai1->ai_addrlen != ai2->ai_addrlen) ||
+ (((ai1->ai_addr == NULL) || (ai2->ai_addr == NULL)) &&
+ (ai1->ai_addr != ai2->ai_addr)) ||
+ (((ai1->ai_canonname == NULL) || (ai2->ai_canonname == NULL)) &&
+ (ai1->ai_canonname != ai2->ai_canonname)))
+ return (-1);
+
+ if ((ai1->ai_canonname != NULL) &&
+ (strcmp(ai1->ai_canonname, ai2->ai_canonname) != 0))
+ return (-1);
+
+ if ((ai1->ai_addr != NULL) &&
+ (memcmp(ai1->ai_addr, ai2->ai_addr, ai1->ai_addrlen) != 0))
+ return (-1);
+
+ if ((ai1->ai_next == NULL) && (ai2->ai_next == NULL))
+ return (0);
+ else
+ return (compare_addrinfo_(ai1->ai_next, ai2->ai_next));
+}
+
+static int
+compare_addrinfo(struct addrinfo *ai1, struct addrinfo *ai2, void *mdata)
+{
+ int rv;
+
+ if (debug) {
+ printf("testing equality of 2 addrinfo structures\n");
+ }
+
+ rv = compare_addrinfo_(ai1, ai2);
+
+ if (debug) {
+ if (rv == 0)
+ printf("equal\n");
+ else {
+ dump_addrinfo(ai1);
+ dump_addrinfo(ai2);
+ printf("not equal\n");
+ }
+ }
+
+ return (rv);
+}
+
+void
+free_addrinfo(struct addrinfo *ai)
+{
+ if (ai == NULL)
+ return;
+
+ free(ai->ai_addr);
+ free(ai->ai_canonname);
+ free_addrinfo(ai->ai_next);
+}
+
+void
+sdump_addrinfo(struct addrinfo *ai, char *buffer, size_t buflen)
+{
+ int written, i;
+
+ written = snprintf(buffer, buflen, "%d %d %d %d %d ",
+ ai->ai_flags, ai->ai_family, ai->ai_socktype, ai->ai_protocol,
+ ai->ai_addrlen);
+ buffer += written;
+ if (written > buflen)
+ return;
+ buflen -= written;
+
+ written = snprintf(buffer, buflen, "%s ",
+ ai->ai_canonname == NULL ? "(null)" : ai->ai_canonname);
+ buffer += written;
+ if (written > buflen)
+ return;
+ buflen -= written;
+
+ if (ai->ai_addr == NULL) {
+ written = snprintf(buffer, buflen, "(null)");
+ buffer += written;
+ if (written > buflen)
+ return;
+ buflen -= written;
+ } else {
+ for (i = 0; i < ai->ai_addrlen; ++i ) {
+ written = snprintf(buffer, buflen,
+ i + 1 != ai->ai_addrlen ? "%d." : "%d",
+ ((unsigned char *)ai->ai_addr)[i]);
+ buffer += written;
+ if (written > buflen)
+ return;
+ buflen -= written;
+
+ if (buflen == 0)
+ return;
+ }
+ }
+
+ if (ai->ai_next != NULL) {
+ written = snprintf(buffer, buflen, ":");
+ buffer += written;
+ if (written > buflen)
+ return;
+ buflen -= written;
+
+ sdump_addrinfo(ai->ai_next, buffer, buflen);
+ }
+}
+
+void
+dump_addrinfo(struct addrinfo *result)
+{
+ if (result != NULL) {
+ char buffer[2048];
+ sdump_addrinfo(result, buffer, sizeof(buffer));
+ printf("%s\n", buffer);
+ } else
+ printf("(null)\n");
+}
+
+static int
+addrinfo_read_snapshot_addr(char *addr, unsigned char *result, size_t len)
+{
+ char *s, *ps, *ts;
+
+ ps = addr;
+ while ( (s = strsep(&ps, ".")) != NULL) {
+ if (len == 0)
+ return (-1);
+
+ *result = (unsigned char)strtol(s, &ts, 10);
+ ++result;
+ if (*ts != '\0')
+ return (-1);
+
+ --len;
+ }
+ if (len != 0)
+ return (-1);
+ else
+ return (0);
+}
+
+static int
+addrinfo_read_snapshot_ai(struct addrinfo *ai, char *line)
+{
+ char *s, *ps, *ts;
+ int i, rv, *pi;
+
+ rv = 0;
+ i = 0;
+ ps = line;
+ memset(ai, 0, sizeof(struct addrinfo));
+ while ( (s = strsep(&ps, " ")) != NULL) {
+ switch (i) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ pi = &ai->ai_flags + i;
+ *pi = (int)strtol(s, &ts, 10);
+ if (*ts != '\0')
+ goto fin;
+ break;
+ case 4:
+ ai->ai_addrlen = (socklen_t)strtol(s, &ts, 10);
+ if (*ts != '\0')
+ goto fin;
+ break;
+ case 5:
+ if (strcmp(s, "(null)") != 0) {
+ ai->ai_canonname = strdup(s);
+ assert(ai->ai_canonname != NULL);
+ }
+ break;
+ case 6:
+ if (strcmp(s, "(null)") != 0) {
+ ai->ai_addr = (struct sockaddr *)malloc(
+ ai->ai_addrlen);
+ assert(ai->ai_addr != NULL);
+ memset(ai->ai_addr, 0, ai->ai_addrlen);
+ rv = addrinfo_read_snapshot_addr(s,
+ (unsigned char *)ai->ai_addr,
+ ai->ai_addrlen);
+
+ if (rv != 0)
+ goto fin;
+ }
+ break;
+ default:
+ /* NOTE: should not be reachable */
+ rv = -1;
+ goto fin;
+ };
+
+ ++i;
+ }
+
+fin:
+ if ((i != 7) || (rv != 0)) {
+ free_addrinfo(ai);
+ memset(ai, 0, sizeof(struct addrinfo));
+ return (-1);
+ }
+
+ return (0);
+}
+
+static int
+addrinfo_read_snapshot_func(struct addrinfo *ai, char *line)
+{
+ struct addrinfo *ai2;
+ char *s, *ps;
+ int i, rv;
+
+ if (debug)
+ printf("1 line read from snapshot:\n%s\n", line);
+
+ rv = 0;
+ i = 0;
+ ps = line;
+
+ s = strsep(&ps, ":");
+ if (s == NULL)
+ return (-1);
+
+ rv = addrinfo_read_snapshot_ai(ai, s);
+ if (rv != 0)
+ return (-1);
+
+ ai2 = ai;
+ while ( (s = strsep(&ps, ":")) != NULL) {
+ ai2->ai_next = (struct addrinfo *)malloc(
+ sizeof(struct addrinfo));
+ assert(ai2->ai_next != NULL);
+ memset(ai2->ai_next, 0, sizeof(struct addrinfo));
+
+ rv = addrinfo_read_snapshot_ai(ai2->ai_next, s);
+ if (rv != 0) {
+ free_addrinfo(ai);
+ return (-1);
+ }
+
+ ai2 = ai2->ai_next;
+ }
+
+ return (0);
+}
+
+static int
+addrinfo_test_correctness(struct addrinfo *ai, void *mdata)
+{
+ if (debug) {
+ printf("testing correctness with the following data:\n");
+ dump_addrinfo(ai);
+ }
+
+ if (ai == NULL)
+ goto errfin;
+
+ if (!((ai->ai_family >= 0) && (ai->ai_family < AF_MAX)))
+ goto errfin;
+
+ if ((ai->ai_socktype != 0) && (ai->ai_socktype != SOCK_STREAM) &&
+ (ai->ai_socktype != SOCK_DGRAM) && (ai->ai_socktype != SOCK_RAW))
+ goto errfin;
+
+ if ((ai->ai_protocol != 0) && (ai->ai_protocol != IPPROTO_UDP) &&
+ (ai->ai_protocol != IPPROTO_TCP))
+ goto errfin;
+
+ if ((ai->ai_flags & ~(AI_CANONNAME | AI_NUMERICHOST | AI_PASSIVE)) != 0)
+ goto errfin;
+
+ if ((ai->ai_addrlen != ai->ai_addr->sa_len) ||
+ (ai->ai_family != ai->ai_addr->sa_family))
+ goto errfin;
+
+ if (debug)
+ printf("correct\n");
+
+ return (0);
+errfin:
+ if (debug)
+ printf("incorrect\n");
+
+ return (-1);
+}
+
+static int
+addrinfo_read_hostlist_func(struct addrinfo *ai, char *line)
+{
+ struct addrinfo *result;
+ int rv;
+
+ if (debug)
+ printf("resolving %s: ", line);
+ rv = getaddrinfo(line, NULL, &hints, &result);
+ if (rv == 0) {
+ if (debug)
+ printf("found\n");
+
+ rv = addrinfo_test_correctness(result, NULL);
+ if (rv != 0) {
+ freeaddrinfo(result);
+ return (rv);
+ }
+
+ clone_addrinfo(ai, result);
+ freeaddrinfo(result);
+ } else {
+ if (debug)
+ printf("not found\n");
+
+ memset(ai, 0, sizeof(struct addrinfo));
+ }
+ return (0);
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr,
+ "Usage: %s [-d] [-46] [-s <file]> -f <file>\n",
+ getprogname());
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ struct addrinfo_test_data td, td_snap;
+ char *snapshot_file, *hostlist_file;
+ int rv;
+ int c;
+
+ if (argc < 2)
+ usage();
+
+ snapshot_file = NULL;
+ hostlist_file = NULL;
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_flags = AI_CANONNAME;
+ while ((c = getopt(argc, argv, "46dns:f:")) != -1)
+ switch (c) {
+ case '4':
+ hints.ai_family = PF_INET;
+ case '6':
+ hints.ai_family = PF_INET6;
+ break;
+ case 'd':
+ debug = 1;
+ break;
+ case 's':
+ snapshot_file = strdup(optarg);
+ method = TEST_BUILD_SNAPSHOT;
+ break;
+ case 'f':
+ hostlist_file = strdup(optarg);
+ break;
+ default:
+ usage();
+ }
+
+ TEST_DATA_INIT(addrinfo, &td, clone_addrinfo, free_addrinfo);
+ TEST_DATA_INIT(addrinfo, &td_snap, clone_addrinfo, free_addrinfo);
+
+ if (hostlist_file == NULL)
+ usage();
+
+ if (access(hostlist_file, R_OK) != 0) {
+ if (debug)
+ printf("can't access the hostlist file %s\n",
+ hostlist_file);
+
+ usage();
+ }
+
+ if (debug)
+ printf("building host lists from %s\n", hostlist_file);
+
+ rv = TEST_SNAPSHOT_FILE_READ(addrinfo, hostlist_file, &td,
+ addrinfo_read_hostlist_func);
+ if (rv != 0)
+ goto fin;
+
+ if (snapshot_file != NULL) {
+ if (access(snapshot_file, W_OK | R_OK) != 0) {
+ if (errno == ENOENT)
+ method = TEST_BUILD_SNAPSHOT;
+ else {
+ if (debug)
+ printf("can't access the snapshot file %s\n",
+ snapshot_file);
+
+ rv = -1;
+ goto fin;
+ }
+ } else {
+ rv = TEST_SNAPSHOT_FILE_READ(addrinfo, snapshot_file,
+ &td_snap, addrinfo_read_snapshot_func);
+ if (rv != 0) {
+ if (debug)
+ printf("error reading snapshot file\n");
+ goto fin;
+ }
+ }
+ }
+
+ switch (method) {
+ case TEST_GETADDRINFO:
+ if (snapshot_file != NULL)
+ rv = DO_2PASS_TEST(addrinfo, &td, &td_snap,
+ compare_addrinfo, NULL);
+ break;
+ case TEST_BUILD_SNAPSHOT:
+ if (snapshot_file != NULL) {
+ rv = TEST_SNAPSHOT_FILE_WRITE(addrinfo, snapshot_file, &td,
+ sdump_addrinfo);
+ }
+ break;
+ default:
+ rv = 0;
+ break;
+ };
+
+fin:
+ TEST_DATA_DESTROY(addrinfo, &td_snap);
+ TEST_DATA_DESTROY(addrinfo, &td);
+ free(hostlist_file);
+ free(snapshot_file);
+ return (rv);
+
+}
+
diff --git a/tools/regression/lib/libc/nss/test-getaddr.t b/tools/regression/lib/libc/nss/test-getaddr.t
new file mode 100644
index 0000000..b3020f0
--- /dev/null
+++ b/tools/regression/lib/libc/nss/test-getaddr.t
@@ -0,0 +1,33 @@
+#!/bin/sh
+# $FreeBSD$
+
+do_test() {
+ number=$1
+ comment=$2
+ opt=$3
+ if ./$executable $opt; then
+ echo "ok $number - $comment"
+ else
+ echo "not ok $number - $comment"
+ fi
+}
+
+cd `dirname $0`
+
+executable=`basename $0 .t`
+
+make $executable 2>&1 > /dev/null
+
+echo 1..6
+#Tests with hints.ai_family is set to PF_UNSPEC
+do_test 1 'getaddrinfo() (PF_UNSPEC)' '-f mach'
+do_test 2 'getaddrinfo() snapshot (PF_UNSPEC)' '-f mach -s snapshot_ai'
+
+#Tests with hints.ai_family is set to PF_INET
+do_test 3 'getaddrinfo() (PF_INET)' '-f mach'
+do_test 4 'getaddrinfo() snapshot (PF_INET)' '-4 -f mach -s snapshot_ai4'
+
+#Tests with hints.ai_family is set to PF_INET6
+do_test 5 'getaddrinfo() (PF_INET6)' '-f mach'
+do_test 6 'getaddrinfo() snapshot (PF_INET6)' '-6 -f mach -s snapshot_ai6'
+
diff --git a/tools/regression/lib/libc/nss/test-getgr.c b/tools/regression/lib/libc/nss/test-getgr.c
new file mode 100644
index 0000000..1b573e8
--- /dev/null
+++ b/tools/regression/lib/libc/nss/test-getgr.c
@@ -0,0 +1,534 @@
+/*-
+ * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org>
+ * All rights regrped.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <arpa/inet.h>
+#include <assert.h>
+#include <errno.h>
+#include <grp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stringlist.h>
+#include <unistd.h>
+#include "testutil.h"
+
+enum test_methods {
+ TEST_GETGRENT,
+ TEST_GETGRNAM,
+ TEST_GETGRGID,
+ TEST_GETGRENT_2PASS,
+ TEST_BUILD_SNAPSHOT
+};
+
+static int debug = 0;
+static enum test_methods method = TEST_BUILD_SNAPSHOT;
+
+DECLARE_TEST_DATA(group)
+DECLARE_TEST_FILE_SNAPSHOT(group)
+DECLARE_1PASS_TEST(group)
+DECLARE_2PASS_TEST(group)
+
+static void clone_group(struct group *, struct group const *);
+static int compare_group(struct group *, struct group *, void *);
+static void dump_group(struct group *);
+static void free_group(struct group *);
+
+static void sdump_group(struct group *, char *, size_t);
+static int group_read_snapshot_func(struct group *, char *);
+
+static int group_check_ambiguity(struct group_test_data *,
+ struct group *);
+static int group_fill_test_data(struct group_test_data *);
+static int group_test_correctness(struct group *, void *);
+static int group_test_getgrnam(struct group *, void *);
+static int group_test_getgrgid(struct group *, void *);
+static int group_test_getgrent(struct group *, void *);
+
+static void usage(void) __attribute__((__noreturn__));
+
+IMPLEMENT_TEST_DATA(group)
+IMPLEMENT_TEST_FILE_SNAPSHOT(group)
+IMPLEMENT_1PASS_TEST(group)
+IMPLEMENT_2PASS_TEST(group)
+
+static void
+clone_group(struct group *dest, struct group const *src)
+{
+ assert(dest != NULL);
+ assert(src != NULL);
+
+ char **cp;
+ int members_num;
+
+ memset(dest, 0, sizeof(struct group));
+
+ if (src->gr_name != NULL) {
+ dest->gr_name = strdup(src->gr_name);
+ assert(dest->gr_name != NULL);
+ }
+
+ if (src->gr_passwd != NULL) {
+ dest->gr_passwd = strdup(src->gr_passwd);
+ assert(dest->gr_passwd != NULL);
+ }
+ dest->gr_gid = src->gr_gid;
+
+ if (src->gr_mem != NULL) {
+ members_num = 0;
+ for (cp = src->gr_mem; *cp; ++cp)
+ ++members_num;
+
+ dest->gr_mem = (char **)malloc(
+ (members_num + 1) * (sizeof(char *)));
+ assert(dest->gr_mem != NULL);
+ memset(dest->gr_mem, 0, (members_num+1) * (sizeof(char *)));
+
+ for (cp = src->gr_mem; *cp; ++cp) {
+ dest->gr_mem[cp - src->gr_mem] = strdup(*cp);
+ assert(dest->gr_mem[cp - src->gr_mem] != NULL);
+ }
+ }
+}
+
+static void
+free_group(struct group *grp)
+{
+ char **cp;
+
+ assert(grp != NULL);
+
+ free(grp->gr_name);
+ free(grp->gr_passwd);
+
+ for (cp = grp->gr_mem; *cp; ++cp)
+ free(*cp);
+ free(grp->gr_mem);
+}
+
+static int
+compare_group(struct group *grp1, struct group *grp2, void *mdata)
+{
+ char **c1, **c2;
+
+ if (grp1 == grp2)
+ return (0);
+
+ if ((grp1 == NULL) || (grp2 == NULL))
+ goto errfin;
+
+ if ((strcmp(grp1->gr_name, grp2->gr_name) != 0) ||
+ (strcmp(grp1->gr_passwd, grp2->gr_passwd) != 0) ||
+ (grp1->gr_gid != grp2->gr_gid))
+ goto errfin;
+
+ c1 = grp1->gr_mem;
+ c2 = grp2->gr_mem;
+
+ if ((grp1->gr_mem == NULL) || (grp2->gr_mem == NULL))
+ goto errfin;
+
+ for (;*c1 && *c2; ++c1, ++c2)
+ if (strcmp(*c1, *c2) != 0)
+ goto errfin;
+
+ if ((*c1 != '\0') || (*c2 != '\0'))
+ goto errfin;
+
+ return 0;
+
+errfin:
+ if ((debug) && (mdata == NULL)) {
+ printf("following structures are not equal:\n");
+ dump_group(grp1);
+ dump_group(grp2);
+ }
+
+ return (-1);
+}
+
+static void
+sdump_group(struct group *grp, char *buffer, size_t buflen)
+{
+ char **cp;
+ int written;
+
+ written = snprintf(buffer, buflen, "%s %s %d",
+ grp->gr_name, grp->gr_passwd, grp->gr_gid);
+ buffer += written;
+ if (written > buflen)
+ return;
+ buflen -= written;
+
+ if (grp->gr_mem != NULL) {
+ if (*(grp->gr_mem) != '\0') {
+ for (cp = grp->gr_mem; *cp; ++cp) {
+ written = snprintf(buffer, buflen, " %s",*cp);
+ buffer += written;
+ if (written > buflen)
+ return;
+ buflen -= written;
+
+ if (buflen == 0)
+ return;
+ }
+ } else
+ snprintf(buffer, buflen, " nomem");
+ } else
+ snprintf(buffer, buflen, " (null)");
+}
+
+static int
+group_read_snapshot_func(struct group *grp, char *line)
+{
+ StringList *sl;
+ char *s, *ps, *ts;
+ int i;
+
+ if (debug)
+ printf("1 line read from snapshot:\n%s\n", line);
+
+ i = 0;
+ sl = NULL;
+ ps = line;
+ memset(grp, 0, sizeof(struct group));
+ while ( (s = strsep(&ps, " ")) != NULL) {
+ switch (i) {
+ case 0:
+ grp->gr_name = strdup(s);
+ assert(grp->gr_name != NULL);
+ break;
+
+ case 1:
+ grp->gr_passwd = strdup(s);
+ assert(grp->gr_passwd != NULL);
+ break;
+
+ case 2:
+ grp->gr_gid = (gid_t)strtol(s, &ts, 10);
+ if (*ts != '\0') {
+ free(grp->gr_name);
+ free(grp->gr_passwd);
+ return (-1);
+ }
+ break;
+
+ default:
+ if (sl == NULL) {
+ if (strcmp(s, "(null)") == 0)
+ return (0);
+
+ sl = sl_init();
+ assert(sl != NULL);
+
+ if (strcmp(s, "nomem") != 0) {
+ ts = strdup(s);
+ assert(ts != NULL);
+ sl_add(sl, ts);
+ }
+ } else {
+ ts = strdup(s);
+ assert(ts != NULL);
+ sl_add(sl, ts);
+ }
+ break;
+ };
+ ++i;
+ }
+
+ if (i < 3) {
+ free(grp->gr_name);
+ free(grp->gr_passwd);
+ memset(grp, 0, sizeof(struct group));
+ return (-1);
+ }
+
+ sl_add(sl, NULL);
+ grp->gr_mem = sl->sl_str;
+
+ /* NOTE: is it a dirty hack or not? */
+ free(sl);
+ return (0);
+}
+
+static void
+dump_group(struct group *result)
+{
+ if (result != NULL) {
+ char buffer[1024];
+ sdump_group(result, buffer, sizeof(buffer));
+ printf("%s\n", buffer);
+ } else
+ printf("(null)\n");
+}
+
+static int
+group_fill_test_data(struct group_test_data *td)
+{
+ struct group *grp;
+
+ setgroupent(1);
+ while ((grp = getgrent()) != NULL) {
+ if (group_test_correctness(grp, NULL) == 0)
+ TEST_DATA_APPEND(group, td, grp);
+ else
+ return (-1);
+ }
+ endgrent();
+
+ return (0);
+}
+
+static int
+group_test_correctness(struct group *grp, void *mdata)
+{
+ if (debug) {
+ printf("testing correctness with the following data:\n");
+ dump_group(grp);
+ }
+
+ if (grp == NULL)
+ goto errfin;
+
+ if (grp->gr_name == NULL)
+ goto errfin;
+
+ if (grp->gr_passwd == NULL)
+ goto errfin;
+
+ if (grp->gr_mem == NULL)
+ goto errfin;
+
+ if (debug)
+ printf("correct\n");
+
+ return (0);
+errfin:
+ if (debug)
+ printf("incorrect\n");
+
+ return (-1);
+}
+
+/* group_check_ambiguity() is needed here because when doing the getgrent()
+ * calls sequence, records from different nsswitch sources can be different,
+ * though having the same pw_name/pw_uid */
+static int
+group_check_ambiguity(struct group_test_data *td, struct group *pwd)
+{
+
+ return (TEST_DATA_FIND(group, td, pwd, compare_group,
+ NULL) != NULL ? 0 : -1);
+}
+
+static int
+group_test_getgrnam(struct group *grp_model, void *mdata)
+{
+ struct group *grp;
+
+ if (debug) {
+ printf("testing getgrnam() with the following data:\n");
+ dump_group(grp_model);
+ }
+
+ grp = getgrnam(grp_model->gr_name);
+ if (group_test_correctness(grp, NULL) != 0)
+ goto errfin;
+
+ if ((compare_group(grp, grp_model, NULL) != 0) &&
+ (group_check_ambiguity((struct group_test_data *)mdata, grp)
+ !=0))
+ goto errfin;
+
+ if (debug)
+ printf("ok\n");
+ return (0);
+
+errfin:
+ if (debug)
+ printf("not ok\n");
+
+ return (-1);
+}
+
+static int
+group_test_getgrgid(struct group *grp_model, void *mdata)
+{
+ struct group *grp;
+
+ if (debug) {
+ printf("testing getgrgid() with the following data...\n");
+ dump_group(grp_model);
+ }
+
+ grp = getgrgid(grp_model->gr_gid);
+ if ((group_test_correctness(grp, NULL) != 0) ||
+ ((compare_group(grp, grp_model, NULL) != 0) &&
+ (group_check_ambiguity((struct group_test_data *)mdata, grp)
+ != 0))) {
+ if (debug)
+ printf("not ok\n");
+ return (-1);
+ } else {
+ if (debug)
+ printf("ok\n");
+ return (0);
+ }
+}
+
+static int
+group_test_getgrent(struct group *grp, void *mdata)
+{
+ /* Only correctness can be checked when doing 1-pass test for
+ * getgrent(). */
+ return (group_test_correctness(grp, NULL));
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr,
+ "Usage: %s -nge2 [-d] [-s <file>]\n",
+ getprogname());
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ struct group_test_data td, td_snap, td_2pass;
+ char *snapshot_file;
+ int rv;
+ int c;
+
+ if (argc < 2)
+ usage();
+
+ snapshot_file = NULL;
+ while ((c = getopt(argc, argv, "nge2ds:")) != -1)
+ switch (c) {
+ case 'd':
+ debug++;
+ break;
+ case 'n':
+ method = TEST_GETGRNAM;
+ break;
+ case 'g':
+ method = TEST_GETGRGID;
+ break;
+ case 'e':
+ method = TEST_GETGRENT;
+ break;
+ case '2':
+ method = TEST_GETGRENT_2PASS;
+ break;
+ case 's':
+ snapshot_file = strdup(optarg);
+ break;
+ default:
+ usage();
+ }
+
+ TEST_DATA_INIT(group, &td, clone_group, free_group);
+ TEST_DATA_INIT(group, &td_snap, clone_group, free_group);
+ if (snapshot_file != NULL) {
+ if (access(snapshot_file, W_OK | R_OK) != 0) {
+ if (errno == ENOENT)
+ method = TEST_BUILD_SNAPSHOT;
+ else {
+ if (debug)
+ printf("can't access the file %s\n",
+ snapshot_file);
+
+ rv = -1;
+ goto fin;
+ }
+ } else {
+ if (method == TEST_BUILD_SNAPSHOT) {
+ rv = 0;
+ goto fin;
+ }
+
+ TEST_SNAPSHOT_FILE_READ(group, snapshot_file,
+ &td_snap, group_read_snapshot_func);
+ }
+ }
+
+ rv = group_fill_test_data(&td);
+ if (rv == -1)
+ return (-1);
+ switch (method) {
+ case TEST_GETGRNAM:
+ if (snapshot_file == NULL)
+ rv = DO_1PASS_TEST(group, &td,
+ group_test_getgrnam, (void *)&td);
+ else
+ rv = DO_1PASS_TEST(group, &td_snap,
+ group_test_getgrnam, (void *)&td_snap);
+ break;
+ case TEST_GETGRGID:
+ if (snapshot_file == NULL)
+ rv = DO_1PASS_TEST(group, &td,
+ group_test_getgrgid, (void *)&td);
+ else
+ rv = DO_1PASS_TEST(group, &td_snap,
+ group_test_getgrgid, (void *)&td_snap);
+ break;
+ case TEST_GETGRENT:
+ if (snapshot_file == NULL)
+ rv = DO_1PASS_TEST(group, &td, group_test_getgrent,
+ (void *)&td);
+ else
+ rv = DO_2PASS_TEST(group, &td, &td_snap,
+ compare_group, NULL);
+ break;
+ case TEST_GETGRENT_2PASS:
+ TEST_DATA_INIT(group, &td_2pass, clone_group, free_group);
+ rv = group_fill_test_data(&td_2pass);
+ if (rv != -1)
+ rv = DO_2PASS_TEST(group, &td, &td_2pass,
+ compare_group, NULL);
+ TEST_DATA_DESTROY(group, &td_2pass);
+ break;
+ case TEST_BUILD_SNAPSHOT:
+ if (snapshot_file != NULL)
+ rv = TEST_SNAPSHOT_FILE_WRITE(group, snapshot_file, &td,
+ sdump_group);
+ break;
+ default:
+ rv = 0;
+ break;
+ };
+
+fin:
+ TEST_DATA_DESTROY(group, &td_snap);
+ TEST_DATA_DESTROY(group, &td);
+ free(snapshot_file);
+ return (rv);
+}
diff --git a/tools/regression/lib/libc/nss/test-getgr.t b/tools/regression/lib/libc/nss/test-getgr.t
new file mode 100644
index 0000000..e2cf8e5
--- /dev/null
+++ b/tools/regression/lib/libc/nss/test-getgr.t
@@ -0,0 +1,29 @@
+#!/bin/sh
+# $FreeBSD$
+
+do_test() {
+ number=$1
+ comment=$2
+ opt=$3
+ if ./$executable $opt; then
+ echo "ok $number - $comment"
+ else
+ echo "not ok $number - $comment"
+ fi
+}
+
+cd `dirname $0`
+
+executable=`basename $0 .t`
+
+make $executable 2>&1 > /dev/null
+
+echo 1..8
+do_test 1 'getgrnam()' '-n'
+do_test 2 'getgrgid()' '-g'
+do_test 3 'getgrent()' '-e'
+do_test 4 'getgrent() 2-pass' '-2'
+do_test 5 'building snapshot, if needed' '-s snapshot_grp'
+do_test 6 'getgrnam() snapshot' '-n -s snapshot_grp'
+do_test 7 'getgrgid() snapshot' '-g -s snapshot_grp'
+do_test 8 'getgrent() snapshot' '-e -s snapshot_grp'
diff --git a/tools/regression/lib/libc/nss/test-gethostby.c b/tools/regression/lib/libc/nss/test-gethostby.c
new file mode 100644
index 0000000..61e4ca2
--- /dev/null
+++ b/tools/regression/lib/libc/nss/test-gethostby.c
@@ -0,0 +1,1105 @@
+/*-
+ * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org>
+ * All rights rehted.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <assert.h>
+#include <errno.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stringlist.h>
+#include <unistd.h>
+#include "testutil.h"
+
+#ifndef min
+#define min(a,b) (((a)<(b))?(a):(b))
+#endif
+
+enum test_methods {
+ TEST_GETHOSTBYNAME2,
+ TEST_GETHOSTBYADDR,
+ TEST_GETHOSTBYNAME2_GETADDRINFO,
+ TEST_GETHOSTBYADDR_GETNAMEINFO,
+ TEST_BUILD_SNAPSHOT,
+ TEST_BUILD_ADDR_SNAPSHOT
+};
+
+static int use_ipnode_functions = 0;
+static int use_ipv6_mapping = 0;
+static int ipnode_flags = 0;
+static int debug = 0;
+static int af_type = AF_INET;
+static enum test_methods method = TEST_BUILD_SNAPSHOT;
+
+DECLARE_TEST_DATA(hostent)
+DECLARE_TEST_FILE_SNAPSHOT(hostent)
+DECLARE_1PASS_TEST(hostent)
+DECLARE_2PASS_TEST(hostent)
+
+/* These stubs will use gethostby***() or getipnodeby***() functions,
+ * depending on the use_ipnode_functions global variable value */
+static struct hostent *__gethostbyname2(const char *, int);
+static struct hostent *__gethostbyaddr(const void *, socklen_t, int);
+static void __freehostent(struct hostent *);
+
+static void clone_hostent(struct hostent *, struct hostent const *);
+static int compare_hostent(struct hostent *, struct hostent *, void *);
+static void dump_hostent(struct hostent *);
+static void free_hostent(struct hostent *);
+
+static int is_hostent_equal(struct hostent *, struct addrinfo *);
+
+static void sdump_hostent(struct hostent *, char *, size_t);
+static int hostent_read_hostlist_func(struct hostent *, char *);
+static int hostent_read_snapshot_addr(char *, unsigned char *, size_t);
+static int hostent_read_snapshot_func(struct hostent *, char *);
+
+static int hostent_test_correctness(struct hostent *, void *);
+static int hostent_test_gethostbyaddr(struct hostent *, void *);
+static int hostent_test_getaddrinfo_eq(struct hostent *, void *);
+static int hostent_test_getnameinfo_eq(struct hostent *, void *);
+
+static void usage(void) __attribute__((__noreturn__));
+
+IMPLEMENT_TEST_DATA(hostent)
+IMPLEMENT_TEST_FILE_SNAPSHOT(hostent)
+IMPLEMENT_1PASS_TEST(hostent)
+IMPLEMENT_2PASS_TEST(hostent)
+
+static struct hostent *
+__gethostbyname2(const char *name, int af)
+{
+ struct hostent *he;
+ int error;
+
+ if (use_ipnode_functions == 0)
+ he = gethostbyname2(name, af);
+ else {
+ error = 0;
+ he = getipnodebyname(name, af, ipnode_flags, &error);
+ if (he == NULL);
+ errno = error;
+ }
+
+ return (he);
+}
+
+static struct hostent *
+__gethostbyaddr(const void *addr, socklen_t len, int af)
+{
+ struct hostent *he;
+ int error;
+
+ if (use_ipnode_functions == 0)
+ he = gethostbyaddr(addr, len, af);
+ else {
+ error = 0;
+ he = getipnodebyaddr(addr, len, af, &error);
+ if (he == NULL)
+ errno = error;
+ }
+
+ return (he);
+}
+
+static void
+__freehostent(struct hostent *he)
+{
+ /* NOTE: checking for he != NULL - just in case */
+ if ((use_ipnode_functions != 0) && (he != NULL))
+ freehostent(he);
+}
+
+static void
+clone_hostent(struct hostent *dest, struct hostent const *src)
+{
+ assert(dest != NULL);
+ assert(src != NULL);
+
+ char **cp;
+ int aliases_num;
+ int addrs_num;
+ size_t offset;
+
+ memset(dest, 0, sizeof(struct hostent));
+
+ if (src->h_name != NULL) {
+ dest->h_name = strdup(src->h_name);
+ assert(dest->h_name != NULL);
+ }
+
+ dest->h_addrtype = src->h_addrtype;
+ dest->h_length = src->h_length;
+
+ if (src->h_aliases != NULL) {
+ aliases_num = 0;
+ for (cp = src->h_aliases; *cp; ++cp)
+ ++aliases_num;
+
+ dest->h_aliases = (char **)malloc((aliases_num + 1) *
+ (sizeof(char *)));
+ assert(dest->h_aliases != NULL);
+ memset(dest->h_aliases, 0, (aliases_num + 1) *
+ (sizeof(char *)));
+
+ for (cp = src->h_aliases; *cp; ++cp) {
+ dest->h_aliases[cp - src->h_aliases] = strdup(*cp);
+ assert(dest->h_aliases[cp - src->h_aliases] != NULL);
+ }
+ }
+
+ if (src->h_addr_list != NULL) {
+ addrs_num = 0;
+ for (cp = src->h_addr_list; *cp; ++cp)
+ ++addrs_num;
+
+ dest->h_addr_list = (char **)malloc((addrs_num + 1) *
+ (sizeof(char *)));
+ assert(dest->h_addr_list != NULL);
+ memset(dest->h_addr_list, 0, (addrs_num + 1) *
+ (sizeof(char *)));
+
+ for (cp = src->h_addr_list; *cp; ++cp) {
+ offset = cp - src->h_addr_list;
+ dest->h_addr_list[offset] =
+ (char *)malloc(src->h_length);
+ assert(dest->h_addr_list[offset] != NULL);
+ memcpy(dest->h_addr_list[offset],
+ src->h_addr_list[offset], src->h_length);
+ }
+ }
+}
+
+static void
+free_hostent(struct hostent *ht)
+{
+ char **cp;
+
+ assert(ht != NULL);
+
+ free(ht->h_name);
+
+ if (ht->h_aliases != NULL) {
+ for (cp = ht->h_aliases; *cp; ++cp)
+ free(*cp);
+ free(ht->h_aliases);
+ }
+
+ if (ht->h_addr_list != NULL) {
+ for (cp = ht->h_addr_list; *cp; ++cp)
+ free(*cp);
+ free(ht->h_addr_list);
+ }
+}
+
+static int
+compare_hostent(struct hostent *ht1, struct hostent *ht2, void *mdata)
+{
+ char **c1, **c2, **ct, **cb;
+ int b;
+
+ if (ht1 == ht2)
+ return 0;
+
+ if ((ht1 == NULL) || (ht2 == NULL))
+ goto errfin;
+
+ if ((ht1->h_name == NULL) || (ht2->h_name == NULL))
+ goto errfin;
+
+ if ((ht1->h_addrtype != ht2->h_addrtype) ||
+ (ht1->h_length != ht2->h_length) ||
+ (strcmp(ht1->h_name, ht2->h_name) != 0))
+ goto errfin;
+
+ c1 = ht1->h_aliases;
+ c2 = ht2->h_aliases;
+
+ if (((ht1->h_aliases == NULL) || (ht2->h_aliases == NULL)) &&
+ (ht1->h_aliases != ht2->h_aliases))
+ goto errfin;
+
+ if ((c1 != NULL) && (c2 != NULL)) {
+ cb = c1;
+ for (;*c1; ++c1) {
+ b = 0;
+ for (ct = c2; *ct; ++ct) {
+ if (strcmp(*c1, *ct) == 0) {
+ b = 1;
+ break;
+ }
+ }
+ if (b == 0) {
+ if (debug)
+ printf("h1 aliases item can't be "\
+ "found in h2 aliases\n");
+ goto errfin;
+ }
+ }
+
+ c1 = cb;
+ for (;*c2; ++c2) {
+ b = 0;
+ for (ct = c1; *ct; ++ct) {
+ if (strcmp(*c2, *ct) == 0) {
+ b = 1;
+ break;
+ }
+ }
+ if (b == 0) {
+ if (debug)
+ printf("h2 aliases item can't be "\
+ " found in h1 aliases\n");
+ goto errfin;
+ }
+ }
+ }
+
+ c1 = ht1->h_addr_list;
+ c2 = ht2->h_addr_list;
+
+ if (((ht1->h_addr_list == NULL) || (ht2->h_addr_list== NULL)) &&
+ (ht1->h_addr_list != ht2->h_addr_list))
+ goto errfin;
+
+ if ((c1 != NULL) && (c2 != NULL)) {
+ cb = c1;
+ for (;*c1; ++c1) {
+ b = 0;
+ for (ct = c2; *ct; ++ct) {
+ if (memcmp(*c1, *ct, ht1->h_length) == 0) {
+ b = 1;
+ break;
+ }
+ }
+ if (b == 0) {
+ if (debug)
+ printf("h1 addresses item can't be "\
+ "found in h2 addresses\n");
+ goto errfin;
+ }
+ }
+
+ c1 = cb;
+ for (;*c2; ++c2) {
+ b = 0;
+ for (ct = c1; *ct; ++ct) {
+ if (memcmp(*c2, *ct, ht1->h_length) == 0) {
+ b = 1;
+ break;
+ }
+ }
+ if (b == 0) {
+ if (debug)
+ printf("h2 addresses item can't be "\
+ "found in h1 addresses\n");
+ goto errfin;
+ }
+ }
+ }
+
+ return 0;
+
+errfin:
+ if ((debug) && (mdata == NULL)) {
+ printf("following structures are not equal:\n");
+ dump_hostent(ht1);
+ dump_hostent(ht2);
+ }
+
+ return (-1);
+}
+
+static int
+check_addrinfo_for_name(struct addrinfo *ai, char const *name)
+{
+ struct addrinfo *ai2;
+
+ for (ai2 = ai; ai2 != NULL; ai2 = ai2->ai_next) {
+ if (strcmp(ai2->ai_canonname, name) == 0)
+ return (0);
+ }
+
+ return (-1);
+}
+
+static int
+check_addrinfo_for_addr(struct addrinfo *ai, char const *addr,
+ socklen_t addrlen, int af)
+{
+ struct addrinfo *ai2;
+
+ for (ai2 = ai; ai2 != NULL; ai2 = ai2->ai_next) {
+ if (af != ai2->ai_family)
+ continue;
+
+ switch (af) {
+ case AF_INET:
+ if (memcmp(addr,
+ (void *)&((struct sockaddr_in *)ai2->ai_addr)->sin_addr,
+ min(addrlen, ai2->ai_addrlen)) == 0)
+ return (0);
+ break;
+ case AF_INET6:
+ if (memcmp(addr,
+ (void *)&((struct sockaddr_in6 *)ai2->ai_addr)->sin6_addr,
+ min(addrlen, ai2->ai_addrlen)) == 0)
+ return (0);
+ break;
+ default:
+ break;
+ }
+ }
+
+ return (-1);
+}
+
+static int
+is_hostent_equal(struct hostent *he, struct addrinfo *ai)
+{
+ char **cp;
+ int rv;
+
+ if (debug)
+ printf("checking equality of he and ai\n");
+
+ rv = check_addrinfo_for_name(ai, he->h_name);
+ if (rv != 0) {
+ if (debug)
+ printf("not equal - he->h_name couldn't be found\n");
+
+ return (rv);
+ }
+
+ for (cp = he->h_addr_list; *cp; ++cp) {
+ rv = check_addrinfo_for_addr(ai, *cp, he->h_length,
+ he->h_addrtype);
+ if (rv != 0) {
+ if (debug)
+ printf("not equal - one of he->h_addr_list couldn't be found\n");
+
+ return (rv);
+ }
+ }
+
+ if (debug)
+ printf("equal\n");
+
+ return (0);
+}
+
+static void
+sdump_hostent(struct hostent *ht, char *buffer, size_t buflen)
+{
+ char **cp;
+ size_t i;
+ int written;
+
+ written = snprintf(buffer, buflen, "%s %d %d",
+ ht->h_name, ht->h_addrtype, ht->h_length);
+ buffer += written;
+ if (written > buflen)
+ return;
+ buflen -= written;
+
+ if (ht->h_aliases != NULL) {
+ if (*(ht->h_aliases) != NULL) {
+ for (cp = ht->h_aliases; *cp; ++cp) {
+ written = snprintf(buffer, buflen, " %s",*cp);
+ buffer += written;
+ if (written > buflen)
+ return;
+ buflen -= written;
+
+ if (buflen == 0)
+ return;
+ }
+ } else {
+ written = snprintf(buffer, buflen, " noaliases");
+ buffer += written;
+ if (written > buflen)
+ return;
+ buflen -= written;
+ }
+ } else {
+ written = snprintf(buffer, buflen, " (null)");
+ buffer += written;
+ if (written > buflen)
+ return;
+ buflen -= written;
+ }
+
+ written = snprintf(buffer, buflen, " : ");
+ buffer += written;
+ if (written > buflen)
+ return;
+ buflen -= written;
+
+ if (ht->h_addr_list != NULL) {
+ if (*(ht->h_addr_list) != NULL) {
+ for (cp = ht->h_addr_list; *cp; ++cp) {
+ for (i = 0; i < ht->h_length; ++i ) {
+ written = snprintf(buffer, buflen,
+ i + 1 != ht->h_length ? "%d." : "%d",
+ (unsigned char)(*cp)[i]);
+ buffer += written;
+ if (written > buflen)
+ return;
+ buflen -= written;
+
+ if (buflen == 0)
+ return;
+ }
+
+ if (*(cp + 1) ) {
+ written = snprintf(buffer, buflen, " ");
+ buffer += written;
+ if (written > buflen)
+ return;
+ buflen -= written;
+ }
+ }
+ } else {
+ written = snprintf(buffer, buflen, " noaddrs");
+ buffer += written;
+ if (written > buflen)
+ return;
+ buflen -= written;
+ }
+ } else {
+ written = snprintf(buffer, buflen, " (null)");
+ buffer += written;
+ if (written > buflen)
+ return;
+ buflen -= written;
+ }
+}
+
+static int
+hostent_read_hostlist_func(struct hostent *he, char *line)
+{
+ struct hostent *result;
+ int rv;
+
+ if (debug)
+ printf("resolving %s: ", line);
+ result = __gethostbyname2(line, af_type);
+ if (result != NULL) {
+ if (debug)
+ printf("found\n");
+
+ rv = hostent_test_correctness(result, NULL);
+ if (rv != 0) {
+ __freehostent(result);
+ return (rv);
+ }
+
+ clone_hostent(he, result);
+ __freehostent(result);
+ } else {
+ if (debug)
+ printf("not found\n");
+
+ memset(he, 0, sizeof(struct hostent));
+ he->h_name = strdup(line);
+ assert(he->h_name != NULL);
+ }
+ return (0);
+}
+
+static int
+hostent_read_snapshot_addr(char *addr, unsigned char *result, size_t len)
+{
+ char *s, *ps, *ts;
+
+ ps = addr;
+ while ( (s = strsep(&ps, ".")) != NULL) {
+ if (len == 0)
+ return (-1);
+
+ *result = (unsigned char)strtol(s, &ts, 10);
+ ++result;
+ if (*ts != '\0')
+ return (-1);
+
+ --len;
+ }
+ if (len != 0)
+ return (-1);
+ else
+ return (0);
+}
+
+static int
+hostent_read_snapshot_func(struct hostent *ht, char *line)
+{
+ StringList *sl1, *sl2;;
+ char *s, *ps, *ts;
+ int i, rv;
+
+ if (debug)
+ printf("1 line read from snapshot:\n%s\n", line);
+
+ rv = 0;
+ i = 0;
+ sl1 = sl2 = NULL;
+ ps = line;
+ memset(ht, 0, sizeof(struct hostent));
+ while ( (s = strsep(&ps, " ")) != NULL) {
+ switch (i) {
+ case 0:
+ ht->h_name = strdup(s);
+ assert(ht->h_name != NULL);
+ break;
+
+ case 1:
+ ht->h_addrtype = (int)strtol(s, &ts, 10);
+ if (*ts != '\0')
+ goto fin;
+ break;
+
+ case 2:
+ ht->h_length = (int)strtol(s, &ts, 10);
+ if (*ts != '\0')
+ goto fin;
+ break;
+
+ case 3:
+ if (sl1 == NULL) {
+ if (strcmp(s, "(null)") == 0)
+ return (0);
+
+ sl1 = sl_init();
+ assert(sl1 != NULL);
+
+ if (strcmp(s, "noaliases") != 0) {
+ ts = strdup(s);
+ assert(ts != NULL);
+ sl_add(sl1, ts);
+ }
+ } else {
+ if (strcmp(s, ":") == 0)
+ ++i;
+ else {
+ ts = strdup(s);
+ assert(ts != NULL);
+ sl_add(sl1, ts);
+ }
+ }
+ break;
+
+ case 4:
+ if (sl2 == NULL) {
+ if (strcmp(s, "(null)") == 0)
+ return (0);
+
+ sl2 = sl_init();
+ assert(sl2 != NULL);
+
+ if (strcmp(s, "noaddrs") != 0) {
+ ts = (char *)malloc(ht->h_length);
+ assert(ts != NULL);
+ memset(ts, 0, ht->h_length);
+ rv = hostent_read_snapshot_addr(s,\
+ (unsigned char *)ts, ht->h_length);
+ sl_add(sl2, ts);
+ if (rv != 0)
+ goto fin;
+ }
+ } else {
+ ts = (char *)malloc(ht->h_length);
+ assert(ts != NULL);
+ memset(ts, 0, ht->h_length);
+ rv = hostent_read_snapshot_addr(s,\
+ (unsigned char *)ts, ht->h_length);
+ sl_add(sl2, ts);
+ if (rv != 0)
+ goto fin;
+ }
+ break;
+ default:
+ break;
+ };
+
+ if ((i != 3) && (i != 4))
+ ++i;
+ }
+
+fin:
+ if (sl1 != NULL) {
+ sl_add(sl1, NULL);
+ ht->h_aliases = sl1->sl_str;
+ }
+ if (sl2 != NULL) {
+ sl_add(sl2, NULL);
+ ht->h_addr_list = sl2->sl_str;
+ }
+
+ if ((i != 4) || (rv != 0)) {
+ free_hostent(ht);
+ memset(ht, 0, sizeof(struct hostent));
+ return (-1);
+ }
+
+ /* NOTE: is it a dirty hack or not? */
+ free(sl1);
+ free(sl2);
+ return (0);
+}
+
+static void
+dump_hostent(struct hostent *result)
+{
+ if (result != NULL) {
+ char buffer[1024];
+ sdump_hostent(result, buffer, sizeof(buffer));
+ printf("%s\n", buffer);
+ } else
+ printf("(null)\n");
+}
+
+static int
+hostent_test_correctness(struct hostent *ht, void *mdata)
+{
+ if (debug) {
+ printf("testing correctness with the following data:\n");
+ dump_hostent(ht);
+ }
+
+ if (ht == NULL)
+ goto errfin;
+
+ if (ht->h_name == NULL)
+ goto errfin;
+
+ if (!((ht->h_addrtype >= 0) && (ht->h_addrtype < AF_MAX)))
+ goto errfin;
+
+ if ((ht->h_length != sizeof(struct in_addr)) &&
+ (ht->h_length != sizeof(struct in6_addr)))
+ goto errfin;
+
+ if (ht->h_aliases == NULL)
+ goto errfin;
+
+ if (ht->h_addr_list == NULL)
+ goto errfin;
+
+ if (debug)
+ printf("correct\n");
+
+ return (0);
+errfin:
+ if (debug)
+ printf("incorrect\n");
+
+ return (-1);
+}
+
+static int
+hostent_test_gethostbyaddr(struct hostent *he, void *mdata)
+{
+ struct hostent *result;
+ struct hostent_test_data *addr_test_data;
+ int rv;
+
+ addr_test_data = (struct hostent_test_data *)mdata;
+
+ /* We should omit unresolved hostents */
+ if (he->h_addr_list != NULL) {
+ char **cp;
+ for (cp = he->h_addr_list; *cp; ++cp) {
+ if (debug)
+ printf("doing reverse lookup for %s\n", he->h_name);
+
+ result = __gethostbyaddr(*cp, he->h_length,
+ he->h_addrtype);
+ if (result == NULL) {
+ if (debug)
+ printf("warning: reverse lookup failed\n");
+
+ continue;
+ }
+ rv = hostent_test_correctness(result, NULL);
+ if (rv != 0) {
+ __freehostent(result);
+ return (rv);
+ }
+
+ if (addr_test_data != NULL)
+ TEST_DATA_APPEND(hostent, addr_test_data, result);
+
+ __freehostent(result);
+ }
+ }
+
+ return (0);
+}
+
+static int
+hostent_test_getaddrinfo_eq(struct hostent *he, void *mdata)
+{
+ struct addrinfo *ai, hints;
+ int rv;
+
+ ai = NULL;
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = af_type;
+ hints.ai_flags = AI_CANONNAME;
+
+ if (debug)
+ printf("using getaddrinfo() to resolve %s\n", he->h_name);
+
+ /* struct hostent *he was not resolved */
+ if (he->h_addr_list == NULL) {
+ /* We can be sure that he->h_name is not NULL */
+ rv = getaddrinfo(he->h_name, NULL, &hints, &ai);
+ if (rv == 0) {
+ if (debug)
+ printf("not ok - shouldn't have been resolved\n");
+ return (-1);
+ }
+ } else {
+ rv = getaddrinfo(he->h_name, NULL, &hints, &ai);
+ if (rv != 0) {
+ if (debug)
+ printf("not ok - should have beed resolved\n");
+ return (-1);
+ }
+
+ rv = is_hostent_equal(he, ai);
+ if (rv != 0) {
+ if (debug)
+ printf("not ok - addrinfo and hostent are not equal\n");
+ return (-1);
+ }
+
+ }
+
+ return (0);
+}
+
+static int
+hostent_test_getnameinfo_eq(struct hostent *he, void *mdata)
+{
+ char buffer[NI_MAXHOST];
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+ struct sockaddr *saddr;
+ struct hostent *result;
+ int rv;
+
+ if (he->h_addr_list != NULL) {
+ char **cp;
+ for (cp = he->h_addr_list; *cp; ++cp) {
+ if (debug)
+ printf("doing reverse lookup for %s\n", he->h_name);
+
+ result = __gethostbyaddr(*cp, he->h_length,
+ he->h_addrtype);
+ if (result != NULL) {
+ rv = hostent_test_correctness(result, NULL);
+ if (rv != 0) {
+ __freehostent(result);
+ return (rv);
+ }
+ } else {
+ if (debug)
+ printf("reverse lookup failed\n");
+ }
+
+ switch (he->h_addrtype) {
+ case AF_INET:
+ memset(&sin, 0, sizeof(struct sockaddr_in));
+ sin.sin_len = sizeof(struct sockaddr_in);
+ sin.sin_family = AF_INET;
+ memcpy(&sin.sin_addr, *cp, he->h_length);
+
+ saddr = (struct sockaddr *)&sin;
+ break;
+ case AF_INET6:
+ memset(&sin6, 0, sizeof(struct sockaddr_in6));
+ sin6.sin6_len = sizeof(struct sockaddr_in6);
+ sin6.sin6_family = AF_INET6;
+ memcpy(&sin6.sin6_addr, *cp, he->h_length);
+
+ saddr = (struct sockaddr *)&sin6;
+ break;
+ default:
+ if (debug)
+ printf("warning: %d family is unsupported\n",
+ he->h_addrtype);
+ continue;
+ }
+
+ assert(saddr != NULL);
+ rv = getnameinfo(saddr, saddr->sa_len, buffer,
+ sizeof(buffer), NULL, 0, NI_NAMEREQD);
+
+ if ((rv != 0) && (result != NULL)) {
+ if (debug)
+ printf("not ok - getnameinfo() didn't make the reverse lookup, when it should have (%s)\n",
+ gai_strerror(rv));
+ return (rv);
+ }
+
+ if ((rv == 0) && (result == NULL)) {
+ if (debug)
+ printf("not ok - getnameinfo() made the reverse lookup, when it shouldn't have\n");
+ return (rv);
+ }
+
+ if ((rv != 0) && (result == NULL)) {
+ if (debug)
+ printf("ok - both getnameinfo() and ***byaddr() failed\n");
+
+ continue;
+ }
+
+ if (debug)
+ printf("comparing %s with %s\n", result->h_name,
+ buffer);
+
+ rv = strcmp(result->h_name, buffer);
+ __freehostent(result);
+
+ if (rv != 0) {
+ if (debug)
+ printf("not ok - getnameinfo() and ***byaddr() results are not equal\n");
+ return (rv);
+ } else {
+ if (debug)
+ printf("ok - getnameinfo() and ***byaddr() results are equal\n");
+ }
+ }
+ }
+
+ return (0);
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr,
+ "Usage: %s -na2i [-o] [-d] [-46] [-mAcM] [-C] [-s <file>] -f <file>\n",
+ getprogname());
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ struct hostent_test_data td, td_addr, td_snap;
+ char *snapshot_file, *hostlist_file;
+ res_state statp;
+ int rv;
+ int c;
+
+ if (argc < 2)
+ usage();
+
+ snapshot_file = NULL;
+ hostlist_file = NULL;
+ while ((c = getopt(argc, argv, "nad2iod46mAcMs:f:")) != -1)
+ switch (c) {
+ case '4':
+ af_type = AF_INET;
+ break;
+ case '6':
+ af_type = AF_INET6;
+ break;
+ case 'M':
+ af_type = AF_INET6;
+ use_ipv6_mapping = 1;
+ ipnode_flags |= AI_V4MAPPED_CFG;
+ break;
+ case 'm':
+ af_type = AF_INET6;
+ use_ipv6_mapping = 1;
+ ipnode_flags |= AI_V4MAPPED;
+ break;
+ case 'c':
+ ipnode_flags |= AI_ADDRCONFIG;
+ break;
+ case 'A':
+ ipnode_flags |= AI_ALL;
+ break;
+ case 'o':
+ use_ipnode_functions = 1;
+ break;
+ case 'd':
+ debug = 1;
+ break;
+ case 'n':
+ method = TEST_GETHOSTBYNAME2;
+ break;
+ case 'a':
+ method = TEST_GETHOSTBYADDR;
+ break;
+ case '2':
+ method = TEST_GETHOSTBYNAME2_GETADDRINFO;
+ break;
+ case 'i':
+ method = TEST_GETHOSTBYADDR_GETNAMEINFO;
+ break;
+ case 's':
+ snapshot_file = strdup(optarg);
+ break;
+ case 'f':
+ hostlist_file = strdup(optarg);
+ break;
+ default:
+ usage();
+ }
+
+ if (use_ipnode_functions == 0) {
+ statp = __res_state();
+ if ((statp == NULL) || ((statp->options & RES_INIT) == 0 &&
+ res_ninit(statp) == -1)) {
+ if (debug)
+ printf("error: can't init res_state\n");
+
+ free(snapshot_file);
+ free(hostlist_file);
+ return (-1);
+ }
+
+ if (use_ipv6_mapping == 0)
+ statp->options &= ~RES_USE_INET6;
+ else
+ statp->options |= RES_USE_INET6;
+ }
+
+ TEST_DATA_INIT(hostent, &td, clone_hostent, free_hostent);
+ TEST_DATA_INIT(hostent, &td_addr, clone_hostent, free_hostent);
+ TEST_DATA_INIT(hostent, &td_snap, clone_hostent, free_hostent);
+
+ if (hostlist_file == NULL)
+ usage();
+
+ if (access(hostlist_file, R_OK) != 0) {
+ if (debug)
+ printf("can't access the hostlist file %s\n",
+ hostlist_file);
+
+ usage();
+ }
+
+ if (debug)
+ printf("building host lists from %s\n", hostlist_file);
+
+ rv = TEST_SNAPSHOT_FILE_READ(hostent, hostlist_file, &td,
+ hostent_read_hostlist_func);
+ if (rv != 0)
+ goto fin;
+
+ if (snapshot_file != NULL) {
+ if (access(snapshot_file, W_OK | R_OK) != 0) {
+ if (errno == ENOENT) {
+ if (method != TEST_GETHOSTBYADDR)
+ method = TEST_BUILD_SNAPSHOT;
+ else
+ method = TEST_BUILD_ADDR_SNAPSHOT;
+ } else {
+ if (debug)
+ printf("can't access the snapshot file %s\n",
+ snapshot_file);
+
+ rv = -1;
+ goto fin;
+ }
+ } else {
+ rv = TEST_SNAPSHOT_FILE_READ(hostent, snapshot_file,
+ &td_snap, hostent_read_snapshot_func);
+ if (rv != 0) {
+ if (debug)
+ printf("error reading snapshot file\n");
+ goto fin;
+ }
+ }
+ }
+
+ switch (method) {
+ case TEST_GETHOSTBYNAME2:
+ if (snapshot_file != NULL)
+ rv = DO_2PASS_TEST(hostent, &td, &td_snap,
+ compare_hostent, NULL);
+ break;
+ case TEST_GETHOSTBYADDR:
+ rv = DO_1PASS_TEST(hostent, &td,
+ hostent_test_gethostbyaddr, (void *)&td_addr);
+
+ if (snapshot_file != NULL)
+ rv = DO_2PASS_TEST(hostent, &td_addr, &td_snap,
+ compare_hostent, NULL);
+ break;
+ case TEST_GETHOSTBYNAME2_GETADDRINFO:
+ rv = DO_1PASS_TEST(hostent, &td,
+ hostent_test_getaddrinfo_eq, NULL);
+ break;
+ case TEST_GETHOSTBYADDR_GETNAMEINFO:
+ rv = DO_1PASS_TEST(hostent, &td,
+ hostent_test_getnameinfo_eq, NULL);
+ break;
+ case TEST_BUILD_SNAPSHOT:
+ if (snapshot_file != NULL) {
+ rv = TEST_SNAPSHOT_FILE_WRITE(hostent, snapshot_file, &td,
+ sdump_hostent);
+ }
+ break;
+ case TEST_BUILD_ADDR_SNAPSHOT:
+ if (snapshot_file != NULL) {
+ rv = DO_1PASS_TEST(hostent, &td,
+ hostent_test_gethostbyaddr, (void *)&td_addr);
+
+ rv = TEST_SNAPSHOT_FILE_WRITE(hostent, snapshot_file,
+ &td_addr, sdump_hostent);
+ }
+ break;
+ default:
+ rv = 0;
+ break;
+ };
+
+fin:
+ TEST_DATA_DESTROY(hostent, &td_snap);
+ TEST_DATA_DESTROY(hostent, &td_addr);
+ TEST_DATA_DESTROY(hostent, &td);
+ free(hostlist_file);
+ free(snapshot_file);
+
+ return (rv);
+}
+
diff --git a/tools/regression/lib/libc/nss/test-gethostby.t b/tools/regression/lib/libc/nss/test-gethostby.t
new file mode 100644
index 0000000..42bed00
--- /dev/null
+++ b/tools/regression/lib/libc/nss/test-gethostby.t
@@ -0,0 +1,113 @@
+#!/bin/sh
+# $FreeBSD$
+
+do_test() {
+ number=$1
+ comment=$2
+ opt=$3
+ if ./$executable $opt; then
+ echo "ok $number - $comment"
+ else
+ echo "not ok $number - $comment"
+ fi
+}
+
+cd `dirname $0`
+
+executable=`basename $0 .t`
+
+make $executable 2>&1 > /dev/null
+
+echo 1..46
+#Tests for gethostby***() functions
+#IPv4-driven testing
+do_test 1 'gethostbyname2() (IPv4)' '-4 -n -f mach'
+do_test 2 'gethostbyaddr() (IPv4)' '-4 -a -f mach'
+do_test 3 'gethostbyname2()-getaddrinfo() (IPv4)' '-4 -2 -f mach'
+do_test 4 'gethostbyaddr()-getnameinfo() (IPv4)' '-4 -i -f mach'
+do_test 5 'gethostbyname2() snapshot (IPv4)'\
+ '-4 -n -s snapshot_htname4 -f mach'
+do_test 6 'gethostbyaddr() snapshot (IPv4)'\
+ '-4 -a -s snapshot_htaddr4 -f mach'
+
+#IPv6-driven testing
+do_test 7 'gethostbyname2() (IPv6)' '-6 -n -f mach'
+do_test 8 'gethostbyaddr() (IPv6)' '-6 -a -f mach'
+do_test 9 'gethostbyname2()-getaddrinfo() (IPv6)' '-6 -2 -f mach'
+do_test 10 'gethostbyaddr()-getnameinfo() (IPv6)' '-6 -i -f mach'
+do_test 11 'gethostbyname2() snapshot (IPv6)'\
+ '-6 -n -s snapshot_htname6 -f mach'
+do_test 12 'gethostbyaddr() snapshot (IPv6)'\
+ '-6 -a -s snapshot_htaddr6 -f mach'
+
+#Mapped IPv6-driven testing (getaddrinfo() equality test is useless here)
+do_test 13 'gethostbyname2() (IPv6 mapped)' '-m -n -f mach'
+do_test 14 'gethostbyaddr() (IPv6 mapped)' '-m -a -f mach'
+do_test 15 'gethostbyname2() snapshot (IPv6 mapped)'\
+ '-m -n -s snapshot_htname6map -f mach'
+do_test 16 'gethostbyaddr() snapshot (IPv6 mapped)'\
+ '-m -a -s snapshot_htaddr6map -f mach'
+
+#Tests for getipnodeby***() functions
+#IPv4-driven testing, flags are 0
+do_test 17 'getipnodebyname() (IPv4)' '-o -4 -n -f mach'
+do_test 18 'getipnodebyaddr() (IPv4)' '-o -4 -a -f mach'
+do_test 19 'getipnodebyname()-getaddrinfo() (IPv4)' '-o -4 -2 -f mach'
+do_test 20 'getipnodebyaddr()-getnameinfo() (IPv4)' '-o -4 -i -f mach'
+do_test 21 'getipnodebyname() snapshot (IPv4)'\
+ '-o -4 -n -s snapshot_ipnodename4 -f mach'
+do_test 22 'getipnodebyname() snapshot (IPv4)'\
+ '-o -4 -a -s snapshot_ipnodeaddr4 -f mach'
+
+#IPv6-driven testing, flags are 0
+do_test 23 'getipnodebyname() (IPv6)' '-o -6 -n -f mach'
+do_test 24 'getipnodebyaddr() (IPv6)' '-o -6 -a -f mach'
+do_test 25 'getipnodebyname()-getaddrinfo() (IPv6)' '-o -6 -2 -f mach'
+do_test 26 'getipnodebyaddr()-getnameinfo() (IPv6)' '-o -6 -i -f mach'
+do_test 27 'getipnodebyname() snapshot (IPv6)'\
+ '-o -6 -n -s snapshot_ipnodename6 -f mach'
+do_test 28 'getipnodebyaddr() snapshot (IPv6)'\
+ '-o -6 -a -s snapshot_ipnodeaddr6 -f mach'
+
+#Mapped IPv6-driven testing, flags are AI_V4MAPPED
+do_test 29 'getipnodebyname() (IPv6, AI_V4MAPPED)' '-o -m -n -f mach'
+do_test 30 'getipnodebyaddr() (IPv6, AI_V4MAPPED)' '-o -m -a -f mach'
+do_test 31 'getipnodebyname() snapshot (IPv6, AI_V4MAPPED)'\
+ '-o -m -n -s snapshot_ipnodename6_AI_V4MAPPED -f mach'
+do_test 32 'getipnodebyaddr() snapshot (IPv6, AI_V4MAPPED)'\
+ '-o -m -a -s snapshot_ipnodeaddr6_AI_V4MAPPED -f mach'
+
+#Mapped IPv6-driven testing, flags are AI_V4MAPPED_CFG
+do_test 33 'getipnodebyname() (IPv6, AI_V4MAPPED_CFG)' '-o -M -n -f mach'
+do_test 34 'getipnodebyaddr() (IPv6, AI_V4MAPPED_CFG)' '-o -M -a -f mach'
+do_test 35 'getipnodebyname() snapshot (IPv6, AI_V4MAPPED_CFG)'\
+ '-o -M -n -s snapshot_ipnodename6_AI_V4MAPPED_CFG -f mach'
+do_test 36 'getipnodebyaddr() snapshot (IPv6, AI_V4MAPPED_CFG)'\
+ '-o -M -a -s snapshot_ipnodeaddr6_AI_V4MAPPED_CFG -f mach'
+
+#Mapped IPv6-driven testing, flags are AI_V4MAPPED_CFG | AI_ALL
+do_test 37 'getipnodebyname() (IPv6, AI_V4MAPPED_CFG | AI_ALL)'\
+ '-o -MA -n -f mach'
+do_test 38 'getipnodebyaddr() (IPv6, AI_V4MAPPED_CFG | AI_ALL)'\
+ '-o -MA -a -f mach'
+do_test 39 'getipnodebyname() snapshot (IPv6, AI_V4MAPPED_CFG | AI_ALL)'\
+ '-o -MA -n -s snapshot_ipnodename6_AI_V4MAPPED_CFG_AI_ALL -f mach'
+do_test 40 'getipnodebyaddr() snapshot (IPv6, AI_V4MAPPED_CFG | AI_ALL)'\
+ '-o -MA -a -s snapshot_ipnodeaddr6_AI_V4MAPPED_CFG_AI_ALL -f mach'
+
+#Mapped IPv6-driven testing, flags are AI_V4MAPPED_CFG | AI_ADDRCONFIG
+do_test 41 'getipnodebyname() (IPv6, AI_V4MAPPED_CFG | AI_ADDRCONFIG)'\
+ '-o -Mc -n -f mach'
+do_test 42 'getipnodebyname() snapshot (IPv6, AI_V4MAPPED_CFG | AI_ADDRCONFIG)'\
+ '-o -Mc -n -s snapshot_ipnodename6_AI_V4MAPPED_CFG_AI_ADDRCONFIG -f mach'
+
+#IPv4-driven testing, flags are AI_ADDRCONFIG
+do_test 43 'getipnodebyname() (IPv4, AI_ADDRCONFIG)' '-o -4c -n -f mach'
+do_test 44 'getipnodebyname() snapshot (IPv4, AI_ADDRCONFIG)'\
+ '-o -4c -n -s snapshot_ipnodename4_AI_ADDRCONFIG -f mach'
+
+#IPv6-driven testing, flags are AI_ADDRCONFIG
+do_test 45 'getipnodebyname() (IPv6, AI_ADDRCONFIG)' '-o -6c -n -f mach'
+do_test 46 'getipnodebyname() snapshot (IPv6, AI_ADDRCONFIG)'\
+ '-o -6c -n -s snapshot_ipnodename6_AI_ADDRCONFIG -f mach'
+
diff --git a/tools/regression/lib/libc/nss/test-getproto.c b/tools/regression/lib/libc/nss/test-getproto.c
new file mode 100644
index 0000000..b94f204
--- /dev/null
+++ b/tools/regression/lib/libc/nss/test-getproto.c
@@ -0,0 +1,536 @@
+/*-
+ * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org>
+ * All rights repeed.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <arpa/inet.h>
+#include <assert.h>
+#include <errno.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stringlist.h>
+#include <unistd.h>
+#include "testutil.h"
+
+enum test_methods {
+ TEST_GETPROTOENT,
+ TEST_GETPROTOBYNAME,
+ TEST_GETPROTOBYNUMBER,
+ TEST_GETPROTOENT_2PASS,
+ TEST_BUILD_SNAPSHOT
+};
+
+static int debug = 0;
+static enum test_methods method = TEST_BUILD_SNAPSHOT;
+
+DECLARE_TEST_DATA(protoent)
+DECLARE_TEST_FILE_SNAPSHOT(protoent)
+DECLARE_1PASS_TEST(protoent)
+DECLARE_2PASS_TEST(protoent)
+
+static void clone_protoent(struct protoent *, struct protoent const *);
+static int compare_protoent(struct protoent *, struct protoent *, void *);
+static void dump_protoent(struct protoent *);
+static void free_protoent(struct protoent *);
+
+static void sdump_protoent(struct protoent *, char *, size_t);
+static int protoent_read_snapshot_func(struct protoent *, char *);
+
+static int protoent_check_ambiguity(struct protoent_test_data *,
+ struct protoent *);
+static int protoent_fill_test_data(struct protoent_test_data *);
+static int protoent_test_correctness(struct protoent *, void *);
+static int protoent_test_getprotobyname(struct protoent *, void *);
+static int protoent_test_getprotobynumber(struct protoent *, void *);
+static int protoent_test_getprotoent(struct protoent *, void *);
+
+static void usage(void) __attribute__((__noreturn__));
+
+IMPLEMENT_TEST_DATA(protoent)
+IMPLEMENT_TEST_FILE_SNAPSHOT(protoent)
+IMPLEMENT_1PASS_TEST(protoent)
+IMPLEMENT_2PASS_TEST(protoent)
+
+static void
+clone_protoent(struct protoent *dest, struct protoent const *src)
+{
+ assert(dest != NULL);
+ assert(src != NULL);
+
+ char **cp;
+ int aliases_num;
+
+ memset(dest, 0, sizeof(struct protoent));
+
+ if (src->p_name != NULL) {
+ dest->p_name = strdup(src->p_name);
+ assert(dest->p_name != NULL);
+ }
+
+ dest->p_proto = src->p_proto;
+
+ if (src->p_aliases != NULL) {
+ aliases_num = 0;
+ for (cp = src->p_aliases; *cp; ++cp)
+ ++aliases_num;
+
+ dest->p_aliases = (char **)malloc((aliases_num+1) * (sizeof(char *)));
+ assert(dest->p_aliases != NULL);
+ memset(dest->p_aliases, 0, (aliases_num+1) * (sizeof(char *)));
+
+ for (cp = src->p_aliases; *cp; ++cp) {
+ dest->p_aliases[cp - src->p_aliases] = strdup(*cp);
+ assert(dest->p_aliases[cp - src->p_aliases] != NULL);
+ }
+ }
+}
+
+static void
+free_protoent(struct protoent *pe)
+{
+ char **cp;
+
+ assert(pe != NULL);
+
+ free(pe->p_name);
+
+ for (cp = pe->p_aliases; *cp; ++cp)
+ free(*cp);
+ free(pe->p_aliases);
+}
+
+static int
+compare_protoent(struct protoent *pe1, struct protoent *pe2, void *mdata)
+{
+ char **c1, **c2;
+
+ if (pe1 == pe2)
+ return 0;
+
+ if ((pe1 == NULL) || (pe2 == NULL))
+ goto errfin;
+
+ if ((strcmp(pe1->p_name, pe2->p_name) != 0) ||
+ (pe1->p_proto != pe2->p_proto))
+ goto errfin;
+
+ c1 = pe1->p_aliases;
+ c2 = pe2->p_aliases;
+
+ if ((pe1->p_aliases == NULL) || (pe2->p_aliases == NULL))
+ goto errfin;
+
+ for (;*c1 && *c2; ++c1, ++c2)
+ if (strcmp(*c1, *c2) != 0)
+ goto errfin;
+
+ if ((*c1 != '\0') || (*c2 != '\0'))
+ goto errfin;
+
+ return 0;
+
+errfin:
+ if ((debug) && (mdata == NULL)) {
+ printf("following structures are not equal:\n");
+ dump_protoent(pe1);
+ dump_protoent(pe2);
+ }
+
+ return (-1);
+}
+
+static void
+sdump_protoent(struct protoent *pe, char *buffer, size_t buflen)
+{
+ char **cp;
+ int written;
+
+ written = snprintf(buffer, buflen, "%s %d",
+ pe->p_name, pe->p_proto);
+ buffer += written;
+ if (written > buflen)
+ return;
+ buflen -= written;
+
+ if (pe->p_aliases != NULL) {
+ if (*(pe->p_aliases) != '\0') {
+ for (cp = pe->p_aliases; *cp; ++cp) {
+ written = snprintf(buffer, buflen, " %s",*cp);
+ buffer += written;
+ if (written > buflen)
+ return;
+ buflen -= written;
+
+ if (buflen == 0)
+ return;
+ }
+ } else
+ snprintf(buffer, buflen, " noaliases");
+ } else
+ snprintf(buffer, buflen, " (null)");
+}
+
+static int
+protoent_read_snapshot_func(struct protoent *pe, char *line)
+{
+ StringList *sl;
+ char *s, *ps, *ts;
+ int i;
+
+ if (debug)
+ printf("1 line read from snapshot:\n%s\n", line);
+
+ i = 0;
+ sl = NULL;
+ ps = line;
+ memset(pe, 0, sizeof(struct protoent));
+ while ( (s = strsep(&ps, " ")) != NULL) {
+ switch (i) {
+ case 0:
+ pe->p_name = strdup(s);
+ assert(pe->p_name != NULL);
+ break;
+
+ case 1:
+ pe->p_proto = (int)strtol(s, &ts, 10);
+ if (*ts != '\0') {
+ free(pe->p_name);
+ return (-1);
+ }
+ break;
+
+ default:
+ if (sl == NULL) {
+ if (strcmp(s, "(null)") == 0)
+ return (0);
+
+ sl = sl_init();
+ assert(sl != NULL);
+
+ if (strcmp(s, "noaliases") != 0) {
+ ts = strdup(s);
+ assert(ts != NULL);
+ sl_add(sl, ts);
+ }
+ } else {
+ ts = strdup(s);
+ assert(ts != NULL);
+ sl_add(sl, ts);
+ }
+ break;
+ };
+ ++i;
+ }
+
+ if (i < 3) {
+ free(pe->p_name);
+ memset(pe, 0, sizeof(struct protoent));
+ return (-1);
+ }
+
+ sl_add(sl, NULL);
+ pe->p_aliases = sl->sl_str;
+
+ /* NOTE: is it a dirty hack or not? */
+ free(sl);
+ return (0);
+}
+
+static void
+dump_protoent(struct protoent *result)
+{
+ if (result != NULL) {
+ char buffer[1024];
+ sdump_protoent(result, buffer, sizeof(buffer));
+ printf("%s\n", buffer);
+ } else
+ printf("(null)\n");
+}
+
+static int
+protoent_fill_test_data(struct protoent_test_data *td)
+{
+ struct protoent *pe;
+
+ setprotoent(1);
+ while ((pe = getprotoent()) != NULL) {
+ if (protoent_test_correctness(pe, NULL) == 0)
+ TEST_DATA_APPEND(protoent, td, pe);
+ else
+ return (-1);
+ }
+ endprotoent();
+
+ return (0);
+}
+
+static int
+protoent_test_correctness(struct protoent *pe, void *mdata)
+{
+ if (debug) {
+ printf("testing correctness with the following data:\n");
+ dump_protoent(pe);
+ }
+
+ if (pe == NULL)
+ goto errfin;
+
+ if (pe->p_name == NULL)
+ goto errfin;
+
+ if (pe->p_proto < 0)
+ goto errfin;
+
+ if (pe->p_aliases == NULL)
+ goto errfin;
+
+ if (debug)
+ printf("correct\n");
+
+ return (0);
+errfin:
+ if (debug)
+ printf("incorrect\n");
+
+ return (-1);
+}
+
+/* protoent_check_ambiguity() is needed when one port+proto is associated with
+ * more than one peice (these cases are usually marked as PROBLEM in
+ * /etc/peices. This functions is needed also when one peice+proto is
+ * associated with several ports. We have to check all the protoent structures
+ * to make sure that pe really exists and correct */
+static int
+protoent_check_ambiguity(struct protoent_test_data *td, struct protoent *pe)
+{
+
+ return (TEST_DATA_FIND(protoent, td, pe, compare_protoent,
+ NULL) != NULL ? 0 : -1);
+}
+
+static int
+protoent_test_getprotobyname(struct protoent *pe_model, void *mdata)
+{
+ char **alias;
+ struct protoent *pe;
+
+ if (debug) {
+ printf("testing getprotobyname() with the following data:\n");
+ dump_protoent(pe_model);
+ }
+
+ pe = getprotobyname(pe_model->p_name);
+ if (protoent_test_correctness(pe, NULL) != 0)
+ goto errfin;
+
+ if ((compare_protoent(pe, pe_model, NULL) != 0) &&
+ (protoent_check_ambiguity((struct protoent_test_data *)mdata, pe)
+ !=0))
+ goto errfin;
+
+ for (alias = pe_model->p_aliases; *alias; ++alias) {
+ pe = getprotobyname(*alias);
+
+ if (protoent_test_correctness(pe, NULL) != 0)
+ goto errfin;
+
+ if ((compare_protoent(pe, pe_model, NULL) != 0) &&
+ (protoent_check_ambiguity(
+ (struct protoent_test_data *)mdata, pe) != 0))
+ goto errfin;
+ }
+
+ if (debug)
+ printf("ok\n");
+ return (0);
+
+errfin:
+ if (debug)
+ printf("not ok\n");
+
+ return (-1);
+}
+
+static int
+protoent_test_getprotobynumber(struct protoent *pe_model, void *mdata)
+{
+ struct protoent *pe;
+
+ if (debug) {
+ printf("testing getprotobyport() with the following data...\n");
+ dump_protoent(pe_model);
+ }
+
+ pe = getprotobynumber(pe_model->p_proto);
+ if ((protoent_test_correctness(pe, NULL) != 0) ||
+ ((compare_protoent(pe, pe_model, NULL) != 0) &&
+ (protoent_check_ambiguity((struct protoent_test_data *)mdata, pe)
+ != 0))) {
+ if (debug)
+ printf("not ok\n");
+ return (-1);
+ } else {
+ if (debug)
+ printf("ok\n");
+ return (0);
+ }
+}
+
+static int
+protoent_test_getprotoent(struct protoent *pe, void *mdata)
+{
+ /* Only correctness can be checked when doing 1-pass test for
+ * getprotoent(). */
+ return (protoent_test_correctness(pe, NULL));
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr,
+ "Usage: %s -nve2 [-d] [-s <file>]\n",
+ getprogname());
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ struct protoent_test_data td, td_snap, td_2pass;
+ char *snapshot_file;
+ int rv;
+ int c;
+
+ if (argc < 2)
+ usage();
+
+ snapshot_file = NULL;
+ while ((c = getopt(argc, argv, "nve2ds:")) != -1)
+ switch (c) {
+ case 'd':
+ debug++;
+ break;
+ case 'n':
+ method = TEST_GETPROTOBYNAME;
+ break;
+ case 'v':
+ method = TEST_GETPROTOBYNUMBER;
+ break;
+ case 'e':
+ method = TEST_GETPROTOENT;
+ break;
+ case '2':
+ method = TEST_GETPROTOENT_2PASS;
+ break;
+ case 's':
+ snapshot_file = strdup(optarg);
+ break;
+ default:
+ usage();
+ }
+
+ TEST_DATA_INIT(protoent, &td, clone_protoent, free_protoent);
+ TEST_DATA_INIT(protoent, &td_snap, clone_protoent, free_protoent);
+ if (snapshot_file != NULL) {
+ if (access(snapshot_file, W_OK | R_OK) != 0) {
+ if (errno == ENOENT)
+ method = TEST_BUILD_SNAPSHOT;
+ else {
+ if (debug)
+ printf("can't access the file %s\n",
+ snapshot_file);
+
+ rv = -1;
+ goto fin;
+ }
+ } else {
+ if (method == TEST_BUILD_SNAPSHOT) {
+ rv = 0;
+ goto fin;
+ }
+
+ TEST_SNAPSHOT_FILE_READ(protoent, snapshot_file,
+ &td_snap, protoent_read_snapshot_func);
+ }
+ }
+
+ rv = protoent_fill_test_data(&td);
+ if (rv == -1)
+ return (-1);
+ switch (method) {
+ case TEST_GETPROTOBYNAME:
+ if (snapshot_file == NULL)
+ rv = DO_1PASS_TEST(protoent, &td,
+ protoent_test_getprotobyname, (void *)&td);
+ else
+ rv = DO_1PASS_TEST(protoent, &td_snap,
+ protoent_test_getprotobyname, (void *)&td_snap);
+ break;
+ case TEST_GETPROTOBYNUMBER:
+ if (snapshot_file == NULL)
+ rv = DO_1PASS_TEST(protoent, &td,
+ protoent_test_getprotobynumber, (void *)&td);
+ else
+ rv = DO_1PASS_TEST(protoent, &td_snap,
+ protoent_test_getprotobynumber, (void *)&td_snap);
+ break;
+ case TEST_GETPROTOENT:
+ if (snapshot_file == NULL)
+ rv = DO_1PASS_TEST(protoent, &td,
+ protoent_test_getprotoent, (void *)&td);
+ else
+ rv = DO_2PASS_TEST(protoent, &td, &td_snap,
+ compare_protoent, NULL);
+ break;
+ case TEST_GETPROTOENT_2PASS:
+ TEST_DATA_INIT(protoent, &td_2pass, clone_protoent,
+ free_protoent);
+ rv = protoent_fill_test_data(&td_2pass);
+ if (rv != -1)
+ rv = DO_2PASS_TEST(protoent, &td, &td_2pass,
+ compare_protoent, NULL);
+ TEST_DATA_DESTROY(protoent, &td_2pass);
+ break;
+ case TEST_BUILD_SNAPSHOT:
+ if (snapshot_file != NULL)
+ rv = TEST_SNAPSHOT_FILE_WRITE(protoent, snapshot_file, &td,
+ sdump_protoent);
+ break;
+ default:
+ rv = 0;
+ break;
+ };
+
+fin:
+ TEST_DATA_DESTROY(protoent, &td_snap);
+ TEST_DATA_DESTROY(protoent, &td);
+ free(snapshot_file);
+ return (rv);
+}
diff --git a/tools/regression/lib/libc/nss/test-getproto.t b/tools/regression/lib/libc/nss/test-getproto.t
new file mode 100644
index 0000000..f582d31
--- /dev/null
+++ b/tools/regression/lib/libc/nss/test-getproto.t
@@ -0,0 +1,29 @@
+#!/bin/sh
+# $FreeBSD$
+
+do_test() {
+ number=$1
+ comment=$2
+ opt=$3
+ if ./$executable $opt; then
+ echo "ok $number - $comment"
+ else
+ echo "not ok $number - $comment"
+ fi
+}
+
+cd `dirname $0`
+
+executable=`basename $0 .t`
+
+make $executable 2>&1 > /dev/null
+
+echo 1..8
+do_test 1 'getprotobyname()' '-n'
+do_test 2 'getprotobynumber()' '-v'
+do_test 3 'getprotoent()' '-e'
+do_test 4 'getprotoent() 2-pass' '-2'
+do_test 5 'building snapshot, if needed' '-s snapshot_proto'
+do_test 6 'getprotobyname() snapshot' '-n -s snapshot_proto'
+do_test 7 'getprotobynumber() snapshot' '-v -s snapshot_proto'
+do_test 8 'getprotoent() snapshot' '-e -s snapshot_proto'
diff --git a/tools/regression/lib/libc/nss/test-getpw.c b/tools/regression/lib/libc/nss/test-getpw.c
new file mode 100644
index 0000000..88277d3
--- /dev/null
+++ b/tools/regression/lib/libc/nss/test-getpw.c
@@ -0,0 +1,489 @@
+/*-
+ * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org>
+ * All rights repwded.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <errno.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "testutil.h"
+
+enum test_methods {
+ TEST_GETPWENT,
+ TEST_GETPWNAM,
+ TEST_GETPWUID,
+ TEST_GETPWENT_2PASS,
+ TEST_BUILD_SNAPSHOT
+};
+
+static int debug = 0;
+static enum test_methods method = TEST_BUILD_SNAPSHOT;
+
+DECLARE_TEST_DATA(passwd)
+DECLARE_TEST_FILE_SNAPSHOT(passwd)
+DECLARE_1PASS_TEST(passwd)
+DECLARE_2PASS_TEST(passwd)
+
+static void clone_passwd(struct passwd *, struct passwd const *);
+static int compare_passwd(struct passwd *, struct passwd *, void *);
+static void free_passwd(struct passwd *);
+
+static void sdump_passwd(struct passwd *, char *, size_t);
+static void dump_passwd(struct passwd *);
+
+static int passwd_read_snapshot_func(struct passwd *, char *);
+
+static int passwd_check_ambiguity(struct passwd_test_data *, struct passwd *);
+static int passwd_fill_test_data(struct passwd_test_data *);
+static int passwd_test_correctness(struct passwd *, void *);
+static int passwd_test_getpwnam(struct passwd *, void *);
+static int passwd_test_getpwuid(struct passwd *, void *);
+static int passwd_test_getpwent(struct passwd *, void *);
+
+static void usage(void) __attribute__((__noreturn__));
+
+IMPLEMENT_TEST_DATA(passwd)
+IMPLEMENT_TEST_FILE_SNAPSHOT(passwd)
+IMPLEMENT_1PASS_TEST(passwd)
+IMPLEMENT_2PASS_TEST(passwd)
+
+static void
+clone_passwd(struct passwd *dest, struct passwd const *src)
+{
+ assert(dest != NULL);
+ assert(src != NULL);
+
+ memcpy(dest, src, sizeof(struct passwd));
+ if (src->pw_name != NULL)
+ dest->pw_name = strdup(src->pw_name);
+ if (src->pw_passwd != NULL)
+ dest->pw_passwd = strdup(src->pw_passwd);
+ if (src->pw_class != NULL)
+ dest->pw_class = strdup(src->pw_class);
+ if (src->pw_gecos != NULL)
+ dest->pw_gecos = strdup(src->pw_gecos);
+ if (src->pw_dir != NULL)
+ dest->pw_dir = strdup(src->pw_dir);
+ if (src->pw_shell != NULL)
+ dest->pw_shell = strdup(dest->pw_shell);
+}
+
+static int
+compare_passwd(struct passwd *pwd1, struct passwd *pwd2, void *mdata)
+{
+ assert(pwd1 != NULL);
+ assert(pwd2 != NULL);
+
+ if (pwd1 == pwd2)
+ return (0);
+
+ if ((pwd1->pw_uid != pwd2->pw_uid) ||
+ (pwd1->pw_gid != pwd2->pw_gid) ||
+ (pwd1->pw_change != pwd2->pw_change) ||
+ (pwd1->pw_expire != pwd2->pw_expire) ||
+ (pwd1->pw_fields != pwd2->pw_fields) ||
+ (strcmp(pwd1->pw_name, pwd2->pw_name) != 0) ||
+ (strcmp(pwd1->pw_passwd, pwd2->pw_passwd) != 0) ||
+ (strcmp(pwd1->pw_class, pwd2->pw_class) != 0) ||
+ (strcmp(pwd1->pw_gecos, pwd2->pw_gecos) != 0) ||
+ (strcmp(pwd1->pw_dir, pwd2->pw_dir) != 0) ||
+ (strcmp(pwd1->pw_shell, pwd2->pw_shell) != 0)
+ )
+ return (-1);
+ else
+ return (0);
+}
+
+static void
+free_passwd(struct passwd *pwd)
+{
+ free(pwd->pw_name);
+ free(pwd->pw_passwd);
+ free(pwd->pw_class);
+ free(pwd->pw_gecos);
+ free(pwd->pw_dir);
+ free(pwd->pw_shell);
+}
+
+static void
+sdump_passwd(struct passwd *pwd, char *buffer, size_t buflen)
+{
+ snprintf(buffer, buflen, "%s:%s:%d:%d:%d:%s:%s:%s:%s:%d:%d",
+ pwd->pw_name, pwd->pw_passwd, pwd->pw_uid, pwd->pw_gid,
+ pwd->pw_change, pwd->pw_class, pwd->pw_gecos, pwd->pw_dir,
+ pwd->pw_shell, pwd->pw_expire, pwd->pw_fields);
+}
+
+static void
+dump_passwd(struct passwd *pwd)
+{
+ if (pwd != NULL) {
+ char buffer[2048];
+ sdump_passwd(pwd, buffer, sizeof(buffer));
+ printf("%s\n", buffer);
+ } else
+ printf("(null)\n");
+}
+
+static int
+passwd_read_snapshot_func(struct passwd *pwd, char *line)
+{
+ char *s, *ps, *ts;
+ int i;
+
+ if (debug)
+ printf("1 line read from snapshot:\n%s\n", line);
+
+ i = 0;
+ ps = line;
+ memset(pwd, 0, sizeof(struct passwd));
+ while ( (s = strsep(&ps, ":")) != NULL) {
+ switch (i) {
+ case 0:
+ pwd->pw_name = strdup(s);
+ assert(pwd->pw_name != NULL);
+ break;
+ case 1:
+ pwd->pw_passwd = strdup(s);
+ assert(pwd->pw_passwd != NULL);
+ break;
+ case 2:
+ pwd->pw_uid = (uid_t)strtol(s, &ts, 10);
+ if (*ts != '\0')
+ goto fin;
+ break;
+ case 3:
+ pwd->pw_gid = (gid_t)strtol(s, &ts, 10);
+ if (*ts != '\0')
+ goto fin;
+ break;
+ case 4:
+ pwd->pw_change = (time_t)strtol(s, &ts, 10);
+ if (*ts != '\0')
+ goto fin;
+ break;
+ case 5:
+ pwd->pw_class = strdup(s);
+ assert(pwd->pw_class != NULL);
+ break;
+ case 6:
+ pwd->pw_gecos = strdup(s);
+ assert(pwd->pw_gecos != NULL);
+ break;
+ case 7:
+ pwd->pw_dir = strdup(s);
+ assert(pwd->pw_dir != NULL);
+ break;
+ case 8:
+ pwd->pw_shell = strdup(s);
+ assert(pwd->pw_shell != NULL);
+ break;
+ case 9:
+ pwd->pw_expire = (time_t)strtol(s, &ts, 10);
+ if (*ts != '\0')
+ goto fin;
+ break;
+ case 10:
+ pwd->pw_fields = (int)strtol(s, &ts, 10);
+ if (*ts != '\0')
+ goto fin;
+ break;
+ default:
+ break;
+ };
+ ++i;
+ }
+
+fin:
+ if (i != 11) {
+ free_passwd(pwd);
+ memset(pwd, 0, sizeof(struct passwd));
+ return (-1);
+ }
+
+ return (0);
+}
+
+static int
+passwd_fill_test_data(struct passwd_test_data *td)
+{
+ struct passwd *pwd;
+
+ setpassent(1);
+ while ((pwd = getpwent()) != NULL) {
+ if (passwd_test_correctness(pwd, NULL) == 0)
+ TEST_DATA_APPEND(passwd, td, pwd);
+ else
+ return (-1);
+ }
+ endpwent();
+
+ return (0);
+}
+
+static int
+passwd_test_correctness(struct passwd *pwd, void *mdata)
+{
+ if (debug) {
+ printf("testing correctness with the following data:\n");
+ dump_passwd(pwd);
+ }
+
+ if (pwd == NULL)
+ return (-1);
+
+ if (pwd->pw_name == NULL)
+ goto errfin;
+
+ if (pwd->pw_passwd == NULL)
+ goto errfin;
+
+ if (pwd->pw_class == NULL)
+ goto errfin;
+
+ if (pwd->pw_gecos == NULL)
+ goto errfin;
+
+ if (pwd->pw_dir == NULL)
+ goto errfin;
+
+ if (pwd->pw_shell == NULL)
+ goto errfin;
+
+ if (debug)
+ printf("correct\n");
+
+ return (0);
+errfin:
+ if (debug)
+ printf("incorrect\n");
+
+ return (-1);
+}
+
+/* passwd_check_ambiguity() is needed here because when doing the getpwent()
+ * calls sequence, records from different nsswitch sources can be different,
+ * though having the same pw_name/pw_uid */
+static int
+passwd_check_ambiguity(struct passwd_test_data *td, struct passwd *pwd)
+{
+
+ return (TEST_DATA_FIND(passwd, td, pwd, compare_passwd,
+ NULL) != NULL ? 0 : -1);
+}
+
+static int
+passwd_test_getpwnam(struct passwd *pwd_model, void *mdata)
+{
+ struct passwd *pwd;
+
+ if (debug) {
+ printf("testing getpwnam() with the following data:\n");
+ dump_passwd(pwd_model);
+ }
+
+ pwd = getpwnam(pwd_model->pw_name);
+ if (passwd_test_correctness(pwd, NULL) != 0)
+ goto errfin;
+
+ if ((compare_passwd(pwd, pwd_model, NULL) != 0) &&
+ (passwd_check_ambiguity((struct passwd_test_data *)mdata, pwd)
+ !=0))
+ goto errfin;
+
+ if (debug)
+ printf("ok\n");
+ return (0);
+
+errfin:
+ if (debug)
+ printf("not ok\n");
+
+ return (-1);
+}
+
+static int
+passwd_test_getpwuid(struct passwd *pwd_model, void *mdata)
+{
+ struct passwd *pwd;
+
+ if (debug) {
+ printf("testing getpwuid() with the following data...\n");
+ dump_passwd(pwd_model);
+ }
+
+ pwd = getpwuid(pwd_model->pw_uid);
+ if ((passwd_test_correctness(pwd, NULL) != 0) ||
+ ((compare_passwd(pwd, pwd_model, NULL) != 0) &&
+ (passwd_check_ambiguity((struct passwd_test_data *)mdata, pwd)
+ != 0))) {
+ if (debug)
+ printf("not ok\n");
+ return (-1);
+ } else {
+ if (debug)
+ printf("ok\n");
+ return (0);
+ }
+}
+
+static int
+passwd_test_getpwent(struct passwd *pwd, void *mdata)
+{
+ /* Only correctness can be checked when doing 1-pass test for
+ * getpwent(). */
+ return (passwd_test_correctness(pwd, NULL));
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr,
+ "Usage: %s -nue2 [-d] [-s <file>]\n",
+ getprogname());
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ struct passwd_test_data td, td_snap, td_2pass;
+ char *snapshot_file;
+ int rv;
+ int c;
+
+ if (argc < 2)
+ usage();
+
+ snapshot_file = NULL;
+ while ((c = getopt(argc, argv, "nue2ds:")) != -1)
+ switch (c) {
+ case 'd':
+ debug++;
+ break;
+ case 'n':
+ method = TEST_GETPWNAM;
+ break;
+ case 'u':
+ method = TEST_GETPWUID;
+ break;
+ case 'e':
+ method = TEST_GETPWENT;
+ break;
+ case '2':
+ method = TEST_GETPWENT_2PASS;
+ break;
+ case 's':
+ snapshot_file = strdup(optarg);
+ break;
+ default:
+ usage();
+ }
+
+ TEST_DATA_INIT(passwd, &td, clone_passwd, free_passwd);
+ TEST_DATA_INIT(passwd, &td_snap, clone_passwd, free_passwd);
+ if (snapshot_file != NULL) {
+ if (access(snapshot_file, W_OK | R_OK) != 0) {
+ if (errno == ENOENT)
+ method = TEST_BUILD_SNAPSHOT;
+ else {
+ if (debug)
+ printf("can't access the file %s\n",
+ snapshot_file);
+
+ rv = -1;
+ goto fin;
+ }
+ } else {
+ if (method == TEST_BUILD_SNAPSHOT) {
+ rv = 0;
+ goto fin;
+ }
+
+ TEST_SNAPSHOT_FILE_READ(passwd, snapshot_file,
+ &td_snap, passwd_read_snapshot_func);
+ }
+ }
+
+ rv = passwd_fill_test_data(&td);
+ if (rv == -1)
+ return (-1);
+
+ switch (method) {
+ case TEST_GETPWNAM:
+ if (snapshot_file == NULL)
+ rv = DO_1PASS_TEST(passwd, &td,
+ passwd_test_getpwnam, (void *)&td);
+ else
+ rv = DO_1PASS_TEST(passwd, &td_snap,
+ passwd_test_getpwnam, (void *)&td_snap);
+ break;
+ case TEST_GETPWUID:
+ if (snapshot_file == NULL)
+ rv = DO_1PASS_TEST(passwd, &td,
+ passwd_test_getpwuid, (void *)&td);
+ else
+ rv = DO_1PASS_TEST(passwd, &td_snap,
+ passwd_test_getpwuid, (void *)&td_snap);
+ break;
+ case TEST_GETPWENT:
+ if (snapshot_file == NULL)
+ rv = DO_1PASS_TEST(passwd, &td, passwd_test_getpwent,
+ (void *)&td);
+ else
+ rv = DO_2PASS_TEST(passwd, &td, &td_snap,
+ compare_passwd, NULL);
+ break;
+ case TEST_GETPWENT_2PASS:
+ TEST_DATA_INIT(passwd, &td_2pass, clone_passwd, free_passwd);
+ rv = passwd_fill_test_data(&td_2pass);
+ if (rv != -1)
+ rv = DO_2PASS_TEST(passwd, &td, &td_2pass,
+ compare_passwd, NULL);
+ TEST_DATA_DESTROY(passwd, &td_2pass);
+ break;
+ case TEST_BUILD_SNAPSHOT:
+ if (snapshot_file != NULL)
+ rv = TEST_SNAPSHOT_FILE_WRITE(passwd, snapshot_file, &td,
+ sdump_passwd);
+ break;
+ default:
+ rv = 0;
+ break;
+ };
+
+fin:
+ TEST_DATA_DESTROY(passwd, &td_snap);
+ TEST_DATA_DESTROY(passwd, &td);
+ free(snapshot_file);
+ return (rv);
+}
diff --git a/tools/regression/lib/libc/nss/test-getpw.t b/tools/regression/lib/libc/nss/test-getpw.t
new file mode 100644
index 0000000..5172177
--- /dev/null
+++ b/tools/regression/lib/libc/nss/test-getpw.t
@@ -0,0 +1,29 @@
+#!/bin/sh
+# $FreeBSD$
+
+do_test() {
+ number=$1
+ comment=$2
+ opt=$3
+ if ./$executable $opt; then
+ echo "ok $number - $comment"
+ else
+ echo "not ok $number - $comment"
+ fi
+}
+
+cd `dirname $0`
+
+executable=`basename $0 .t`
+
+make $executable 2>&1 > /dev/null
+
+echo 1..8
+do_test 1 'getpwnam()' '-n'
+do_test 2 'getpwuid()' '-u'
+do_test 3 'getpwent()' '-e'
+do_test 4 'getpwent() 2-pass' '-2'
+do_test 5 'building snapshot, if needed' '-s snapshot_pwd'
+do_test 6 'getpwnam() snapshot' '-n -s snapshot_pwd'
+do_test 7 'getpwuid() snapshot' '-u -s snapshot_pwd'
+do_test 8 'getpwent() snapshot' '-e -s snapshot_pwd'
diff --git a/tools/regression/lib/libc/nss/test-getrpc.c b/tools/regression/lib/libc/nss/test-getrpc.c
new file mode 100644
index 0000000..df0bc83
--- /dev/null
+++ b/tools/regression/lib/libc/nss/test-getrpc.c
@@ -0,0 +1,535 @@
+/*-
+ * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org>
+ * All rights repeed.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <arpa/inet.h>
+#include <rpc/rpc.h>
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stringlist.h>
+#include <unistd.h>
+#include "testutil.h"
+
+enum test_methods {
+ TEST_GETRPCENT,
+ TEST_GETRPCBYNAME,
+ TEST_GETRPCBYNUMBER,
+ TEST_GETRPCENT_2PASS,
+ TEST_BUILD_SNAPSHOT
+};
+
+static int debug = 0;
+static enum test_methods method = TEST_BUILD_SNAPSHOT;
+
+DECLARE_TEST_DATA(rpcent)
+DECLARE_TEST_FILE_SNAPSHOT(rpcent)
+DECLARE_1PASS_TEST(rpcent)
+DECLARE_2PASS_TEST(rpcent)
+
+static void clone_rpcent(struct rpcent *, struct rpcent const *);
+static int compare_rpcent(struct rpcent *, struct rpcent *, void *);
+static void dump_rpcent(struct rpcent *);
+static void free_rpcent(struct rpcent *);
+
+static void sdump_rpcent(struct rpcent *, char *, size_t);
+static int rpcent_read_snapshot_func(struct rpcent *, char *);
+
+static int rpcent_check_ambiguity(struct rpcent_test_data *,
+ struct rpcent *);
+static int rpcent_fill_test_data(struct rpcent_test_data *);
+static int rpcent_test_correctness(struct rpcent *, void *);
+static int rpcent_test_getrpcbyname(struct rpcent *, void *);
+static int rpcent_test_getrpcbynumber(struct rpcent *, void *);
+static int rpcent_test_getrpcent(struct rpcent *, void *);
+
+static void usage(void) __attribute__((__noreturn__));
+
+IMPLEMENT_TEST_DATA(rpcent)
+IMPLEMENT_TEST_FILE_SNAPSHOT(rpcent)
+IMPLEMENT_1PASS_TEST(rpcent)
+IMPLEMENT_2PASS_TEST(rpcent)
+
+static void
+clone_rpcent(struct rpcent *dest, struct rpcent const *src)
+{
+ assert(dest != NULL);
+ assert(src != NULL);
+
+ char **cp;
+ int aliases_num;
+
+ memset(dest, 0, sizeof(struct rpcent));
+
+ if (src->r_name != NULL) {
+ dest->r_name = strdup(src->r_name);
+ assert(dest->r_name != NULL);
+ }
+
+ dest->r_number = src->r_number;
+
+ if (src->r_aliases != NULL) {
+ aliases_num = 0;
+ for (cp = src->r_aliases; *cp; ++cp)
+ ++aliases_num;
+
+ dest->r_aliases = (char **)malloc((aliases_num+1) * (sizeof(char *)));
+ assert(dest->r_aliases != NULL);
+ memset(dest->r_aliases, 0, (aliases_num+1) * (sizeof(char *)));
+
+ for (cp = src->r_aliases; *cp; ++cp) {
+ dest->r_aliases[cp - src->r_aliases] = strdup(*cp);
+ assert(dest->r_aliases[cp - src->r_aliases] != NULL);
+ }
+ }
+}
+
+static void
+free_rpcent(struct rpcent *rpc)
+{
+ char **cp;
+
+ assert(rpc != NULL);
+
+ free(rpc->r_name);
+
+ for (cp = rpc->r_aliases; *cp; ++cp)
+ free(*cp);
+ free(rpc->r_aliases);
+}
+
+static int
+compare_rpcent(struct rpcent *rpc1, struct rpcent *rpc2, void *mdata)
+{
+ char **c1, **c2;
+
+ if (rpc1 == rpc2)
+ return 0;
+
+ if ((rpc1 == NULL) || (rpc2 == NULL))
+ goto errfin;
+
+ if ((strcmp(rpc1->r_name, rpc2->r_name) != 0) ||
+ (rpc1->r_number != rpc2->r_number))
+ goto errfin;
+
+ c1 = rpc1->r_aliases;
+ c2 = rpc2->r_aliases;
+
+ if ((rpc1->r_aliases == NULL) || (rpc2->r_aliases == NULL))
+ goto errfin;
+
+ for (;*c1 && *c2; ++c1, ++c2)
+ if (strcmp(*c1, *c2) != 0)
+ goto errfin;
+
+ if ((*c1 != '\0') || (*c2 != '\0'))
+ goto errfin;
+
+ return 0;
+
+errfin:
+ if ((debug) && (mdata == NULL)) {
+ printf("following structures are not equal:\n");
+ dump_rpcent(rpc1);
+ dump_rpcent(rpc2);
+ }
+
+ return (-1);
+}
+
+static void
+sdump_rpcent(struct rpcent *rpc, char *buffer, size_t buflen)
+{
+ char **cp;
+ int written;
+
+ written = snprintf(buffer, buflen, "%s %d",
+ rpc->r_name, rpc->r_number);
+ buffer += written;
+ if (written > buflen)
+ return;
+ buflen -= written;
+
+ if (rpc->r_aliases != NULL) {
+ if (*(rpc->r_aliases) != '\0') {
+ for (cp = rpc->r_aliases; *cp; ++cp) {
+ written = snprintf(buffer, buflen, " %s",*cp);
+ buffer += written;
+ if (written > buflen)
+ return;
+ buflen -= written;
+
+ if (buflen == 0)
+ return;
+ }
+ } else
+ snprintf(buffer, buflen, " noaliases");
+ } else
+ snprintf(buffer, buflen, " (null)");
+}
+
+static int
+rpcent_read_snapshot_func(struct rpcent *rpc, char *line)
+{
+ StringList *sl;
+ char *s, *ps, *ts;
+ int i;
+
+ if (debug)
+ printf("1 line read from snapshot:\n%s\n", line);
+
+ i = 0;
+ sl = NULL;
+ ps = line;
+ memset(rpc, 0, sizeof(struct rpcent));
+ while ( (s = strsep(&ps, " ")) != NULL) {
+ switch (i) {
+ case 0:
+ rpc->r_name = strdup(s);
+ assert(rpc->r_name != NULL);
+ break;
+
+ case 1:
+ rpc->r_number = (int)strtol(s, &ts, 10);
+ if (*ts != '\0') {
+ free(rpc->r_name);
+ return (-1);
+ }
+ break;
+
+ default:
+ if (sl == NULL) {
+ if (strcmp(s, "(null)") == 0)
+ return (0);
+
+ sl = sl_init();
+ assert(sl != NULL);
+
+ if (strcmp(s, "noaliases") != 0) {
+ ts = strdup(s);
+ assert(ts != NULL);
+ sl_add(sl, ts);
+ }
+ } else {
+ ts = strdup(s);
+ assert(ts != NULL);
+ sl_add(sl, ts);
+ }
+ break;
+ };
+ ++i;
+ }
+
+ if (i < 3) {
+ free(rpc->r_name);
+ memset(rpc, 0, sizeof(struct rpcent));
+ return (-1);
+ }
+
+ sl_add(sl, NULL);
+ rpc->r_aliases = sl->sl_str;
+
+ /* NOTE: is it a dirty hack or not? */
+ free(sl);
+ return (0);
+}
+
+static void
+dump_rpcent(struct rpcent *result)
+{
+ if (result != NULL) {
+ char buffer[1024];
+ sdump_rpcent(result, buffer, sizeof(buffer));
+ printf("%s\n", buffer);
+ } else
+ printf("(null)\n");
+}
+
+static int
+rpcent_fill_test_data(struct rpcent_test_data *td)
+{
+ struct rpcent *rpc;
+
+ setrpcent(1);
+ while ((rpc = getrpcent()) != NULL) {
+ if (rpcent_test_correctness(rpc, NULL) == 0)
+ TEST_DATA_APPEND(rpcent, td, rpc);
+ else
+ return (-1);
+ }
+ endrpcent();
+
+ return (0);
+}
+
+static int
+rpcent_test_correctness(struct rpcent *rpc, void *mdata)
+{
+ if (debug) {
+ printf("testing correctness with the following data:\n");
+ dump_rpcent(rpc);
+ }
+
+ if (rpc == NULL)
+ goto errfin;
+
+ if (rpc->r_name == NULL)
+ goto errfin;
+
+ if (rpc->r_number < 0)
+ goto errfin;
+
+ if (rpc->r_aliases == NULL)
+ goto errfin;
+
+ if (debug)
+ printf("correct\n");
+
+ return (0);
+errfin:
+ if (debug)
+ printf("incorrect\n");
+
+ return (-1);
+}
+
+/* rpcent_check_ambiguity() is needed when one port+rpc is associated with
+ * more than one peice (these cases are usually marked as PROBLEM in
+ * /etc/peices. This functions is needed also when one peice+rpc is
+ * associated with several ports. We have to check all the rpcent structures
+ * to make sure that rpc really exists and correct */
+static int
+rpcent_check_ambiguity(struct rpcent_test_data *td, struct rpcent *rpc)
+{
+
+ return (TEST_DATA_FIND(rpcent, td, rpc, compare_rpcent,
+ NULL) != NULL ? 0 : -1);
+}
+
+static int
+rpcent_test_getrpcbyname(struct rpcent *rpc_model, void *mdata)
+{
+ char **alias;
+ struct rpcent *rpc;
+
+ if (debug) {
+ printf("testing getrpcbyname() with the following data:\n");
+ dump_rpcent(rpc_model);
+ }
+
+ rpc = getrpcbyname(rpc_model->r_name);
+ if (rpcent_test_correctness(rpc, NULL) != 0)
+ goto errfin;
+
+ if ((compare_rpcent(rpc, rpc_model, NULL) != 0) &&
+ (rpcent_check_ambiguity((struct rpcent_test_data *)mdata, rpc)
+ !=0))
+ goto errfin;
+
+ for (alias = rpc_model->r_aliases; *alias; ++alias) {
+ rpc = getrpcbyname(*alias);
+
+ if (rpcent_test_correctness(rpc, NULL) != 0)
+ goto errfin;
+
+ if ((compare_rpcent(rpc, rpc_model, NULL) != 0) &&
+ (rpcent_check_ambiguity(
+ (struct rpcent_test_data *)mdata, rpc) != 0))
+ goto errfin;
+ }
+
+ if (debug)
+ printf("ok\n");
+ return (0);
+
+errfin:
+ if (debug)
+ printf("not ok\n");
+
+ return (-1);
+}
+
+static int
+rpcent_test_getrpcbynumber(struct rpcent *rpc_model, void *mdata)
+{
+ struct rpcent *rpc;
+
+ if (debug) {
+ printf("testing getrpcbyport() with the following data...\n");
+ dump_rpcent(rpc_model);
+ }
+
+ rpc = getrpcbynumber(rpc_model->r_number);
+ if ((rpcent_test_correctness(rpc, NULL) != 0) ||
+ ((compare_rpcent(rpc, rpc_model, NULL) != 0) &&
+ (rpcent_check_ambiguity((struct rpcent_test_data *)mdata, rpc)
+ != 0))) {
+ if (debug)
+ printf("not ok\n");
+ return (-1);
+ } else {
+ if (debug)
+ printf("ok\n");
+ return (0);
+ }
+}
+
+static int
+rpcent_test_getrpcent(struct rpcent *rpc, void *mdata)
+{
+ /* Only correctness can be checked when doing 1-pass test for
+ * getrpcent(). */
+ return (rpcent_test_correctness(rpc, NULL));
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr,
+ "Usage: %s -nve2 [-d] [-s <file>]\n",
+ getprogname());
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ struct rpcent_test_data td, td_snap, td_2pass;
+ char *snapshot_file;
+ int rv;
+ int c;
+
+ if (argc < 2)
+ usage();
+
+ snapshot_file = NULL;
+ while ((c = getopt(argc, argv, "nve2ds:")) != -1)
+ switch (c) {
+ case 'd':
+ debug++;
+ break;
+ case 'n':
+ method = TEST_GETRPCBYNAME;
+ break;
+ case 'v':
+ method = TEST_GETRPCBYNUMBER;
+ break;
+ case 'e':
+ method = TEST_GETRPCENT;
+ break;
+ case '2':
+ method = TEST_GETRPCENT_2PASS;
+ break;
+ case 's':
+ snapshot_file = strdup(optarg);
+ break;
+ default:
+ usage();
+ }
+
+ TEST_DATA_INIT(rpcent, &td, clone_rpcent, free_rpcent);
+ TEST_DATA_INIT(rpcent, &td_snap, clone_rpcent, free_rpcent);
+ if (snapshot_file != NULL) {
+ if (access(snapshot_file, W_OK | R_OK) != 0) {
+ if (errno == ENOENT)
+ method = TEST_BUILD_SNAPSHOT;
+ else {
+ if (debug)
+ printf("can't access the file %s\n",
+ snapshot_file);
+
+ rv = -1;
+ goto fin;
+ }
+ } else {
+ if (method == TEST_BUILD_SNAPSHOT) {
+ rv = 0;
+ goto fin;
+ }
+
+ TEST_SNAPSHOT_FILE_READ(rpcent, snapshot_file,
+ &td_snap, rpcent_read_snapshot_func);
+ }
+ }
+
+ rv = rpcent_fill_test_data(&td);
+ if (rv == -1)
+ return (-1);
+ switch (method) {
+ case TEST_GETRPCBYNAME:
+ if (snapshot_file == NULL)
+ rv = DO_1PASS_TEST(rpcent, &td,
+ rpcent_test_getrpcbyname, (void *)&td);
+ else
+ rv = DO_1PASS_TEST(rpcent, &td_snap,
+ rpcent_test_getrpcbyname, (void *)&td_snap);
+ break;
+ case TEST_GETRPCBYNUMBER:
+ if (snapshot_file == NULL)
+ rv = DO_1PASS_TEST(rpcent, &td,
+ rpcent_test_getrpcbynumber, (void *)&td);
+ else
+ rv = DO_1PASS_TEST(rpcent, &td_snap,
+ rpcent_test_getrpcbynumber, (void *)&td_snap);
+ break;
+ case TEST_GETRPCENT:
+ if (snapshot_file == NULL)
+ rv = DO_1PASS_TEST(rpcent, &td, rpcent_test_getrpcent,
+ (void *)&td);
+ else
+ rv = DO_2PASS_TEST(rpcent, &td, &td_snap,
+ compare_rpcent, NULL);
+ break;
+ case TEST_GETRPCENT_2PASS:
+ TEST_DATA_INIT(rpcent, &td_2pass, clone_rpcent, free_rpcent);
+ rv = rpcent_fill_test_data(&td_2pass);
+ if (rv != -1)
+ rv = DO_2PASS_TEST(rpcent, &td, &td_2pass,
+ compare_rpcent, NULL);
+ TEST_DATA_DESTROY(rpcent, &td_2pass);
+ break;
+ case TEST_BUILD_SNAPSHOT:
+ if (snapshot_file != NULL)
+ rv = TEST_SNAPSHOT_FILE_WRITE(rpcent, snapshot_file, &td,
+ sdump_rpcent);
+ break;
+ default:
+ rv = 0;
+ break;
+ };
+
+fin:
+ TEST_DATA_DESTROY(rpcent, &td_snap);
+ TEST_DATA_DESTROY(rpcent, &td);
+ free(snapshot_file);
+ return (rv);
+}
diff --git a/tools/regression/lib/libc/nss/test-getrpc.t b/tools/regression/lib/libc/nss/test-getrpc.t
new file mode 100644
index 0000000..831a086
--- /dev/null
+++ b/tools/regression/lib/libc/nss/test-getrpc.t
@@ -0,0 +1,29 @@
+#!/bin/sh
+# $FreeBSD$
+
+do_test() {
+ number=$1
+ comment=$2
+ opt=$3
+ if ./$executable $opt; then
+ echo "ok $number - $comment"
+ else
+ echo "not ok $number - $comment"
+ fi
+}
+
+cd `dirname $0`
+
+executable=`basename $0 .t`
+
+make $executable 2>&1 > /dev/null
+
+echo 1..8
+do_test 1 'getrpcbyname()' '-n'
+do_test 2 'getrpcbynumber()' '-v'
+do_test 3 'getrpcent()' '-e'
+do_test 4 'getrpcent() 2-pass' '-2'
+do_test 5 'building snapshot, if needed' '-s snapshot_rpc'
+do_test 6 'getrpcbyname() snapshot' '-n -s snapshot_rpc'
+do_test 7 'getrpcbynumber() snapshot' '-v -s snapshot_rpc'
+do_test 8 'getrpcent() snapshot' '-e -s snapshot_rpc'
diff --git a/tools/regression/lib/libc/nss/test-getserv.c b/tools/regression/lib/libc/nss/test-getserv.c
new file mode 100644
index 0000000..79d42f0
--- /dev/null
+++ b/tools/regression/lib/libc/nss/test-getserv.c
@@ -0,0 +1,551 @@
+/*-
+ * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <arpa/inet.h>
+#include <assert.h>
+#include <errno.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stringlist.h>
+#include <unistd.h>
+#include "testutil.h"
+
+enum test_methods {
+ TEST_GETSERVENT,
+ TEST_GETSERVBYNAME,
+ TEST_GETSERVBYPORT,
+ TEST_GETSERVENT_2PASS,
+ TEST_BUILD_SNAPSHOT
+};
+
+static int debug = 0;
+static enum test_methods method = TEST_BUILD_SNAPSHOT;
+
+DECLARE_TEST_DATA(servent)
+DECLARE_TEST_FILE_SNAPSHOT(servent)
+DECLARE_1PASS_TEST(servent)
+DECLARE_2PASS_TEST(servent)
+
+static void clone_servent(struct servent *, struct servent const *);
+static int compare_servent(struct servent *, struct servent *, void *);
+static void dump_servent(struct servent *);
+static void free_servent(struct servent *);
+
+static void sdump_servent(struct servent *, char *, size_t);
+static int servent_read_snapshot_func(struct servent *, char *);
+
+static int servent_check_ambiguity(struct servent_test_data *,
+ struct servent *);
+static int servent_fill_test_data(struct servent_test_data *);
+static int servent_test_correctness(struct servent *, void *);
+static int servent_test_getservbyname(struct servent *, void *);
+static int servent_test_getservbyport(struct servent *, void *);
+static int servent_test_getservent(struct servent *, void *);
+
+static void usage(void) __attribute__((__noreturn__));
+
+IMPLEMENT_TEST_DATA(servent)
+IMPLEMENT_TEST_FILE_SNAPSHOT(servent)
+IMPLEMENT_1PASS_TEST(servent)
+IMPLEMENT_2PASS_TEST(servent)
+
+static void
+clone_servent(struct servent *dest, struct servent const *src)
+{
+ assert(dest != NULL);
+ assert(src != NULL);
+
+ char **cp;
+ int aliases_num;
+
+ memset(dest, 0, sizeof(struct servent));
+
+ if (src->s_name != NULL) {
+ dest->s_name = strdup(src->s_name);
+ assert(dest->s_name != NULL);
+ }
+
+ if (src->s_proto != NULL) {
+ dest->s_proto = strdup(src->s_proto);
+ assert(dest->s_proto != NULL);
+ }
+ dest->s_port = src->s_port;
+
+ if (src->s_aliases != NULL) {
+ aliases_num = 0;
+ for (cp = src->s_aliases; *cp; ++cp)
+ ++aliases_num;
+
+ dest->s_aliases = (char **)malloc((aliases_num+1) * (sizeof(char *)));
+ assert(dest->s_aliases != NULL);
+ memset(dest->s_aliases, 0, (aliases_num+1) * (sizeof(char *)));
+
+ for (cp = src->s_aliases; *cp; ++cp) {
+ dest->s_aliases[cp - src->s_aliases] = strdup(*cp);
+ assert(dest->s_aliases[cp - src->s_aliases] != NULL);
+ }
+ }
+}
+
+static void
+free_servent(struct servent *serv)
+{
+ char **cp;
+
+ assert(serv != NULL);
+
+ free(serv->s_name);
+ free(serv->s_proto);
+
+ for (cp = serv->s_aliases; *cp; ++cp)
+ free(*cp);
+ free(serv->s_aliases);
+}
+
+static int
+compare_servent(struct servent *serv1, struct servent *serv2, void *mdata)
+{
+ char **c1, **c2;
+
+ if (serv1 == serv2)
+ return 0;
+
+ if ((serv1 == NULL) || (serv2 == NULL))
+ goto errfin;
+
+ if ((strcmp(serv1->s_name, serv2->s_name) != 0) ||
+ (strcmp(serv1->s_proto, serv2->s_proto) != 0) ||
+ (serv1->s_port != serv2->s_port))
+ goto errfin;
+
+ c1 = serv1->s_aliases;
+ c2 = serv2->s_aliases;
+
+ if ((serv1->s_aliases == NULL) || (serv2->s_aliases == NULL))
+ goto errfin;
+
+ for (;*c1 && *c2; ++c1, ++c2)
+ if (strcmp(*c1, *c2) != 0)
+ goto errfin;
+
+ if ((*c1 != '\0') || (*c2 != '\0'))
+ goto errfin;
+
+ return 0;
+
+errfin:
+ if ((debug) && (mdata == NULL)) {
+ printf("following structures are not equal:\n");
+ dump_servent(serv1);
+ dump_servent(serv2);
+ }
+
+ return (-1);
+}
+
+static void
+sdump_servent(struct servent *serv, char *buffer, size_t buflen)
+{
+ char **cp;
+ int written;
+
+ written = snprintf(buffer, buflen, "%s %d %s",
+ serv->s_name, ntohs(serv->s_port), serv->s_proto);
+ buffer += written;
+ if (written > buflen)
+ return;
+ buflen -= written;
+
+ if (serv->s_aliases != NULL) {
+ if (*(serv->s_aliases) != '\0') {
+ for (cp = serv->s_aliases; *cp; ++cp) {
+ written = snprintf(buffer, buflen, " %s",*cp);
+ buffer += written;
+ if (written > buflen)
+ return;
+ buflen -= written;
+
+ if (buflen == 0)
+ return;
+ }
+ } else
+ snprintf(buffer, buflen, " noaliases");
+ } else
+ snprintf(buffer, buflen, " (null)");
+}
+
+static int
+servent_read_snapshot_func(struct servent *serv, char *line)
+{
+ StringList *sl;
+ char *s, *ps, *ts;
+ int i;
+
+ if (debug)
+ printf("1 line read from snapshot:\n%s\n", line);
+
+ i = 0;
+ sl = NULL;
+ ps = line;
+ memset(serv, 0, sizeof(struct servent));
+ while ( (s = strsep(&ps, " ")) != NULL) {
+ switch (i) {
+ case 0:
+ serv->s_name = strdup(s);
+ assert(serv->s_name != NULL);
+ break;
+
+ case 1:
+ serv->s_port = htons(
+ (int)strtol(s, &ts, 10));
+ if (*ts != '\0') {
+ free(serv->s_name);
+ return (-1);
+ }
+ break;
+
+ case 2:
+ serv->s_proto = strdup(s);
+ assert(serv->s_proto != NULL);
+ break;
+
+ default:
+ if (sl == NULL) {
+ if (strcmp(s, "(null)") == 0)
+ return (0);
+
+ sl = sl_init();
+ assert(sl != NULL);
+
+ if (strcmp(s, "noaliases") != 0) {
+ ts = strdup(s);
+ assert(ts != NULL);
+ sl_add(sl, ts);
+ }
+ } else {
+ ts = strdup(s);
+ assert(ts != NULL);
+ sl_add(sl, ts);
+ }
+ break;
+ };
+ ++i;
+ }
+
+ if (i < 3) {
+ free(serv->s_name);
+ free(serv->s_proto);
+ memset(serv, 0, sizeof(struct servent));
+ return (-1);
+ }
+
+ sl_add(sl, NULL);
+ serv->s_aliases = sl->sl_str;
+
+ /* NOTE: is it a dirty hack or not? */
+ free(sl);
+ return (0);
+}
+
+static void
+dump_servent(struct servent *result)
+{
+ if (result != NULL) {
+ char buffer[1024];
+ sdump_servent(result, buffer, sizeof(buffer));
+ printf("%s\n", buffer);
+ } else
+ printf("(null)\n");
+}
+
+static int
+servent_fill_test_data(struct servent_test_data *td)
+{
+ struct servent *serv;
+
+ setservent(1);
+ while ((serv = getservent()) != NULL) {
+ if (servent_test_correctness(serv, NULL) == 0)
+ TEST_DATA_APPEND(servent, td, serv);
+ else
+ return (-1);
+ }
+ endservent();
+
+ return (0);
+}
+
+static int
+servent_test_correctness(struct servent *serv, void *mdata)
+{
+ if (debug) {
+ printf("testing correctness with the following data:\n");
+ dump_servent(serv);
+ }
+
+ if (serv == NULL)
+ goto errfin;
+
+ if (serv->s_name == NULL)
+ goto errfin;
+
+ if (serv->s_proto == NULL)
+ goto errfin;
+
+ if (ntohs(serv->s_port < 0))
+ goto errfin;
+
+ if (serv->s_aliases == NULL)
+ goto errfin;
+
+ if (debug)
+ printf("correct\n");
+
+ return (0);
+errfin:
+ if (debug)
+ printf("incorrect\n");
+
+ return (-1);
+}
+
+/* servent_check_ambiguity() is needed when one port+proto is associated with
+ * more than one service (these cases are usually marked as PROBLEM in
+ * /etc/services. This functions is needed also when one service+proto is
+ * associated with several ports. We have to check all the servent structures
+ * to make sure that serv really exists and correct */
+static int
+servent_check_ambiguity(struct servent_test_data *td, struct servent *serv)
+{
+
+ return (TEST_DATA_FIND(servent, td, serv, compare_servent,
+ NULL) != NULL ? 0 : -1);
+}
+
+static int
+servent_test_getservbyname(struct servent *serv_model, void *mdata)
+{
+ char **alias;
+ struct servent *serv;
+
+ if (debug) {
+ printf("testing getservbyname() with the following data:\n");
+ dump_servent(serv_model);
+ }
+
+ serv = getservbyname(serv_model->s_name, serv_model->s_proto);
+ if (servent_test_correctness(serv, NULL) != 0)
+ goto errfin;
+
+ if ((compare_servent(serv, serv_model, NULL) != 0) &&
+ (servent_check_ambiguity((struct servent_test_data *)mdata, serv)
+ !=0))
+ goto errfin;
+
+ for (alias = serv_model->s_aliases; *alias; ++alias) {
+ serv = getservbyname(*alias, serv_model->s_proto);
+
+ if (servent_test_correctness(serv, NULL) != 0)
+ goto errfin;
+
+ if ((compare_servent(serv, serv_model, NULL) != 0) &&
+ (servent_check_ambiguity(
+ (struct servent_test_data *)mdata, serv) != 0))
+ goto errfin;
+ }
+
+ if (debug)
+ printf("ok\n");
+ return (0);
+
+errfin:
+ if (debug)
+ printf("not ok\n");
+
+ return (-1);
+}
+
+static int
+servent_test_getservbyport(struct servent *serv_model, void *mdata)
+{
+ struct servent *serv;
+
+ if (debug) {
+ printf("testing getservbyport() with the following data...\n");
+ dump_servent(serv_model);
+ }
+
+ serv = getservbyport(serv_model->s_port, serv_model->s_proto);
+ if ((servent_test_correctness(serv, NULL) != 0) ||
+ ((compare_servent(serv, serv_model, NULL) != 0) &&
+ (servent_check_ambiguity((struct servent_test_data *)mdata, serv)
+ != 0))) {
+ if (debug)
+ printf("not ok\n");
+ return (-1);
+ } else {
+ if (debug)
+ printf("ok\n");
+ return (0);
+ }
+}
+
+static int
+servent_test_getservent(struct servent *serv, void *mdata)
+{
+ /* Only correctness can be checked when doing 1-pass test for
+ * getservent(). */
+ return (servent_test_correctness(serv, NULL));
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr,
+ "Usage: %s -npe2 [-d] [-s <file>]\n",
+ getprogname());
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ struct servent_test_data td, td_snap, td_2pass;
+ char *snapshot_file;
+ int rv;
+ int c;
+
+ if (argc < 2)
+ usage();
+
+ snapshot_file = NULL;
+ while ((c = getopt(argc, argv, "npe2ds:")) != -1)
+ switch (c) {
+ case 'd':
+ debug++;
+ break;
+ case 'n':
+ method = TEST_GETSERVBYNAME;
+ break;
+ case 'p':
+ method = TEST_GETSERVBYPORT;
+ break;
+ case 'e':
+ method = TEST_GETSERVENT;
+ break;
+ case '2':
+ method = TEST_GETSERVENT_2PASS;
+ break;
+ case 's':
+ snapshot_file = strdup(optarg);
+ break;
+ default:
+ usage();
+ }
+
+ TEST_DATA_INIT(servent, &td, clone_servent, free_servent);
+ TEST_DATA_INIT(servent, &td_snap, clone_servent, free_servent);
+ if (snapshot_file != NULL) {
+ if (access(snapshot_file, W_OK | R_OK) != 0) {
+ if (errno == ENOENT)
+ method = TEST_BUILD_SNAPSHOT;
+ else {
+ if (debug)
+ printf("can't access the file %s\n",
+ snapshot_file);
+
+ rv = -1;
+ goto fin;
+ }
+ } else {
+ if (method == TEST_BUILD_SNAPSHOT) {
+ rv = 0;
+ goto fin;
+ }
+
+ TEST_SNAPSHOT_FILE_READ(servent, snapshot_file,
+ &td_snap, servent_read_snapshot_func);
+ }
+ }
+
+ rv = servent_fill_test_data(&td);
+ if (rv == -1)
+ return (-1);
+ switch (method) {
+ case TEST_GETSERVBYNAME:
+ if (snapshot_file == NULL)
+ rv = DO_1PASS_TEST(servent, &td,
+ servent_test_getservbyname, (void *)&td);
+ else
+ rv = DO_1PASS_TEST(servent, &td_snap,
+ servent_test_getservbyname, (void *)&td_snap);
+ break;
+ case TEST_GETSERVBYPORT:
+ if (snapshot_file == NULL)
+ rv = DO_1PASS_TEST(servent, &td,
+ servent_test_getservbyport, (void *)&td);
+ else
+ rv = DO_1PASS_TEST(servent, &td_snap,
+ servent_test_getservbyport, (void *)&td_snap);
+ break;
+ case TEST_GETSERVENT:
+ if (snapshot_file == NULL)
+ rv = DO_1PASS_TEST(servent, &td, servent_test_getservent,
+ (void *)&td);
+ else
+ rv = DO_2PASS_TEST(servent, &td, &td_snap,
+ compare_servent, NULL);
+ break;
+ case TEST_GETSERVENT_2PASS:
+ TEST_DATA_INIT(servent, &td_2pass, clone_servent, free_servent);
+ rv = servent_fill_test_data(&td_2pass);
+ if (rv != -1)
+ rv = DO_2PASS_TEST(servent, &td, &td_2pass,
+ compare_servent, NULL);
+ TEST_DATA_DESTROY(servent, &td_2pass);
+ break;
+ case TEST_BUILD_SNAPSHOT:
+ if (snapshot_file != NULL)
+ rv = TEST_SNAPSHOT_FILE_WRITE(servent, snapshot_file, &td,
+ sdump_servent);
+ break;
+ default:
+ rv = 0;
+ break;
+ };
+
+fin:
+ TEST_DATA_DESTROY(servent, &td_snap);
+ TEST_DATA_DESTROY(servent, &td);
+ free(snapshot_file);
+ return (rv);
+}
diff --git a/tools/regression/lib/libc/nss/test-getserv.t b/tools/regression/lib/libc/nss/test-getserv.t
new file mode 100644
index 0000000..60a6c50
--- /dev/null
+++ b/tools/regression/lib/libc/nss/test-getserv.t
@@ -0,0 +1,29 @@
+#!/bin/sh
+# $FreeBSD$
+
+do_test() {
+ number=$1
+ comment=$2
+ opt=$3
+ if ./$executable $opt; then
+ echo "ok $number - $comment"
+ else
+ echo "not ok $number - $comment"
+ fi
+}
+
+cd `dirname $0`
+
+executable=`basename $0 .t`
+
+make $executable 2>&1 > /dev/null
+
+echo 1..8
+do_test 1 'getservbyname()' '-n'
+do_test 2 'getservbyport()' '-p'
+do_test 3 'getservent()' '-e'
+do_test 4 'getservent() 2-pass' '-2'
+do_test 5 'building snapshot, if needed' '-s snapshot_serv'
+do_test 6 'getservbyname() snapshot' '-n -s snapshot_serv'
+do_test 7 'getservbyport() snapshot' '-p -s snapshot_serv'
+do_test 8 'getservent() snapshot' '-e -s snapshot_serv'
diff --git a/tools/regression/lib/libc/nss/test-getusershell.c b/tools/regression/lib/libc/nss/test-getusershell.c
new file mode 100644
index 0000000..20faaac
--- /dev/null
+++ b/tools/regression/lib/libc/nss/test-getusershell.c
@@ -0,0 +1,235 @@
+/*-
+ * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org>
+ * All rights repwded.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "testutil.h"
+
+enum test_methods {
+ TEST_GETUSERSHELL,
+ TEST_BUILD_SNAPSHOT
+};
+
+struct usershell {
+ char *path;
+};
+
+static int debug = 0;
+static enum test_methods method = TEST_GETUSERSHELL;
+
+DECLARE_TEST_DATA(usershell)
+DECLARE_TEST_FILE_SNAPSHOT(usershell)
+DECLARE_2PASS_TEST(usershell)
+
+static void clone_usershell(struct usershell *, struct usershell const *);
+static int compare_usershell(struct usershell *, struct usershell *, void *);
+static void free_usershell(struct usershell *);
+
+static void sdump_usershell(struct usershell *, char *, size_t);
+static void dump_usershell(struct usershell *);
+
+static int usershell_read_snapshot_func(struct usershell *, char *);
+
+static void usage(void) __attribute__((__noreturn__));
+
+IMPLEMENT_TEST_DATA(usershell)
+IMPLEMENT_TEST_FILE_SNAPSHOT(usershell)
+IMPLEMENT_2PASS_TEST(usershell)
+
+static void
+clone_usershell(struct usershell *dest, struct usershell const *src)
+{
+ assert(dest != NULL);
+ assert(src != NULL);
+
+ if (src->path != NULL) {
+ dest->path = strdup(src->path);
+ assert(dest->path != NULL);
+ }
+}
+
+static int
+compare_usershell(struct usershell *us1, struct usershell *us2, void *mdata)
+{
+ int rv;
+
+ assert(us1 != NULL);
+ assert(us2 != NULL);
+
+ dump_usershell(us1);
+ dump_usershell(us2);
+
+ if (us1 == us2)
+ return (0);
+
+ rv = strcmp(us1->path, us2->path);
+ if (rv != 0) {
+ printf("following structures are not equal:\n");
+ dump_usershell(us1);
+ dump_usershell(us2);
+ }
+
+ return (rv);
+}
+
+static void
+free_usershell(struct usershell *us)
+{
+ free(us->path);
+}
+
+static void
+sdump_usershell(struct usershell *us, char *buffer, size_t buflen)
+{
+ snprintf(buffer, buflen, "%s", us->path);
+}
+
+static void
+dump_usershell(struct usershell *us)
+{
+ if (us != NULL) {
+ char buffer[2048];
+ sdump_usershell(us, buffer, sizeof(buffer));
+ printf("%s\n", buffer);
+ } else
+ printf("(null)\n");
+}
+
+static int
+usershell_read_snapshot_func(struct usershell *us, char *line)
+{
+ us->path = strdup(line);
+ assert(us->path != NULL);
+
+ return (0);
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr,
+ "Usage: %s [-d] -s <file>\n",
+ getprogname());
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ struct usershell_test_data td, td_snap;
+ struct usershell ushell;
+ char *snapshot_file;
+ int rv;
+ int c;
+
+ if (argc < 2)
+ usage();
+
+ rv = 0;
+ snapshot_file = NULL;
+ while ((c = getopt(argc, argv, "ds:")) != -1) {
+ switch (c) {
+ case 'd':
+ debug = 1;
+ break;
+ case 's':
+ snapshot_file = strdup(optarg);
+ break;
+ default:
+ usage();
+ }
+ }
+
+ TEST_DATA_INIT(usershell, &td, clone_usershell, free_usershell);
+ TEST_DATA_INIT(usershell, &td_snap, clone_usershell, free_usershell);
+
+ setusershell();
+ while ((ushell.path = getusershell()) != NULL) {
+ if (debug) {
+ printf("usershell found:\n");
+ dump_usershell(&ushell);
+ }
+ TEST_DATA_APPEND(usershell, &td, &ushell);
+ }
+ endusershell();
+
+
+ if (snapshot_file != NULL) {
+ if (access(snapshot_file, W_OK | R_OK) != 0) {
+ if (errno == ENOENT)
+ method = TEST_BUILD_SNAPSHOT;
+ else {
+ if (debug)
+ printf("can't access the snapshot file %s\n",
+ snapshot_file);
+
+ rv = -1;
+ goto fin;
+ }
+ } else {
+ rv = TEST_SNAPSHOT_FILE_READ(usershell, snapshot_file,
+ &td_snap, usershell_read_snapshot_func);
+ if (rv != 0) {
+ if (debug)
+ printf("error reading snapshot file\n");
+ goto fin;
+ }
+ }
+ }
+
+ switch (method) {
+ case TEST_GETUSERSHELL:
+ if (snapshot_file != NULL) {
+ rv = DO_2PASS_TEST(usershell, &td, &td_snap,
+ compare_usershell, NULL);
+ }
+ break;
+ case TEST_BUILD_SNAPSHOT:
+ if (snapshot_file != NULL) {
+ rv = TEST_SNAPSHOT_FILE_WRITE(usershell, snapshot_file, &td,
+ sdump_usershell);
+ }
+ break;
+ default:
+ rv = 0;
+ break;
+ };
+
+fin:
+ TEST_DATA_DESTROY(usershell, &td_snap);
+ TEST_DATA_DESTROY(usershell, &td);
+ free(snapshot_file);
+ return (rv);
+
+}
diff --git a/tools/regression/lib/libc/nss/test-getusershell.t b/tools/regression/lib/libc/nss/test-getusershell.t
new file mode 100644
index 0000000..16a392a
--- /dev/null
+++ b/tools/regression/lib/libc/nss/test-getusershell.t
@@ -0,0 +1,22 @@
+#!/bin/sh
+# $FreeBSD$
+
+do_test() {
+ number=$1
+ comment=$2
+ opt=$3
+ if ./$executable $opt; then
+ echo "ok $number - $comment"
+ else
+ echo "not ok $number - $comment"
+ fi
+}
+
+cd `dirname $0`
+
+executable=`basename $0 .t`
+
+make $executable 2>&1 > /dev/null
+
+echo 1..1
+do_test 1 'getusershell() snapshot' '-s snapshot_usershell'
diff --git a/tools/regression/lib/libc/nss/testutil.h b/tools/regression/lib/libc/nss/testutil.h
new file mode 100644
index 0000000..f1e91c2
--- /dev/null
+++ b/tools/regression/lib/libc/nss/testutil.h
@@ -0,0 +1,334 @@
+/*-
+ * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/queue.h>
+
+#define DECLARE_TEST_DATA(ent) \
+struct ent##_entry { \
+ struct ent data; \
+ STAILQ_ENTRY(ent##_entry) entries; \
+}; \
+ \
+struct ent##_test_data { \
+ void (*clone_func)(struct ent *, struct ent const *); \
+ void (*free_func)(struct ent *); \
+ \
+ STAILQ_HEAD(ent_head, ent##_entry) snapshot_data; \
+}; \
+ \
+void __##ent##_test_data_init(struct ent##_test_data *, \
+ void (*)(struct ent *, struct ent const *), \
+ void (*freef)(struct ent *)); \
+void __##ent##_test_data_destroy(struct ent##_test_data *); \
+ \
+void __##ent##_test_data_append(struct ent##_test_data *, struct ent *data);\
+int __##ent##_test_data_foreach(struct ent##_test_data *, \
+ int (*)(struct ent *, void *), void *); \
+int __##ent##_test_data_compare(struct ent##_test_data *, \
+ struct ent##_test_data *, int (*)(struct ent *, struct ent *, \
+ void *), void *); \
+struct ent *__##ent##_test_data_find(struct ent##_test_data *, struct ent *,\
+ int (*)(struct ent *, struct ent *, void *), void *); \
+void __##ent##_test_data_clear(struct ent##_test_data *);
+
+#define TEST_DATA_INIT(ent, td, clonef, freef)\
+ __##ent##_test_data_init(td, clonef, freef)
+#define TEST_DATA_DESTROY(ent, td) __##ent##_test_data_destroy(td)
+#define TEST_DATA_APPEND(ent, td, d) __##ent##_test_data_append(td, d)
+#define TEST_DATA_FOREACH(ent, td, f, mdata)\
+ __##ent##_test_data_foreach(td, f, mdata)
+#define TEST_DATA_COMPARE(ent, td1, td2, fcmp, mdata)\
+ __##ent##_test_data_compare(td1, td2, fcmp, mdata);
+#define TEST_DATA_FIND(ent, td, d, fcmp, mdata)\
+ __##ent##_test_data_find(td, d, fcmp, mdata)
+#define TEST_DATA_CLEAR(ent, td) __##ent##_test_data_clear(td)
+
+#define IMPLEMENT_TEST_DATA(ent) \
+void \
+__##ent##_test_data_init(struct ent##_test_data *td, \
+ void (*clonef)(struct ent *, struct ent const *), \
+ void (*freef)(struct ent *)) \
+{ \
+ assert(td != NULL); \
+ assert(clonef != NULL); \
+ assert(freef != NULL); \
+ \
+ memset(td, 0, sizeof(*td)); \
+ td->clone_func = clonef; \
+ td->free_func = freef; \
+ STAILQ_INIT(&td->snapshot_data); \
+} \
+ \
+void \
+__##ent##_test_data_destroy(struct ent##_test_data *td) \
+{ \
+ __##ent##_test_data_clear(td); \
+} \
+ \
+void \
+__##ent##_test_data_append(struct ent##_test_data *td, struct ent *app_data)\
+{ \
+ struct ent##_entry *e; \
+ \
+ assert(td != NULL); \
+ assert(app_data != NULL); \
+ \
+ e = (struct ent##_entry *)malloc(sizeof(struct ent##_entry)); \
+ assert(e != NULL); \
+ memset(e, 0, sizeof(struct ent##_entry)); \
+ \
+ td->clone_func(&e->data, app_data); \
+ STAILQ_INSERT_TAIL(&td->snapshot_data, e, entries); \
+} \
+ \
+int \
+__##ent##_test_data_foreach(struct ent##_test_data *td, \
+ int (*forf)(struct ent *, void *), void *mdata) \
+{ \
+ struct ent##_entry *e; \
+ int rv; \
+ \
+ assert(td != NULL); \
+ assert(forf != NULL); \
+ \
+ rv = 0; \
+ STAILQ_FOREACH(e, &td->snapshot_data, entries) { \
+ rv = forf(&e->data, mdata); \
+ if (rv != 0) \
+ break; \
+ } \
+ \
+ return (rv); \
+} \
+ \
+int \
+__##ent##_test_data_compare(struct ent##_test_data *td1, struct ent##_test_data *td2,\
+ int (*cmp_func)(struct ent *, struct ent *, void *), void *mdata)\
+{ \
+ struct ent##_entry *e1, *e2; \
+ int rv; \
+ \
+ assert(td1 != NULL); \
+ assert(td2 != NULL); \
+ assert(cmp_func != NULL); \
+ \
+ e1 = STAILQ_FIRST(&td1->snapshot_data); \
+ e2 = STAILQ_FIRST(&td2->snapshot_data); \
+ \
+ rv = 0; \
+ do { \
+ if ((e1 == NULL) || (e2 == NULL)) { \
+ if (e1 == e2) \
+ return (0); \
+ else \
+ return (-1); \
+ } \
+ \
+ rv = cmp_func(&e1->data, &e2->data, mdata); \
+ e1 = STAILQ_NEXT(e1, entries); \
+ e2 = STAILQ_NEXT(e2, entries); \
+ } while (rv == 0); \
+ \
+ return (rv); \
+} \
+ \
+struct ent * \
+__##ent##_test_data_find(struct ent##_test_data *td, struct ent *data, \
+ int (*cmp)(struct ent *, struct ent *, void *), void *mdata) \
+{ \
+ struct ent##_entry *e; \
+ struct ent *result; \
+ \
+ assert(td != NULL); \
+ assert(cmp != NULL); \
+ \
+ result = NULL; \
+ STAILQ_FOREACH(e, &td->snapshot_data, entries) { \
+ if (cmp(&e->data, data, mdata) == 0) { \
+ result = &e->data; \
+ break; \
+ } \
+ } \
+ \
+ return (result); \
+} \
+ \
+ \
+void \
+__##ent##_test_data_clear(struct ent##_test_data *td) \
+{ \
+ struct ent##_entry *e; \
+ assert(td != NULL); \
+ \
+ while (!STAILQ_EMPTY(&td->snapshot_data)) { \
+ e = STAILQ_FIRST(&td->snapshot_data); \
+ STAILQ_REMOVE_HEAD(&td->snapshot_data, entries); \
+ \
+ td->free_func(&e->data); \
+ free(e); \
+ } \
+}
+
+ \
+#define DECLARE_TEST_FILE_SNAPSHOT(ent) \
+struct ent##_snp_param { \
+ FILE *fp; \
+ void (*sdump_func)(struct ent *, char *, size_t); \
+}; \
+ \
+int __##ent##_snapshot_write_func(struct ent *, void *); \
+int __##ent##_snapshot_write(char const *, struct ent##_test_data *, \
+ void (*)(struct ent *, char *, size_t)); \
+int __##ent##_snapshot_read(char const *, struct ent##_test_data *, \
+ int (*)(struct ent *, char *));
+
+#define TEST_SNAPSHOT_FILE_WRITE(ent, fname, td, f) \
+ __##ent##_snapshot_write(fname, td, f)
+#define TEST_SNAPSHOT_FILE_READ(ent, fname, td, f) \
+ __##ent##_snapshot_read(fname, td, f)
+
+#define IMPLEMENT_TEST_FILE_SNAPSHOT(ent) \
+int \
+__##ent##_snapshot_write_func(struct ent *data, void *mdata) \
+{ \
+ char buffer[1024]; \
+ struct ent##_snp_param *param; \
+ \
+ assert(data != NULL); \
+ \
+ param = (struct ent##_snp_param *)mdata; \
+ param->sdump_func(data, buffer, sizeof(buffer)); \
+ fputs(buffer, param->fp); \
+ fputc('\n', param->fp); \
+ \
+ return (0); \
+} \
+ \
+int \
+__##ent##_snapshot_write(char const *fname, struct ent##_test_data *td, \
+ void (*sdump_func)(struct ent *, char *, size_t)) \
+{ \
+ struct ent##_snp_param param; \
+ \
+ assert(fname != NULL); \
+ assert(td != NULL); \
+ \
+ param.fp = fopen(fname, "w"); \
+ if (param.fp == NULL) \
+ return (-1); \
+ \
+ param.sdump_func = sdump_func; \
+ __##ent##_test_data_foreach(td, __##ent##_snapshot_write_func, &param);\
+ fclose(param.fp); \
+ \
+ return (0); \
+} \
+ \
+int \
+__##ent##_snapshot_read(char const *fname, struct ent##_test_data *td, \
+ int (*read_func)(struct ent *, char *)) \
+{ \
+ char buffer[1024]; \
+ struct ent data; \
+ char *s; \
+ FILE *fi; \
+ size_t len; \
+ int rv; \
+ \
+ assert(fname != NULL); \
+ assert(td != NULL); \
+ \
+ fi = fopen(fname, "r"); \
+ if (fi == NULL) \
+ return (-1); \
+ \
+ rv = 0; \
+ memset(buffer, 0, sizeof(buffer)); \
+ while (!feof(fi)) { \
+ s = fgets(buffer, sizeof(buffer), fi); \
+ if (s != NULL && s[0] != '#') { \
+ len = strlen(s); \
+ if (len == 0) \
+ continue; \
+ if (buffer[len - 1] == '\n') \
+ buffer[len -1] = '\0'; \
+ \
+ rv = read_func(&data, s); \
+ if (rv == 0) { \
+ __##ent##_test_data_append(td, &data); \
+ td->free_func(&data); \
+ } else \
+ goto fin; \
+ } \
+ } \
+ \
+fin: \
+ fclose(fi); \
+ return (rv); \
+}
+
+#define DECLARE_1PASS_TEST(ent) \
+int __##ent##_1pass_test(struct ent##_test_data *, \
+ int (*)(struct ent *, void *), \
+ void *);
+
+#define DO_1PASS_TEST(ent, td, f, mdata) \
+ __##ent##_1pass_test(td, f, mdata)
+
+#define IMPLEMENT_1PASS_TEST(ent) \
+int \
+__##ent##_1pass_test(struct ent##_test_data *td, \
+ int (*tf)(struct ent *, void *), \
+ void *mdata) \
+{ \
+ int rv; \
+ rv = __##ent##_test_data_foreach(td, tf, mdata); \
+ \
+ return (rv); \
+}
+
+#define DECLARE_2PASS_TEST(ent) \
+int __##ent##_2pass_test(struct ent##_test_data *, \
+ struct ent##_test_data *, \
+ int (*)(struct ent *, struct ent *, void *), void *);
+
+#define DO_2PASS_TEST(ent, td1, td2, f, mdata) \
+ __##ent##_2pass_test(td1, td2, f, mdata)
+
+#define IMPLEMENT_2PASS_TEST(ent) \
+int \
+__##ent##_2pass_test(struct ent##_test_data *td1, \
+ struct ent##_test_data *td2, \
+ int (*cmp_func)(struct ent *, struct ent *, void *), \
+ void *cmp_mdata) \
+{ \
+ int rv; \
+ \
+ rv = __##ent##_test_data_compare(td1, td2, cmp_func, cmp_mdata); \
+ return (rv); \
+}
diff --git a/tools/regression/lib/libc/regex/Makefile b/tools/regression/lib/libc/regex/Makefile
new file mode 100644
index 0000000..f91bef2
--- /dev/null
+++ b/tools/regression/lib/libc/regex/Makefile
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+GROT= ../../../../../lib/libc/regex/grot
+
+.PHONY: tests
+tests:
+ cd ${GROT}; make && echo "PASS regex"
+
+.PHONY: clean
+clean:
+ cd ${GROT}; make spotless
diff --git a/tools/regression/lib/libc/resolv/Makefile b/tools/regression/lib/libc/resolv/Makefile
new file mode 100644
index 0000000..9b4e6b1
--- /dev/null
+++ b/tools/regression/lib/libc/resolv/Makefile
@@ -0,0 +1,15 @@
+# $NetBSD: Makefile,v 1.1 2004/05/13 19:17:12 christos Exp $
+# $FreeBSD$
+
+PROG= resolv
+NO_MAN=
+
+# Note: this test relies on being dynamically linked. You will get a
+# spurious PASS for a statically linked test.
+DPADD+= ${LIBPTHREAD}
+LDADD+= -lpthread
+
+regress: ${PROG}
+ ./${PROG} -r ${.CURDIR}/mach
+
+.include <bsd.prog.mk>
diff --git a/tools/regression/lib/libc/resolv/mach b/tools/regression/lib/libc/resolv/mach
new file mode 100644
index 0000000..f3c3981
--- /dev/null
+++ b/tools/regression/lib/libc/resolv/mach
@@ -0,0 +1,92 @@
+above.warped.net
+anoncvs.cirr.com
+anoncvs.isc.netbsd.org
+anoncvs.leo.org
+anoncvs.netbsd.lt
+anoncvs.netbsd.ro
+anoncvs.netbsd.se
+antioche.antioche.eu.org
+boulder.tele.dk
+centaurus.4web.cz
+chur.math.ntnu.no
+cnftp.bjpu.edu.cn
+console.netbsd.org
+cvs.fi.netbsd.org
+cvs.mikrolahti.fi
+cvs.netbsd.org
+cvsup-netbsd.leo.org
+cvsup.netbsd.se
+cvsup.pasta.cs.uit.no
+ftp.bitcon.no
+ftp.chg.ru
+ftp.duth.gr
+ftp.estpak.ee
+ftp.fsn.hu
+ftp.funet.fi
+ftp.grondar.za
+ftp.leo.org
+ftp.netbsd.lt
+ftp.netbsd.org
+ftp.nluug.nl
+ftp.plig.org
+ftp.uni-erlangen.de
+ftp.xgate.co.kr
+gd.tuwien.ac.at
+gort.ludd.luth.se
+grappa.unix-ag.uni-kl.de
+info.wins.uva.nl
+irc.warped.net
+knug.youn.co.kr
+lala.iri.co.jp
+mail.jp.netbsd.org
+mail.kr.netbsd.org
+mail.netbsd.org
+melanoma.cs.rmit.edu.au
+mirror.aarnet.edu.au
+mirror.netbsd.com.br
+mirror03.inet.tele.dk
+moon.vub.ac.be
+nbwww.sergei.cc
+net.bsd.cz
+netbsd.3miasto.net
+netbsd.4ka.mipt.ru
+netbsd.apk.od.ua
+netbsd.csie.nctu.edu.tw
+netbsd.enderunix.org
+netbsd.ftp.fu-berlin.de
+netbsd.netlead.com.au
+netbsd.nsysu.edu.tw
+netbsd.pair.com
+netbsd.stevens-tech.edu
+netbsd.triada.bg
+netbsd.unix.net.nz
+netbsd.unixtech.be
+netbsd.vejas.lt
+netbsd.wagener-consulting.lu
+netbsd.zarco.org
+netbsdiso.interoute.net.uk
+netbsdwww.bitcon.no
+netbsdwww.cordef.com.pl
+netbsdwww.cs.rmit.edu.au
+netbsdwww.interoute.net.uk
+news.gw.com
+ns.netbsd.org
+pigu.iri.co.jp
+pluto.cdpa.nsysu.edu.tw
+projects.slowass.net
+server6.pasta.cs.uit.no
+skeleton.phys.spbu.ru
+snoopy.allbsd.org
+spike.allbsd.org
+sundry.netbsd.org
+tanya.sergei.cc
+web-a.fi.gw.com
+web-a.us.gw.com
+web.netbsd.mirror.arhea.net
+www.en.netbsd.de
+www.netbsd.cl
+www.netbsd.nl
+www.netbsd.org
+www.netbsd.ro
+zathras.netbsd.org
+zeppo.rediris.es
diff --git a/tools/regression/lib/libc/resolv/resolv.c b/tools/regression/lib/libc/resolv/resolv.c
new file mode 100644
index 0000000..dc925d3
--- /dev/null
+++ b/tools/regression/lib/libc/resolv/resolv.c
@@ -0,0 +1,330 @@
+/* $NetBSD: resolv.c,v 1.6 2004/05/23 16:59:11 christos Exp $ */
+
+/*-
+ * Copyright (c) 2004 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/* $FreeBSD$ */
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: resolv.c,v 1.6 2004/05/23 16:59:11 christos Exp $");
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <netdb.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <err.h>
+#include <string.h>
+#include <stringlist.h>
+
+#define NTHREADS 10
+#define NHOSTS 100
+#define WS " \t\n\r"
+
+enum method {
+ METHOD_GETADDRINFO,
+ METHOD_GETHOSTBY,
+ METHOD_GETIPNODEBY
+};
+
+static StringList *hosts = NULL;
+static int debug = 0;
+static enum method method = METHOD_GETADDRINFO;
+static int reverse = 0;
+static int *ask = NULL;
+static int *got = NULL;
+
+static void usage(void) __attribute__((__noreturn__));
+static void load(const char *);
+static void resolvone(int);
+static void *resolvloop(void *);
+static void run(int *);
+
+static pthread_mutex_t stats = PTHREAD_MUTEX_INITIALIZER;
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr,
+ "Usage: %s [-AdHIr] [-h <nhosts>] [-n <nthreads>] <file> ...\n",
+ getprogname());
+ exit(1);
+}
+
+static void
+load(const char *fname)
+{
+ FILE *fp;
+ size_t len;
+ char *line;
+
+ if ((fp = fopen(fname, "r")) == NULL)
+ err(1, "Cannot open `%s'", fname);
+ while ((line = fgetln(fp, &len)) != NULL) {
+ char c = line[len];
+ char *ptr;
+ line[len] = '\0';
+ for (ptr = strtok(line, WS); ptr; ptr = strtok(NULL, WS))
+ sl_add(hosts, strdup(ptr));
+ line[len] = c;
+ }
+
+ (void)fclose(fp);
+}
+
+static int
+resolv_getaddrinfo(pthread_t self, char *host, int port)
+{
+ char portstr[6], buf[1024], hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
+ struct addrinfo hints, *res;
+ int error, len;
+
+ snprintf(portstr, sizeof(portstr), "%d", port);
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_socktype = SOCK_STREAM;
+ error = getaddrinfo(host, portstr, &hints, &res);
+ if (debug) {
+ len = snprintf(buf, sizeof(buf), "%p: host %s %s\n",
+ self, host, error ? "not found" : "ok");
+ (void)write(STDOUT_FILENO, buf, len);
+ }
+ if (error == 0 && reverse) {
+ memset(hbuf, 0, sizeof(hbuf));
+ memset(pbuf, 0, sizeof(pbuf));
+ getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf),
+ pbuf, sizeof(pbuf), 0);
+ if (debug) {
+ len = snprintf(buf, sizeof(buf),
+ "%p: reverse %s %s\n", self, hbuf, pbuf);
+ (void)write(STDOUT_FILENO, buf, len);
+ }
+ }
+ if (error == 0)
+ freeaddrinfo(res);
+ return error;
+}
+
+static int
+resolv_gethostby(pthread_t self, char *host)
+{
+ char buf[1024];
+ struct hostent *hp, *hp2;
+ int len;
+
+ hp = gethostbyname(host);
+ if (debug) {
+ len = snprintf(buf, sizeof(buf), "%p: host %s %s\n",
+ self, host, (hp == NULL) ? "not found" : "ok");
+ (void)write(STDOUT_FILENO, buf, len);
+ }
+ if (hp && reverse) {
+ memcpy(buf, hp->h_addr, hp->h_length);
+ hp2 = gethostbyaddr(buf, hp->h_length, hp->h_addrtype);
+ if (hp2 && debug) {
+ len = snprintf(buf, sizeof(buf),
+ "%p: reverse %s\n", self, hp2->h_name);
+ (void)write(STDOUT_FILENO, buf, len);
+ }
+ }
+ return hp ? 0 : -1;
+}
+
+static int
+resolv_getipnodeby(pthread_t self, char *host)
+{
+ char buf[1024];
+ struct hostent *hp, *hp2;
+ int len, h_error;
+
+ hp = getipnodebyname(host, AF_INET, 0, &h_error);
+ if (debug) {
+ len = snprintf(buf, sizeof(buf), "%p: host %s %s\n",
+ self, host, (hp == NULL) ? "not found" : "ok");
+ (void)write(STDOUT_FILENO, buf, len);
+ }
+ if (hp && reverse) {
+ memcpy(buf, hp->h_addr, hp->h_length);
+ hp2 = getipnodebyaddr(buf, hp->h_length, hp->h_addrtype,
+ &h_error);
+ if (hp2 && debug) {
+ len = snprintf(buf, sizeof(buf),
+ "%p: reverse %s\n", self, hp2->h_name);
+ (void)write(STDOUT_FILENO, buf, len);
+ }
+ if (hp2)
+ freehostent(hp2);
+ }
+ if (hp)
+ freehostent(hp);
+ return hp ? 0 : -1;
+}
+
+static void
+resolvone(int n)
+{
+ char buf[1024];
+ pthread_t self = pthread_self();
+ size_t i = (random() & 0x0fffffff) % hosts->sl_cur;
+ char *host = hosts->sl_str[i];
+ struct addrinfo hints, *res;
+ int error, len;
+
+ if (debug) {
+ len = snprintf(buf, sizeof(buf), "%p: %d resolving %s %d\n",
+ self, n, host, (int)i);
+ (void)write(STDOUT_FILENO, buf, len);
+ }
+ switch (method) {
+ case METHOD_GETADDRINFO:
+ error = resolv_getaddrinfo(self, host, i);
+ break;
+ case METHOD_GETHOSTBY:
+ error = resolv_gethostby(self, host);
+ break;
+ case METHOD_GETIPNODEBY:
+ error = resolv_getipnodeby(self, host);
+ break;
+ default:
+ break;
+ }
+ pthread_mutex_lock(&stats);
+ ask[i]++;
+ got[i] += error == 0;
+ pthread_mutex_unlock(&stats);
+}
+
+static void *
+resolvloop(void *p)
+{
+ int *nhosts = (int *)p;
+ if (*nhosts == 0)
+ return;
+ do
+ resolvone(*nhosts);
+ while (--(*nhosts));
+ return NULL;
+}
+
+static void
+run(int *nhosts)
+{
+ pthread_t self = pthread_self();
+ if (pthread_create(&self, NULL, resolvloop, nhosts) != 0)
+ err(1, "pthread_create");
+}
+
+int
+main(int argc, char *argv[])
+{
+ int nthreads = NTHREADS;
+ int nhosts = NHOSTS;
+ int i, c, done, *nleft;
+ hosts = sl_init();
+
+ srandom(1234);
+
+ while ((c = getopt(argc, argv, "Adh:HIn:r")) != -1)
+ switch (c) {
+ case 'A':
+ method = METHOD_GETADDRINFO;
+ break;
+ case 'd':
+ debug++;
+ break;
+ case 'h':
+ nhosts = atoi(optarg);
+ break;
+ case 'H':
+ method = METHOD_GETHOSTBY;
+ break;
+ case 'I':
+ method = METHOD_GETIPNODEBY;
+ break;
+ case 'n':
+ nthreads = atoi(optarg);
+ break;
+ case 'r':
+ reverse++;
+ break;
+ default:
+ usage();
+ }
+
+ for (i = optind; i < argc; i++)
+ load(argv[i]);
+
+ if (hosts->sl_cur == 0)
+ usage();
+
+ if ((nleft = malloc(nthreads * sizeof(int))) == NULL)
+ err(1, "malloc");
+ if ((ask = calloc(hosts->sl_cur, sizeof(int))) == NULL)
+ err(1, "calloc");
+ if ((got = calloc(hosts->sl_cur, sizeof(int))) == NULL)
+ err(1, "calloc");
+
+
+ for (i = 0; i < nthreads; i++) {
+ nleft[i] = nhosts;
+ run(&nleft[i]);
+ }
+
+ for (done = 0; !done;) {
+ done = 1;
+ for (i = 0; i < nthreads; i++) {
+ if (nleft[i] != 0) {
+ done = 0;
+ break;
+ }
+ }
+ sleep(1);
+ }
+ c = 0;
+ for (i = 0; i < hosts->sl_cur; i++) {
+ if (ask[i] != got[i] && got[i] != 0) {
+ warnx("Error: host %s ask %d got %d\n",
+ hosts->sl_str[i], ask[i], got[i]);
+ c++;
+ }
+ }
+ free(nleft);
+ free(ask);
+ free(got);
+ sl_free(hosts, 1);
+ return c;
+}
diff --git a/tools/regression/lib/libc/resolv/resolv.t b/tools/regression/lib/libc/resolv/resolv.t
new file mode 100644
index 0000000..278ba06
--- /dev/null
+++ b/tools/regression/lib/libc/resolv/resolv.t
@@ -0,0 +1,24 @@
+#!/bin/sh
+# $FreeBSD$
+
+do_test() {
+ number=$1
+ comment=$2
+ opt=$3
+ if ./$executable $opt; then
+ echo "ok $number - $comment"
+ else
+ echo "not ok $number - $comment"
+ fi
+}
+
+cd `dirname $0`
+
+executable=`basename $0 .t`
+
+make $executable 2>&1 > /dev/null
+
+echo 1..3
+do_test 1 'getaddrinfo()' '-r mach'
+do_test 2 'gethostbyname()' '-rH mach'
+do_test 3 'getipnodebyname()' '-rI mach'
diff --git a/tools/regression/lib/libc/stdio/Makefile b/tools/regression/lib/libc/stdio/Makefile
new file mode 100644
index 0000000..35131e2
--- /dev/null
+++ b/tools/regression/lib/libc/stdio/Makefile
@@ -0,0 +1,12 @@
+# $FreeBSD$
+
+TESTS= test-perror test-printfloat test-scanfloat
+CFLAGS+= -lm
+
+.PHONY: tests
+tests: ${TESTS}
+ for p in ${TESTS}; do ${.OBJDIR}/$$p; done
+
+.PHONY: clean
+clean:
+ -rm -f ${TESTS}
diff --git a/tools/regression/lib/libc/stdio/test-perror.c b/tools/regression/lib/libc/stdio/test-perror.c
new file mode 100644
index 0000000..992b734
--- /dev/null
+++ b/tools/regression/lib/libc/stdio/test-perror.c
@@ -0,0 +1,107 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Test program for perror() as specified by IEEE Std. 1003.1-2001 and
+ * ISO/IEC 9899:1999.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <paths.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static void cleanup(void);
+static char tmpfil[PATH_MAX];
+
+int
+main(int argc, char *argv[])
+{
+ char lbuf[512];
+ int i;
+ char *s;
+
+ printf("1..1\n");
+
+ strcpy(tmpfil, _PATH_TMP "perror.XXXXXXXX");
+ if (mkstemp(tmpfil) < 0)
+ err(1, "mkstemp");
+ atexit(cleanup);
+ /* Reopen stderr on a file descriptor other than 2. */
+ fclose(stderr);
+ for (i = 0; i < 3; i++)
+ dup(0);
+ if (freopen(tmpfil, "r+", stderr) == NULL)
+ err(1, "%s", tmpfil);
+
+ /*
+ * Test that perror() doesn't call strerror() (4.4BSD bug),
+ * the two ways of omitting a program name, and the formatting when
+ * a program name is specified.
+ */
+ s = strerror(ENOENT);
+ assert(strcmp(s, "No such file or directory") == 0);
+ errno = EPERM;
+ perror(NULL);
+ perror("");
+ perror("test-perror");
+ assert(strcmp(s, "No such file or directory") == 0);
+
+ /*
+ * Read it back to check...
+ */
+ rewind(stderr);
+ s = fgets(lbuf, sizeof(lbuf), stderr);
+ assert(s != NULL);
+ assert(strcmp(s, "Operation not permitted\n") == 0);
+ s = fgets(lbuf, sizeof(lbuf), stderr);
+ assert(s != NULL);
+ assert(strcmp(s, "Operation not permitted\n") == 0);
+ s = fgets(lbuf, sizeof(lbuf), stderr);
+ assert(s != NULL);
+ assert(strcmp(s, "test-perror: Operation not permitted\n") == 0);
+ s = fgets(lbuf, sizeof(lbuf), stderr);
+ assert(s == NULL);
+ fclose(stderr);
+
+ printf("ok 1 - perror()\n");
+
+ return (0);
+}
+
+static void
+cleanup(void)
+{
+
+ unlink(tmpfil);
+}
diff --git a/tools/regression/lib/libc/stdio/test-perror.t b/tools/regression/lib/libc/stdio/test-perror.t
new file mode 100644
index 0000000..8bdfd03
--- /dev/null
+++ b/tools/regression/lib/libc/stdio/test-perror.t
@@ -0,0 +1,10 @@
+#!/bin/sh
+# $FreeBSD$
+
+cd `dirname $0`
+
+executable=`basename $0 .t`
+
+make $executable 2>&1 > /dev/null
+
+exec ./$executable
diff --git a/tools/regression/lib/libc/stdio/test-printfloat.c b/tools/regression/lib/libc/stdio/test-printfloat.c
new file mode 100644
index 0000000..5717a15
--- /dev/null
+++ b/tools/regression/lib/libc/stdio/test-printfloat.c
@@ -0,0 +1,341 @@
+/*-
+ * Copyright (c) 2002, 2005 David Schultz <das@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Test for printf() floating point formats.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <err.h>
+#include <fenv.h>
+#include <float.h>
+#include <locale.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define testfmt(result, fmt, ...) \
+ _testfmt((result), __LINE__, #__VA_ARGS__, fmt, __VA_ARGS__)
+void _testfmt(const char *, int, const char *, const char *, ...);
+void smash_stack(void);
+
+int
+main(int argc, char *argv[])
+{
+
+ printf("1..11\n");
+ assert(setlocale(LC_NUMERIC, ""));
+
+ /*
+ * Basic tests of decimal output functionality.
+ */
+ testfmt(" 1.000000E+00", "%13E", 1.0);
+ testfmt(" 1.000000", "%13f", 1.0);
+ testfmt(" 1", "%13G", 1.0);
+ testfmt(" 1.000000E+00", "%13LE", 1.0L);
+ testfmt(" 1.000000", "%13Lf", 1.0L);
+ testfmt(" 1", "%13LG", 1.0L);
+
+ testfmt("2.718282", "%.*f", -2, 2.7182818);
+
+ testfmt("1.234568e+06", "%e", 1234567.8);
+ testfmt("1234567.800000", "%f", 1234567.8);
+ testfmt("1.23457E+06", "%G", 1234567.8);
+ testfmt("1.234568e+06", "%Le", 1234567.8L);
+ testfmt("1234567.800000", "%Lf", 1234567.8L);
+ testfmt("1.23457E+06", "%LG", 1234567.8L);
+
+#if (LDBL_MANT_DIG > DBL_MANT_DIG) && !defined(__i386__)
+ testfmt("123456789.864210", "%Lf", 123456789.8642097531L);
+ testfmt("-1.23457E+08", "%LG", -123456789.8642097531L);
+ testfmt("123456789.8642097531", "%.10Lf", 123456789.8642097531L);
+ testfmt(" 3.141592653589793238e-4000", "%L27.18Le",
+ 3.14159265358979323846e-4000L);
+#endif
+
+ printf("ok 1 - printfloat\n");
+
+ /*
+ * Infinities and NaNs
+ */
+ testfmt("nan", "%e", NAN);
+ testfmt("NAN", "%F", NAN);
+ testfmt("nan", "%g", NAN);
+ testfmt("NAN", "%LE", (long double)NAN);
+ testfmt(" nan", "%05e", NAN);
+
+ testfmt("INF", "%E", HUGE_VAL);
+ testfmt("-inf", "%f", -HUGE_VAL);
+ testfmt("+inf", "%+g", HUGE_VAL);
+ testfmt(" inf", "%4.2Le", HUGE_VALL);
+ testfmt("-inf", "%Lf", -HUGE_VALL);
+ testfmt(" inf", "%05e", HUGE_VAL);
+ testfmt(" -inf", "%05e", -HUGE_VAL);
+
+ printf("ok 2 - printfloat\n");
+
+ /*
+ * Padding
+ */
+ testfmt("0.000000e+00", "%e", 0.0);
+ testfmt("0.000000", "%F", (double)0.0);
+ testfmt("0", "%G", 0.0);
+ testfmt(" 0", "%3.0Lg", 0.0L);
+ testfmt(" 0", "%5.0f", 0.001);
+ printf("ok 3 - printfloat\n");
+
+ /*
+ * Precision specifiers
+ */
+ testfmt("1.0123e+00", "%.4e", 1.0123456789);
+ testfmt("1.0123", "%.4f", 1.0123456789);
+ testfmt("1.012", "%.4g", 1.0123456789);
+ testfmt("1.2346e-02", "%.4e", 0.0123456789);
+ testfmt("0.0123", "%.4f", 0.0123456789);
+ testfmt("0.01235", "%.4g", 0.0123456789);
+ printf("ok 4 - printfloat\n");
+
+ /*
+ * Thousands' separators and other locale fun
+ */
+ testfmt("12345678.0625", "%'.04f", 12345678.0625);
+ testfmt("0012345678.0625", "%'015.4F", 12345678.0625);
+
+ assert(setlocale(LC_NUMERIC, "hi_IN.ISCII-DEV")); /* grouping == 2;3 */
+ testfmt("123,456,78.0625", "%'.4f", 12345678.0625);
+ testfmt("00123,456,78.0625", "%'017.4F", 12345678.0625);
+ testfmt(" 90,00", "%'6.0f", 9000.0);
+ testfmt("90,00.0", "%'.1f", 9000.0);
+
+ assert(setlocale(LC_NUMERIC, "ru_RU.ISO8859-5")); /* decimalpoint==, */
+ testfmt("3,1415", "%g", 3.1415);
+
+ /* thousands=. decimalpoint=, grouping=3;3 */
+ assert(setlocale(LC_NUMERIC, "el_GR.ISO8859-7")); /* decimalpoint==, */
+ testfmt("1.234,00", "%'.2f", 1234.00);
+ testfmt("123.456,789", "%'.3f", 123456.789);
+
+ assert(setlocale(LC_NUMERIC, ""));
+ testfmt("12345678.062500", "%'f", 12345678.0625);
+ testfmt("9000.000000", "%'f", 9000.0);
+
+ printf("ok 5 - printfloat\n");
+
+ /*
+ * Signed conversions
+ */
+ testfmt("+2.500000e-01", "%+e", 0.25);
+ testfmt("+0.000000", "%+F", 0.0);
+ testfmt("-1", "%+g", -1.0);
+
+ testfmt("-1.000000e+00", "% e", -1.0);
+ testfmt("+1.000000", "% +f", 1.0);
+ testfmt(" 1", "% g", 1.0);
+ testfmt(" 0", "% g", 0.0);
+
+ printf("ok 6 - printfloat\n");
+
+ /*
+ * ``Alternate form''
+ */
+ testfmt("1.250e+00", "%#.3e", 1.25);
+ testfmt("123.000000", "%#f", 123.0);
+ testfmt(" 12345.", "%#7.5g", 12345.0);
+ testfmt(" 1.00000", "%#8g", 1.0);
+ testfmt("0.0", "%#.2g", 0.0);
+ printf("ok 7 - printfloat\n");
+
+ /*
+ * Padding and decimal point placement
+ */
+ testfmt("03.2E+00", "%08.1E", 3.25);
+ testfmt("003.25", "%06.2F", 3.25);
+ testfmt("0003.25", "%07.4G", 3.25);
+
+ testfmt("3.14159e-05", "%g", 3.14159e-5);
+ testfmt("0.000314159", "%g", 3.14159e-4);
+ testfmt("3.14159e+06", "%g", 3.14159e6);
+ testfmt("314159", "%g", 3.14159e5);
+ testfmt("314159.", "%#g", 3.14159e5);
+
+ testfmt(" 9.000000e+03", "%13e", 9000.0);
+ testfmt(" 9000.000000", "%12f", 9000.0);
+ testfmt(" 9000", "%5g", 9000.0);
+ testfmt(" 900000.", "%#8g", 900000.0);
+ testfmt(" 9e+06", "%6g", 9000000.0);
+ testfmt(" 9.000000e-04", "%13e", 0.0009);
+ testfmt(" 0.000900", "%9f", 0.0009);
+ testfmt(" 0.0009", "%7g", 0.0009);
+ testfmt(" 9e-05", "%6g", 0.00009);
+ testfmt(" 9.00000e-05", "%#12g", 0.00009);
+ testfmt(" 9.e-05", "%#7.1g", 0.00009);
+
+ testfmt(" 0.0", "%4.1f", 0.0);
+ testfmt("90.0", "%4.1f", 90.0);
+ testfmt(" 100", "%4.0f", 100.0);
+ testfmt("9.0e+01", "%4.1e", 90.0);
+ testfmt("1e+02", "%4.0e", 100.0);
+
+ printf("ok 8 - printfloat\n");
+
+ /*
+ * Decimal rounding
+ */
+ fesetround(FE_DOWNWARD);
+ testfmt("4.437", "%.3f", 4.4375);
+ testfmt("-4.438", "%.3f", -4.4375);
+ testfmt("4.437", "%.3Lf", 4.4375L);
+ testfmt("-4.438", "%.3Lf", -4.4375L);
+
+ fesetround(FE_UPWARD);
+ testfmt("4.438", "%.3f", 4.4375);
+ testfmt("-4.437", "%.3f", -4.4375);
+ testfmt("4.438", "%.3Lf", 4.4375L);
+ testfmt("-4.437", "%.3Lf", -4.4375L);
+
+ fesetround(FE_TOWARDZERO);
+ testfmt("4.437", "%.3f", 4.4375);
+ testfmt("-4.437", "%.3f", -4.4375);
+ testfmt("4.437", "%.3Lf", 4.4375L);
+ testfmt("-4.437", "%.3Lf", -4.4375L);
+
+ fesetround(FE_TONEAREST);
+ testfmt("4.438", "%.3f", 4.4375);
+ testfmt("-4.438", "%.3f", -4.4375);
+ testfmt("4.438", "%.3Lf", 4.4375L);
+ testfmt("-4.438", "%.3Lf", -4.4375L);
+
+ printf("ok 9 - printfloat\n");
+
+ /*
+ * Hexadecimal floating point (%a, %A) tests. Some of these
+ * are only valid if the implementation converts to hex digits
+ * on nibble boundaries.
+ */
+ testfmt("0x0p+0", "%a", 0x0.0p0);
+ testfmt("0X0.P+0", "%#LA", 0x0.0p0L);
+ testfmt("inf", "%La", (long double)INFINITY);
+ testfmt("+INF", "%+A", INFINITY);
+ testfmt("nan", "%La", (long double)NAN);
+ testfmt("NAN", "%A", NAN);
+
+ testfmt(" 0x1.23p+0", "%10a", 0x1.23p0);
+ testfmt(" 0x1.23p-500", "%12a", 0x1.23p-500);
+ testfmt(" 0x1.2p+40", "%10.1a", 0x1.23p40);
+ testfmt(" 0X1.230000000000000000000000P-4", "%32.24A", 0x1.23p-4);
+ testfmt("0x1p-1074", "%a", 0x1p-1074);
+ testfmt("0x1.2345p-1024", "%a", 0x1.2345p-1024);
+
+#if (LDBL_MANT_DIG == 64) && !defined(__i386__)
+ testfmt("0xc.90fdaa22168c234p-2", "%La", 0x3.243f6a8885a308dp0L);
+ testfmt("0x8p-16448", "%La", 0x1p-16445L);
+ testfmt("0x9.8765p-16384", "%La", 0x9.8765p-16384L);
+#elif (LDBL_MANT_DIG == 113)
+ testfmt("0x1.921fb54442d18469898cc51701b8p+1", "%La",
+ 0x3.243f6a8885a308d313198a2e037p0L);
+ testfmt("0x1p-16494", "%La", 0x1p-16494L);
+ testfmt("0x1.2345p-16384", "%La", 0x1.2345p-16384L);
+#else
+ testfmt("0xc.90fdaa22168cp-2", "%La", 0x3.243f6a8885a31p0L);
+ testfmt("0x8p-1077", "%La", 0x1p-1074L);
+ testfmt("0x9.8765p-1024", "%La", 0x9.8765p-1024L);
+#endif
+
+ printf("ok 10 - printfloat\n");
+
+ /*
+ * Hexadecimal rounding
+ */
+ fesetround(FE_TOWARDZERO);
+ testfmt("0X1.23456789ABCP+0", "%.11A", 0x1.23456789abcdep0);
+ testfmt("-0x1.23456p+0", "%.5a", -0x1.23456789abcdep0);
+ testfmt("0x1.23456p+0", "%.5a", 0x1.23456789abcdep0);
+ testfmt("0x1.234567p+0", "%.6a", 0x1.23456789abcdep0);
+ testfmt("-0x1.234566p+0", "%.6a", -0x1.23456689abcdep0);
+
+ fesetround(FE_DOWNWARD);
+ testfmt("0X1.23456789ABCP+0", "%.11A", 0x1.23456789abcdep0);
+ testfmt("-0x1.23457p+0", "%.5a", -0x1.23456789abcdep0);
+ testfmt("0x1.23456p+0", "%.5a", 0x1.23456789abcdep0);
+ testfmt("0x1.234567p+0", "%.6a", 0x1.23456789abcdep0);
+ testfmt("-0x1.234567p+0", "%.6a", -0x1.23456689abcdep0);
+
+ fesetround(FE_UPWARD);
+ testfmt("0X1.23456789ABDP+0", "%.11A", 0x1.23456789abcdep0);
+ testfmt("-0x1.23456p+0", "%.5a", -0x1.23456789abcdep0);
+ testfmt("0x1.23457p+0", "%.5a", 0x1.23456789abcdep0);
+ testfmt("0x1.234568p+0", "%.6a", 0x1.23456789abcdep0);
+ testfmt("-0x1.234566p+0", "%.6a", -0x1.23456689abcdep0);
+
+ fesetround(FE_TONEAREST);
+ testfmt("0x1.23456789abcdep+4", "%a", 0x1.23456789abcdep4);
+ testfmt("0X1.23456789ABDP+0", "%.11A", 0x1.23456789abcdep0);
+ testfmt("-0x1.23456p+0", "%.5a", -0x1.23456789abcdep0);
+ testfmt("0x1.23456p+0", "%.5a", 0x1.23456789abcdep0);
+ testfmt("0x1.234568p+0", "%.6a", 0x1.23456789abcdep0);
+ testfmt("-0x1.234567p+0", "%.6a", -0x1.23456689abcdep0);
+ testfmt("0x2.00p-1030", "%.2a", 0x1.fffp-1030);
+ testfmt("0x2.00p-1027", "%.2a", 0xf.fffp-1030);
+ testfmt("0x1.83p+0", "%.2a", 1.51);
+
+ printf("ok 11 - printfloat\n");
+
+ return (0);
+}
+
+void
+smash_stack(void)
+{
+ static uint32_t junk = 0xdeadbeef;
+ uint32_t buf[512];
+ int i;
+
+ for (i = 0; i < sizeof(buf) / sizeof(buf[0]); i++)
+ buf[i] = junk;
+}
+
+void
+_testfmt(const char *result, int line, const char *argstr, const char *fmt,...)
+{
+ char s[100];
+ va_list ap;
+
+ va_start(ap, fmt);
+ smash_stack();
+ vsnprintf(s, sizeof(s), fmt, ap);
+ if (strcmp(result, s) != 0) {
+ fprintf(stderr,
+ "%d: printf(\"%s\", %s) ==> [%s], expected [%s]\n",
+ line, fmt, argstr, s, result);
+ abort();
+ }
+}
diff --git a/tools/regression/lib/libc/stdio/test-printfloat.t b/tools/regression/lib/libc/stdio/test-printfloat.t
new file mode 100644
index 0000000..8bdfd03
--- /dev/null
+++ b/tools/regression/lib/libc/stdio/test-printfloat.t
@@ -0,0 +1,10 @@
+#!/bin/sh
+# $FreeBSD$
+
+cd `dirname $0`
+
+executable=`basename $0 .t`
+
+make $executable 2>&1 > /dev/null
+
+exec ./$executable
diff --git a/tools/regression/lib/libc/stdio/test-scanfloat.c b/tools/regression/lib/libc/stdio/test-scanfloat.c
new file mode 100644
index 0000000..ef6faae
--- /dev/null
+++ b/tools/regression/lib/libc/stdio/test-scanfloat.c
@@ -0,0 +1,293 @@
+/*-
+ * Copyright (C) 2003, 2005 David Schultz <das@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Test for scanf() floating point formats.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <fenv.h>
+#include <float.h>
+#include <locale.h>
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+
+#define eq(type, a, b) _eq(type##_EPSILON, (a), (b))
+static int _eq(long double epsilon, long double a, long double b);
+
+extern int __scanfdebug;
+
+int
+main(int argc, char *argv[])
+{
+ char buf[128];
+ long double ld = 0.0;
+ double d = 0.0;
+ float f = 0.0;
+
+ printf("1..3\n");
+
+ buf[0] = '\0';
+ assert(setlocale(LC_NUMERIC, ""));
+
+ __scanfdebug = 1;
+
+ /*
+ * Various tests for normalized numbers
+ */
+ sscanf("3.141592", "%e", &f);
+ assert(eq(FLT, f, 3.141592));
+
+ sscanf("3.141592653589793", "%lf", &d);
+ assert(eq(DBL, d, 3.141592653589793));
+
+ sscanf("1.234568e+06", "%E", &f);
+ assert(eq(FLT, f, 1.234568e+06));
+
+ sscanf("-1.234568e6", "%lF", &d);
+ assert(eq(DBL, d, -1.234568e6));
+
+ sscanf("+1.234568e-52", "%LG", &ld);
+ assert(eq(LDBL, ld, 1.234568e-52L));
+
+ sscanf("0.1", "%la", &d);
+ assert(eq(DBL, d, 0.1));
+
+ sscanf("00.2", "%lA", &d);
+ assert(eq(DBL, d, 0.2));
+
+ sscanf("123456", "%5le%s", &d, buf);
+ assert(eq(DBL, d, 12345.));
+ assert(strcmp(buf, "6") == 0);
+
+ sscanf("1.0Q", "%*5le%s", buf);
+ assert(strcmp(buf, "Q") == 0);
+
+ sscanf("-1.23e", "%e%s", &f, buf);
+ assert(eq(FLT, f, -1.23));
+ assert(strcmp(buf, "e") == 0);
+
+ sscanf("1.25e+", "%le%s", &d, buf);
+ assert(eq(DBL, d, 1.25));
+ assert(strcmp(buf, "e+") == 0);
+
+ sscanf("1.23E4E5", "%le%s", &d, buf);
+ assert(eq(DBL, d, 1.23e4));
+ assert(strcmp(buf, "E5") == 0);
+
+ sscanf("12e6", "%le", &d);
+ assert(eq(DBL, d, 12e6));
+
+ sscanf("1.a", "%le%s", &d, buf);
+ assert(eq(DBL, d, 1.0));
+ assert(strcmp(buf, "a") == 0);
+
+ sscanf(".0p4", "%le%s", &d, buf);
+ assert(eq(DBL, d, 0.0));
+ assert(strcmp(buf, "p4") == 0);
+
+ d = 0.25;
+ assert(sscanf(".", "%le", &d) == 0);
+ assert(d == 0.25);
+
+ sscanf("0x08", "%le", &d);
+ assert(d == 0x8p0);
+
+ sscanf("0x90a.bcdefP+09a", "%le%s", &d, buf);
+ assert(d == 0x90a.bcdefp+09);
+ assert(strcmp(buf, "a") == 0);
+
+#if (LDBL_MANT_DIG > DBL_MANT_DIG) && !defined(__i386__)
+ sscanf("3.14159265358979323846", "%Lg", &ld);
+ assert(eq(LDBL, ld, 3.14159265358979323846L));
+
+ sscanf(" 0X.0123456789abcdefffp-3g", "%Le%s", &ld, buf);
+ assert(ld == 0x0.0123456789abcdefffp-3L);
+ assert(strcmp(buf, "g") == 0);
+#endif
+
+ sscanf("0xg", "%le%s", &d, buf);
+ assert(d == 0.0);
+ assert(strcmp(buf, "xg") == 0);
+
+ assert(setlocale(LC_NUMERIC, "ru_RU.ISO8859-5")); /* decimalpoint==, */
+
+ sscanf("1.23", "%le%s", &d, buf);
+ assert(d == 1.0);
+ assert(strcmp(buf, ".23") == 0);
+
+ sscanf("1,23", "%le", &d);
+ assert(d == 1.23);
+
+ assert(setlocale(LC_NUMERIC, ""));
+
+ printf("ok 1 - scanfloat\n");
+
+ /*
+ * Infinity and NaN tests
+ */
+ sscanf("-Inf", "%le", &d);
+ assert(d < 0.0 && isinf(d));
+
+ sscanf("iNfInItY and beyond", "%le%s", &d, buf);
+ assert(d > 0.0 && isinf(d));
+ assert(strcmp(buf, " and beyond"));
+
+ sscanf("NaN", "%le", &d);
+ assert(isnan(d));
+
+ sscanf("NAN(123Y", "%le%s", &d, buf);
+ assert(isnan(d));
+ assert(strcmp(buf, "(123Y") == 0);
+
+ sscanf("nan(f00f)plugh", "%le%s", &d, buf);
+ assert(isnan(d));
+ assert(strcmp(buf, "plugh") == 0);
+
+ sscanf("-nan", "%le", &d);
+ assert(isnan(d));
+
+ /* Only quiet NaNs should be returned. */
+ sscanf("NaN", "%e", &f);
+ sscanf("nan", "%le", &d);
+ sscanf("nan", "%Le", &ld);
+ feclearexcept(FE_ALL_EXCEPT);
+ assert(f != f);
+ assert(d != d);
+ assert(ld != ld);
+ assert(fetestexcept(FE_INVALID) == 0);
+ sscanf("nan(1234)", "%e", &f);
+ sscanf("nan(1234)", "%le", &d);
+ sscanf("nan(1234)", "%Le", &ld);
+ feclearexcept(FE_ALL_EXCEPT);
+ assert(f != f);
+ assert(d != d);
+ assert(ld != ld);
+#if 0
+ /*
+ * POSIX says we should only generate quiet NaNs, but the gdtoa
+ * author convincingly argues that if you ask for a NaN format
+ * based on some implementation-defined string, you should get
+ * what you asked for, even if it's a signaling NaN.
+ */
+ assert(fetestexcept(FE_INVALID) == 0);
+#endif
+
+ printf("ok 2 - scanfloat\n");
+
+ /*
+ * Rounding tests
+ */
+
+ fesetround(FE_DOWNWARD);
+
+ sscanf("1.999999999999999999999999999999999", "%le", &d);
+ assert(d < 2.0);
+ sscanf("0x1.ffffffffffffffp0", "%le", &d);
+ assert(d < 2.0);
+ sscanf("1.999999999999999999999999999999999", "%Le", &ld);
+ assert(ld < 2.0);
+
+ sscanf("1.0571892669084007", "%le", &d);
+ assert(d == 0x1.0ea3f4af0dc59p0);
+ sscanf("-1.0571892669084007", "%le", &d);
+ assert(d == -0x1.0ea3f4af0dc5ap0);
+ sscanf("1.0571892669084010", "%le", &d);
+ assert(d == 0x1.0ea3f4af0dc5ap0);
+
+ sscanf("0x1.23p-5000", "%le", &d);
+ assert(d == 0.0);
+
+ sscanf("0x1.2345678p-1050", "%le", &d);
+ assert(d == 0x1.234567p-1050);
+
+ fesetround(FE_UPWARD);
+
+ sscanf("1.0571892669084007", "%le", &d);
+ assert(d == 0x1.0ea3f4af0dc5ap0);
+ sscanf("-1.0571892669084007", "%le", &d);
+ assert(d == -0x1.0ea3f4af0dc59p0);
+ sscanf("1.0571892669084010", "%le", &d);
+ assert(d == 0x1.0ea3f4af0dc5bp0);
+
+ sscanf("0x1.23p-5000", "%le", &d);
+ assert(d == 0x1p-1074);
+
+ sscanf("0x1.2345678p-1050", "%le", &d);
+ assert(d == 0x1.234568p-1050);
+
+ fesetround(FE_TOWARDZERO);
+
+ sscanf("1.0571892669084007", "%le", &d);
+ assert(d == 0x1.0ea3f4af0dc59p0);
+ sscanf("-1.0571892669084007", "%le", &d);
+ assert(d == -0x1.0ea3f4af0dc59p0);
+ sscanf("1.0571892669084010", "%le", &d);
+ assert(d == 0x1.0ea3f4af0dc5ap0);
+
+ sscanf("0x1.23p-5000", "%le", &d);
+ assert(d == 0.0);
+
+ sscanf("0x1.2345678p-1050", "%le", &d);
+ assert(d == 0x1.234567p-1050);
+
+ fesetround(FE_TONEAREST);
+
+ /* 1.0571892669084007 is slightly closer to 0x1.0ea3f4af0dc59p0 */
+ sscanf("1.0571892669084007", "%le", &d);
+ assert(d == 0x1.0ea3f4af0dc59p0);
+ sscanf("-1.0571892669084007", "%le", &d);
+ assert(d == -0x1.0ea3f4af0dc59p0);
+ sscanf("1.0571892669084010", "%le", &d);
+ assert(d == 0x1.0ea3f4af0dc5bp0);
+
+ /* strtod() should round small numbers to 0. */
+ sscanf("0x1.23p-5000", "%le", &d);
+ assert(d == 0.0);
+
+ /* Extra digits in a denormal shouldn't break anything. */
+ sscanf("0x1.2345678p-1050", "%le", &d);
+ assert(d == 0x1.234568p-1050);
+
+ printf("ok 3 - scanfloat\n");
+
+ return (0);
+}
+
+static int
+_eq(long double epsilon, long double a, long double b)
+{
+ long double delta;
+
+ delta = a - b;
+ if (delta < 0) /* XXX no fabsl() */
+ delta = -delta;
+ return (delta <= epsilon);
+}
diff --git a/tools/regression/lib/libc/stdio/test-scanfloat.t b/tools/regression/lib/libc/stdio/test-scanfloat.t
new file mode 100644
index 0000000..8bdfd03
--- /dev/null
+++ b/tools/regression/lib/libc/stdio/test-scanfloat.t
@@ -0,0 +1,10 @@
+#!/bin/sh
+# $FreeBSD$
+
+cd `dirname $0`
+
+executable=`basename $0 .t`
+
+make $executable 2>&1 > /dev/null
+
+exec ./$executable
diff --git a/tools/regression/lib/libc/stdlib/Makefile b/tools/regression/lib/libc/stdlib/Makefile
new file mode 100644
index 0000000..c707795
--- /dev/null
+++ b/tools/regression/lib/libc/stdlib/Makefile
@@ -0,0 +1,13 @@
+# $FreeBSD$
+
+TESTS= test-qsort \
+ test-heapsort \
+ test-mergesort
+
+.PHONY: tests
+tests: ${TESTS}
+ for p in ${TESTS}; do ${.OBJDIR}/$$p; done
+
+.PHONY: clean
+clean:
+ -rm -f ${TESTS}
diff --git a/tools/regression/lib/libc/stdlib/test-heapsort.c b/tools/regression/lib/libc/stdlib/test-heapsort.c
new file mode 100644
index 0000000..6ce8924
--- /dev/null
+++ b/tools/regression/lib/libc/stdlib/test-heapsort.c
@@ -0,0 +1,66 @@
+/*-
+ * Copyright (C) 2004 Maxim Sobolev <sobomax@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Test for heapsort() routine.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "test-sort.h"
+
+int
+main(int argc, char *argv[])
+{
+ int i, j;
+ int testvector[IVEC_LEN];
+ int sresvector[IVEC_LEN];
+
+ printf("1..1\n");
+ for (j = 2; j < IVEC_LEN; j++) {
+ /* Populate test vectors */
+ for (i = 0; i < j; i++)
+ testvector[i] = sresvector[i] = initvector[i];
+
+ /* Sort using heapsort(3) */
+ heapsort(testvector, j, sizeof(testvector[0]), sorthelp);
+ /* Sort using reference slow sorting routine */
+ ssort(sresvector, j);
+
+ /* Compare results */
+ for (i = 0; i < j; i++)
+ assert(testvector[i] == sresvector[i]);
+ }
+
+ printf("ok 1 - heapsort\n");
+
+ return(0);
+}
diff --git a/tools/regression/lib/libc/stdlib/test-heapsort.t b/tools/regression/lib/libc/stdlib/test-heapsort.t
new file mode 100644
index 0000000..8bdfd03
--- /dev/null
+++ b/tools/regression/lib/libc/stdlib/test-heapsort.t
@@ -0,0 +1,10 @@
+#!/bin/sh
+# $FreeBSD$
+
+cd `dirname $0`
+
+executable=`basename $0 .t`
+
+make $executable 2>&1 > /dev/null
+
+exec ./$executable
diff --git a/tools/regression/lib/libc/stdlib/test-mergesort.c b/tools/regression/lib/libc/stdlib/test-mergesort.c
new file mode 100644
index 0000000..729d481
--- /dev/null
+++ b/tools/regression/lib/libc/stdlib/test-mergesort.c
@@ -0,0 +1,66 @@
+/*-
+ * Copyright (C) 2004 Maxim Sobolev <sobomax@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Test for mergesort() routine.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "test-sort.h"
+
+int
+main(int argc, char *argv[])
+{
+ int i, j;
+ int testvector[IVEC_LEN];
+ int sresvector[IVEC_LEN];
+
+ printf("1..1\n");
+ for (j = 2; j < IVEC_LEN; j++) {
+ /* Populate test vectors */
+ for (i = 0; i < j; i++)
+ testvector[i] = sresvector[i] = initvector[i];
+
+ /* Sort using mergesort(3) */
+ mergesort(testvector, j, sizeof(testvector[0]), sorthelp);
+ /* Sort using reference slow sorting routine */
+ ssort(sresvector, j);
+
+ /* Compare results */
+ for (i = 0; i < j; i++)
+ assert(testvector[i] == sresvector[i]);
+ }
+
+ printf("ok 1 - mergesort\n");
+
+ return(0);
+}
diff --git a/tools/regression/lib/libc/stdlib/test-mergesort.t b/tools/regression/lib/libc/stdlib/test-mergesort.t
new file mode 100644
index 0000000..8bdfd03
--- /dev/null
+++ b/tools/regression/lib/libc/stdlib/test-mergesort.t
@@ -0,0 +1,10 @@
+#!/bin/sh
+# $FreeBSD$
+
+cd `dirname $0`
+
+executable=`basename $0 .t`
+
+make $executable 2>&1 > /dev/null
+
+exec ./$executable
diff --git a/tools/regression/lib/libc/stdlib/test-qsort.c b/tools/regression/lib/libc/stdlib/test-qsort.c
new file mode 100644
index 0000000..8a508e8
--- /dev/null
+++ b/tools/regression/lib/libc/stdlib/test-qsort.c
@@ -0,0 +1,66 @@
+/*-
+ * Copyright (C) 2004 Maxim Sobolev <sobomax@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Test for qsort() routine.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "test-sort.h"
+
+int
+main(int argc, char *argv[])
+{
+ int i, j;
+ int testvector[IVEC_LEN];
+ int sresvector[IVEC_LEN];
+
+ printf("1..1\n");
+ for (j = 2; j < IVEC_LEN; j++) {
+ /* Populate test vectors */
+ for (i = 0; i < j; i++)
+ testvector[i] = sresvector[i] = initvector[i];
+
+ /* Sort using qsort(3) */
+ qsort(testvector, j, sizeof(testvector[0]), sorthelp);
+ /* Sort using reference slow sorting routine */
+ ssort(sresvector, j);
+
+ /* Compare results */
+ for (i = 0; i < j; i++)
+ assert(testvector[i] == sresvector[i]);
+ }
+
+ printf("ok 1 - qsort\n");
+
+ return(0);
+}
diff --git a/tools/regression/lib/libc/stdlib/test-qsort.t b/tools/regression/lib/libc/stdlib/test-qsort.t
new file mode 100644
index 0000000..8bdfd03
--- /dev/null
+++ b/tools/regression/lib/libc/stdlib/test-qsort.t
@@ -0,0 +1,10 @@
+#!/bin/sh
+# $FreeBSD$
+
+cd `dirname $0`
+
+executable=`basename $0 .t`
+
+make $executable 2>&1 > /dev/null
+
+exec ./$executable
diff --git a/tools/regression/lib/libc/stdlib/test-sort.h b/tools/regression/lib/libc/stdlib/test-sort.h
new file mode 100644
index 0000000..e060f72
--- /dev/null
+++ b/tools/regression/lib/libc/stdlib/test-sort.h
@@ -0,0 +1,269 @@
+/*-
+ * Copyright (C) 2004 Maxim Sobolev <sobomax@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _TEST_SORT_H
+#define _TEST_SORT_H
+
+static int
+sorthelp(const void *a, const void *b)
+{
+ const int *oa, *ob;
+
+ oa = a;
+ ob = b;
+ /* Don't use "return *oa - *ob" since it's easy to cause overflow! */
+ if (*oa > *ob)
+ return 1;
+ if (*oa < *ob)
+ return -1;
+ return 0;
+}
+
+/* Reference sorting routine (slooow!) */
+static void
+ssort(int v[], int nmemb)
+{
+ int i, j, k;
+
+ for (i = 0; i < nmemb; i++) {
+ for (j = i + 1; j < nmemb; j++) {
+ if (v[j] < v[i]) {
+ k = v[i];
+ v[i] = v[j];
+ v[j] = k;
+ }
+ }
+ }
+}
+
+/* Some random data */
+static int initvector[1024] = {
+ 599853225, 371951333, -428880425, 1450668530, 85530178, -460170550,
+ -270680269, 717137591, 106244401, -1138072905, -113532586,
+ 599690958, 464993720, 107690177, 24249019, -1151018550, 794225588,
+ 1494905642, -62951716, -734531757, 1197251494, 1020063925,
+ -634536734, -216634704, 617366508, -18840190, 481010395,
+ -1555785724, 128221950, -1747743676, 1119012320, -252160437,
+ 617137855, 1159833073, -106647920, -1570719046, -769400990,
+ -130308848, 1186546396, 215253591, 445832488, 160263176, 777264170,
+ -274636650, -696134447, 1057957088, -626175254, 188632134,
+ -98941793, -1602334908, -373717125, 885013862, 571258221,
+ -399572192, 407761463, -733249776, 12094800, -367046815, 178974501,
+ -452638559, -516580143, -94282073, 1411115180, -1151792797,
+ 1442815268, 1106583674, 515269284, -74019972, 598818901, 696848474,
+ -657910766, -287309335, 1538095746, 143543003, 851444033,
+ -947573348, 296222973, 1339592140, -947505360, 872027891,
+ -418844714, -583075597, -324758197, -964531573, 1016795914,
+ -866842580, -304084402, -286930819, 338975583, 803597943,
+ -452483372, 1525283506, -1185830826, -596405894, 905191340,
+ -1638026278, 106749913, 582771197, -730713796, 56052422,
+ 1498040174, 644967266, 182541575, 280483468, -1932835017,
+ -435546874, 940106007, 1753388509, -340355019, -231577358,
+ -714879035, 1051182949, 204261785, 1321346243, -895289878,
+ -240369893, 566608506, -350777580, -1384849829, -876816409,
+ 1013787299, -1408035937, -222626650, 1708168486, -645148461,
+ 1854654, -393012507, 179327030, -1607975548, -715202732, 730588290,
+ 246968517, -550975254, -101136772, -174103176, 1188941016,
+ 2004650834, -1501389866, -2021225998, 1219042515, -464113898,
+ 268565342, 126451123, -1045877126, -198918003, 310177444,
+ 1578314812, 1828867082, 453336898, -908485523, 749777130,
+ -1028565802, 61360571, 241484853, -175693399, 1816211059,
+ 533940889, -1496933703, 385185125, -821132413, -8923391,
+ -1429546239, 46190992, 449247332, -20432494, 778761611, -178782699,
+ -811194695, -632276211, 70196094, 890817525, -1447776908,
+ -323783741, -62333222, 954929503, 247668507, -1394420605,
+ 367913886, 1364926759, 1298781924, 357923028, -73644747,
+ -319744305, 61718202, -1454549286, 387493522, 2018321449,
+ 861026653, 289973298, 1755939093, -84772204, 43425266, -1325753781,
+ -679938775, 1228500370, -763816405, 548903035, 1765563727,
+ 425183052, 1424621863, -188287424, 554385654, 751831998,
+ 1377088085, 66622090, 139224450, -1305816167, 650140724, 593988868,
+ -444913321, 589045097, 1261428989, 101292769, -780376786,
+ 559307348, 1644593236, -1838606833, 53570301, -680576100,
+ -44969538, 268718267, -632104125, 276904628, 626299449, -11761453,
+ 545899086, -1027343598, -432251872, 539353494, -399575006,
+ -568383580, -677802882, 1296513472, 801202048, 806425805, 1983363,
+ 850487421, 38046173, 1535399484, 1998285544, -1301751898,
+ -46561973, 56545408, -1107662676, 456041145, -452923904,
+ -262219453, -371849200, 392524281, 1650231392, 1185585356,
+ 126610511, -1125389657, 1015981177, -1318481342, -213835789,
+ 1263484054, -654361441, 1408272041, -231555284, -1121778152,
+ -395512897, 332277674, -349703586, 1809474399, -223731607,
+ -1342224737, 736165236, 67535587, 89879082, 471445838, 423788300,
+ -384354470, 907475706, 154886390, -1406736539, -8558766,
+ -203405718, -422127884, 1048520863, 747418501, 87438975, 727668160,
+ -914936981, 428266976, -455742009, -949014605, 487159058,
+ -262526850, -309451504, -76928461, 1072951428, -1370953830,
+ 238231681, -1831047244, -405735199, -35941848, 469048670,
+ 505307987, -660553590, 876537439, -314195871, 999234339,
+ -1405846240, -579885695, 629067031, 863481510, -742301385,
+ -1723403128, -153070386, 782682839, -343111818, -877101810,
+ 1438467302, -319951459, -1585702508, -338381888, 484108815,
+ -1726935191, -749923706, 1657932127, -816151395, -566321865,
+ -133542331, 84961164, 598275578, 1302065347, -533098653,
+ -1766383037, 53169714, -464201288, 617735133, 862536123,
+ -141730724, -1967377125, -1023736305, -1012511106, 64484992,
+ -1250856831, 426409332, -355670055, -298251663, -867634978,
+ -776124819, 74018333, -425385214, -108004251, -1192766130,
+ 1294193867, -109867195, -78667637, 1164855393, -826007552,
+ -522528066, 1160283046, -1095276403, -1218917472, -396475366,
+ -77394733, -425603169, 251928357, -393559355, 1488845184,
+ 898455978, -773338691, -37627855, -345014717, 204298578, 209084274,
+ 1047080643, -414348222, 26496664, 705759824, 575149152, 604904761,
+ 624988690, 1446041250, 1000757225, -1354896151, 1422958189,
+ -1607165311, -832757521, 365074225, 1171764999, 1200795217,
+ -203957828, 23166236, -846818698, -547439867, -790192498,
+ -122123561, 914298013, 66225525, -36163174, -480698856,
+ -1269421818, 624641703, 254923102, 1564329013, -583609221,
+ -649433551, -743396069, 1182455435, 102658744, 285599336,
+ 692480463, -852737563, -660090184, 1374350065, 72300985, 690541659,
+ -1194212957, -1151816525, 157415641, 487398246, 1030153072,
+ 933723020, 1359181027, -1303457764, -1543773272, 774306017,
+ -854382652, 755485667, -864943584, -63242545, -1271480354,
+ 157720215, -205001173, 889984130, -581583822, -473779111,
+ -932136577, 735326252, 428638717, 1888884222, 561493709,
+ -1966427364, -1710208603, 340121869, 918894036, 927172509,
+ 904178436, 1476687667, 90796414, 651591731, -550913123, -42218158,
+ 637756529, 1091478400, 124976584, -48739309, -798898083, 393581349,
+ -1078624722, -789291577, 1010582542, -512317005, 1222773656,
+ 466454593, 1183558811, 822782663, -851624703, -850404012,
+ 1473672600, 852527073, 1073953362, 137635828, 936104739, -86567759,
+ -882563252, 1845232980, -737978404, -104703380, 149802989,
+ -349118325, 1479797538, 1966007488, 1254228842, 414304661,
+ -790805785, 31583329, -76864151, 558202855, -1447047313, 716720607,
+ -404224238, -54107627, 1747385914, -657407390, 202940208,
+ 1083067056, -532861378, 163426933, -130289277, 1301785258,
+ -302920320, -637947485, -644895903, -1668027530, 391890467,
+ -126586485, -536836984, -1154536413, -339505118, -1187229462,
+ -670985870, -601310813, -1350055158, -482479784, 139847714,
+ -253955849, 5190414, -542857077, 1175835684, -584165057,
+ 1132775766, -592091269, -891445655, -340995936, 736395810,
+ 779967964, 515095845, -1138437307, -259226729, -167820100,
+ -801611617, -282451622, -1313679283, -1436126694, 1258773990,
+ -717601098, -583559645, -1307478759, 1238647247, 1589011223,
+ -1029216445, -107030650, 400152690, -1349079913, 1428582247,
+ 21546946, 208807686, -169450574, -1086213374, -1242715198,
+ 669098277, 416626722, -1122525014, -1389466669, -391843085,
+ -56318357, 421040094, 212303518, 738666684, -1185364904,
+ -506192760, 646735912, -1424722633, 745226976, 1019191717,
+ -190891744, -310320868, -373655022, -665117060, 830760000,
+ 583906512, -330536027, 611092636, -321344259, -1255008904,
+ -777959046, -523043472, 88896910, 346062204, -163734816, 336635665,
+ 906060268, -128891583, 740952564, 916767203, 296514859, 198670559,
+ 358136672, -152253676, 12038867, -1469916749, -1020980597,
+ -897143313, 354240970, -97959800, 814172811, 1983363241, 264990663,
+ 105154676, 1060463014, 430172143, 375111946, -824526943,
+ -708877751, -1377442616, -236559551, 684724584, 1602131358,
+ -42140186, -763499840, -605167, 98575879, -376577598, 1689746083,
+ -777973879, -1396984691, -187780326, 281040966, 1858859521,
+ 158395760, 1022807978, -218458812, 811779708, 1495113833,
+ 1192561226, 629539535, -1365196683, -1120253162, 1091681956,
+ 134286445, 1172218369, -34093658, -137087343, -27869226,
+ -180889478, 55705436, 52362743, -1745516232, -926564477,
+ -513701675, -1666272054, 1457952810, 843953275, -478275722,
+ -1240291080, 101859661, -1606687523, 916365333, 314713310,
+ -22002688, 1019022641, -1171741314, -129050627, -211955813,
+ -1020176299, 1357865293, -609819628, 724533854, -1141449545,
+ 22285231, -97731145, -302329687, 191910894, -1300709885,
+ -644951895, 640448036, -1289009824, 1445456129, 846416471,
+ 1821291740, -1639640821, -712724532, -447475807, 132156847,
+ 258067455, 324301319, 278586969, -1544082357, 636007277, 977122066,
+ 127462480, 365126129, 1086276825, -432124148, 896598926,
+ -388550179, 273357331, -845018695, -1089465389, 384439820,
+ -558419772, 1476422025, 730712769, 190665059, -764968927,
+ -789708218, 637873581, 348429858, 1386000168, -638123594,
+ -842010345, -607926448, 19535163, -742771490, -18323344, 246155488,
+ 350409468, 1290907730, -492566468, 300358636, 501876267, 252441807,
+ 1233551975, -1431067042, 517177374, -1540299707, -948380761,
+ 1253997663, 693795998, 148707823, 152894502, 98729538, -30042824,
+ -563057441, 723726409, 367338961, 1395435261, 217868876,
+ 1220652431, 953572083, -1134905155, -734486813, -587470130,
+ -864647866, 1030737023, 781798521, -321076732, -460548153,
+ 122681678, -873728847, -1286304399, -75472885, 113390881,
+ -1556849198, -1070802176, 924389470, 957478910, 5974049, 709413506,
+ 476334647, 572869787, 776298405, -8822420, -99326499, -707855342,
+ -1187216303, 668038414, 262454769, -1120293198, -32011040,
+ 249812104, -101835410, 1082281087, -570183855, -954535179,
+ 1384361473, -983199686, 2017611313, 328926483, -878162849,
+ -1202254181, -225604951, 966898955, 247213529, -1257544612,
+ -197005970, -1039902730, -1947925142, 1752780907, -313410699,
+ -464474556, 416580338, -1063356643, -292212702, 57509168,
+ 1034124629, 1059212593, 468522867, 845369497, 1872717306,
+ -1216544764, -1419907623, 1376869956, -66585488, -1590974467,
+ -367070705, -1456529060, 791844031, 336217635, -1106832215,
+ 1476739427, -751018210, -1411671555, -1880387375, -1714242595,
+ 1169006474, -479442380, -892267555, -1471250266, -267888858,
+ 808634418, 1324777189, -585449929, 1127186951, 468768901,
+ -2002989138, -52352849, 186493053, 1258464606, 117157186,
+ 445919258, 908401949, -1112221136, 863904453, -942718649,
+ 796754809, -38943966, -781978872, -56814078, 1273857459,
+ -1781920832, 209979504, 811828269, -1150814437, 850061883,
+ -532968763, 252506408, -885025629, 391567580, -1295702482,
+ 574894420, 1462248349, 1622584325, -88443443, -1122006092,
+ -169758578, 456282338, -443233309, 436693483, -956563815,
+ -480221349, 435252860, -1114099391, 1060053979, -470893945,
+ -1273682879, -734596176, 639950927, -1278648701, 306274747,
+ -410562146, 1137869228, -1970746553, 1313830798, 1248071822,
+ -247297704, 1015218053, -1607348116, -261817613, -821413148,
+ -782942639, -628711083, 240953091, -629550668, -1584736319,
+ 856616893, -186759752, 197905373, 541638393, 603407919, -278480495,
+ 410077039, 544065371, -1509627427, 402918436, -450463799,
+ -131169308, 249920630, 1079548609, -927911828, 1444577689,
+ -353002528, -224292462, 1247795279, -790844631, -40427503,
+ 59829765, -332587567, 1319862109, -1261340753, 121711726,
+ 1342756342, -643495787, 100326201, -934436714, -69134888,
+ -898880561, -379524737, -577234570, -805827092, -1575493557,
+ -289920678, -476605057, 1235714994, -317239591, 418553949,
+ 410053338, -204985448, 1206503615, 202610372, -932244873,
+ 782207875, -288661931, -806814809, 1270953679, 2060991595,
+ -311412846, 327279979, 1148562672, 55239149, -610114433,
+ -1511688434, 87619740, -433503545, 326150519, -581293393,
+ -97417688, -289736140, -1543886029, -1251976119, 1585774446,
+ 1570011421, 432602745, 486343696, -834680922, 265004849,
+ -1132107706, 502627197, -815873818, 249635389, 1985714127,
+ -1095817653, -130743522, -645266828, -334621094, 199921747,
+ 1059256177, 378031303, 1519740920, 925540689, 1405957844,
+ 1387748290, -56138046, -770637828, -187984510, -1361735163,
+ 1294823206, -608941238, 451860688, -510549867, 1143516283,
+ -779090703, 1459305047, -600335915, -1684168049, 1516622316,
+ -631733335, -4360068, 499778796, 587600402, -1296000335, -37959743,
+ -1084203927, 1162902556, 246374600, -515103645, 341724568,
+ -702303954, 452229900, 485108287, 1170048553, -1510148355,
+ 611133912, 1997927484, -142022671, -724776653, -336090522,
+ 708283514, -1409637378, -2052637687, 376055110, 226628105,
+ -1714452033, -1776158002, 369167930, 1800807012, 710680889,
+ -69951947, -1223849766, -1862239787, 218536127, -656411794,
+ -1202269188, 609634805, -224425858, 519797951, 284223080,
+ 869408930, 270750206, -544967439, 2097168510, 31650971, -600985417,
+ -165303097, -257809088, -1043223971, 1827891621, -156827355,
+ 499719603
+};
+
+#define IVEC_LEN (sizeof(initvector) / sizeof(initvector[0]))
+
+#endif
diff --git a/tools/regression/lib/libc/string/Makefile b/tools/regression/lib/libc/string/Makefile
new file mode 100644
index 0000000..af76f9d
--- /dev/null
+++ b/tools/regression/lib/libc/string/Makefile
@@ -0,0 +1,15 @@
+# $FreeBSD$
+
+CFLAGS+= -I/usr/local/include
+LDFLAGS+= -L/usr/local/lib
+LDLIBS= -ltap
+
+TESTS= test-strerror
+
+.PHONY: tests
+tests: ${TESTS}
+ for p in ${TESTS}; do ${.OBJDIR}/$$p; done
+
+.PHONY: clean
+clean:
+ -rm -f ${TESTS}
diff --git a/tools/regression/lib/libc/string/test-strerror.c b/tools/regression/lib/libc/string/test-strerror.c
new file mode 100644
index 0000000..f5274ed
--- /dev/null
+++ b/tools/regression/lib/libc/string/test-strerror.c
@@ -0,0 +1,130 @@
+/*-
+ * Copyright (c) 2001 Wes Peters <wes@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <tap.h>
+
+int
+main(void)
+{
+ char buf[64];
+ char *sret;
+ int iret;
+
+ plan_tests(25);
+
+ /*
+ * strerror() failure tests.
+ */
+ errno = 0;
+ sret = strerror(0);
+ ok1(strcmp(sret, "Unknown error: 0") == 0);
+ ok1(errno == EINVAL);
+
+ errno = 0;
+ sret = strerror(INT_MAX);
+ snprintf(buf, sizeof(buf), "Unknown error: %d", INT_MAX);
+ ok1(strcmp(sret, buf) == 0);
+ ok1(errno == EINVAL);
+
+ /*
+ * strerror() success tests.
+ */
+ errno = 0;
+ sret = strerror(EPERM);
+ ok1(strcmp(sret, "Operation not permitted") == 0);
+ ok1(errno == 0);
+
+ errno = 0;
+ sret = strerror(EPFNOSUPPORT);
+ ok1(strcmp(sret, "Protocol family not supported") == 0);
+ ok1(errno == 0);
+
+ errno = 0;
+ sret = strerror(ELAST);
+ ok1(errno == 0);
+
+ /*
+ * strerror_r() failure tests.
+ */
+ memset(buf, '*', sizeof(buf));
+ iret = strerror_r(0, buf, sizeof(buf));
+ ok1(strcmp(buf, "Unknown error: 0") == 0);
+ ok1(iret == EINVAL);
+
+ memset(buf, '*', sizeof(buf));
+ /* One byte too short. */
+ iret = strerror_r(EPERM, buf, strlen("Operation not permitted"));
+ ok1(strcmp(buf, "Operation not permitte") == 0);
+ ok1(iret == ERANGE);
+
+ memset(buf, '*', sizeof(buf));
+ /* One byte too short. */
+ iret = strerror_r(-1, buf, strlen("Unknown error: -1"));
+ ok1(strcmp(buf, "Unknown error: -") == 0);
+ ok1(iret == EINVAL);
+
+ memset(buf, '*', sizeof(buf));
+ /* Two bytes too short. */
+ iret = strerror_r(-2, buf, strlen("Unknown error: -2") - 1);
+ ok1(strcmp(buf, "Unknown error: ") == 0);
+ ok1(iret == EINVAL);
+
+ memset(buf, '*', sizeof(buf));
+ /* Three bytes too short. */
+ iret = strerror_r(-2, buf, strlen("Unknown error: -2") - 2);
+ ok1(strcmp(buf, "Unknown error:") == 0);
+ ok1(iret == EINVAL);
+
+ memset(buf, '*', sizeof(buf));
+ /* One byte too short. */
+ iret = strerror_r(12345, buf, strlen("Unknown error: 12345"));
+ ok1(strcmp(buf, "Unknown error: 1234") == 0);
+ ok1(iret == EINVAL);
+
+ /*
+ * strerror_r() success tests.
+ */
+ memset(buf, '*', sizeof(buf));
+ iret = strerror_r(EDEADLK, buf, sizeof(buf));
+ ok1(strcmp(buf, "Resource deadlock avoided") == 0);
+ ok1(iret == 0);
+
+ memset(buf, '*', sizeof(buf));
+ iret = strerror_r(EPROCLIM, buf, sizeof(buf));
+ ok1(strcmp(buf, "Too many processes") == 0);
+ ok1(iret == 0);
+
+ return exit_status();
+}
diff --git a/tools/regression/lib/libc/string/test-strerror.t b/tools/regression/lib/libc/string/test-strerror.t
new file mode 100644
index 0000000..8bdfd03
--- /dev/null
+++ b/tools/regression/lib/libc/string/test-strerror.t
@@ -0,0 +1,10 @@
+#!/bin/sh
+# $FreeBSD$
+
+cd `dirname $0`
+
+executable=`basename $0 .t`
+
+make $executable 2>&1 > /dev/null
+
+exec ./$executable
OpenPOWER on IntegriCloud