diff --git a/.gitignore b/.gitignore
index c805925..a6f6403 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
ChangeLog
+*~
*.pc
*.la
*.lo
@@ -9,6 +10,8 @@ ChangeLog
*.trs
*.gcda
*.gcno
+*.sym
+*.map
.dirstamp
.deps/
.libs/
@@ -19,6 +22,6 @@ autom4te.cache/
build-aux/
configure
config.*
+format.ld
libtool
-m4/
stamp-h1
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index ca88de2..72b7625 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,19 +1,54 @@
-image: debian:buster
-
-before_script:
- - apt-get update -qq
- - apt-get install -qq -y --no-install-recommends
- git gcc make autoconf automake libtool libmd-dev gcovr
+.vpath-tests:
+ script:
+ - ./autogen
+ - mkdir -p build-tree
+ - cd build-tree
+ - ../configure
+ - make check
-unit-tests:
- stage: test
+.unit-tests:
script:
- ./autogen && ./configure
- make check
-coverage:
- stage: test
+.unit-tests-asan:
+ script:
+ - ./autogen && ./configure --enable-sanitize
+ - make check
+
+.coverage:
script:
- ./autogen && ./configure --disable-static
- make check CFLAGS="--coverage -O0 -ggdb" LDFLAGS="--coverage -O0 -ggdb"
- gcovr -s -e test/
+ coverage: /^TOTAL.*\s+(\d+\%)$/
+
+.debian:
+ image: debian:latest
+ stage: test
+ before_script:
+ - apt-get update -qq
+ - apt-get install -qq -y --no-install-recommends
+ git gcc make autoconf automake libtool libmd-dev gcovr
+
+.alpine:
+ image: alpine:latest
+ stage: test
+ before_script:
+ - apk add --no-cache git gcc make autoconf automake libtool
+ bsd-compat-headers linux-headers libmd-dev musl-dev gcovr
+
+vpath-tests:debian:
+ extends: [.debian, .vpath-tests]
+
+unit-tests:debian:
+ extends: [.debian, .unit-tests-asan]
+
+coverage:debian:
+ extends: [.debian, .coverage]
+
+unit-tests:alpine:
+ extends: [.alpine, .unit-tests]
+
+coverage:alpine:
+ extends: [.alpine, .coverage]
diff --git a/COPYING b/COPYING
index 8a99303..7814d8f 100644
--- a/COPYING
+++ b/COPYING
@@ -3,75 +3,10 @@ Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Files:
*
Copyright:
- Copyright © 2004-2006, 2008-2021 Guillem Jover <guillem@hadrons.org>
+ Copyright © 2004-2024 Guillem Jover <guillem@hadrons.org>
License: BSD-3-clause
Files:
- man/arc4random.3bsd
- man/tree.3bsd
-Copyright:
- Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
- All rights reserved.
-License: BSD-4-clause-Niels-Provos
- 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 Niels Provos.
- 4. The name of the author may not be used to endorse or promote products
- derived from this software without specific prior written permission.
- .
- THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
-
-Files:
- man/getprogname.3bsd
-Copyright:
- Copyright © 2001 Christopher G. Demetriou
- All rights reserved.
-License: BSD-4-clause-Christopher-G-Demetriou
- 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 for the
- NetBSD Project. See http://www.netbsd.org/ for
- information about NetBSD.
- 4. The name of the author may not be used to endorse or promote products
- derived from this software without specific prior written permission.
- .
- THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
-
-Files:
include/bsd/err.h
include/bsd/stdlib.h
include/bsd/sys/param.h
@@ -236,6 +171,7 @@ License: BSD-5-clause-Peter-Wemm
Files:
include/bsd/stringlist.h
+ man/arc4random.3bsd
man/fmtcheck.3bsd
man/humanize_number.3bsd
man/stringlist.3bsd
@@ -250,6 +186,12 @@ Copyright:
Copyright © 2013 John-Mark Gurney <jmg@FreeBSD.org>
All rights reserved.
.
+ Copyright © 2014 The NetBSD Foundation, Inc.
+ All rights reserved.
+ .
+ Some code was derived from software contributed to The NetBSD Foundation
+ by Taylor R. Campbell.
+ .
Some code was contributed to The NetBSD Foundation by Allen Briggs.
.
Some code was contributed to The NetBSD Foundation by Luke Mewburn.
@@ -311,7 +253,6 @@ Copyright:
All rights reserved.
.
Copyright © 2009 Advanced Computing Technologies LLC
- Written by: John H. Baldwin <jhb@FreeBSD.org>
All rights reserved.
.
Copyright © 2011 Guillem Jover <guillem@hadrons.org>
@@ -348,6 +289,7 @@ License: BSD-2-clause-verbatim
Files:
include/bsd/sys/tree.h
man/fparseln.3bsd
+ man/tree.3bsd
src/fparseln.c
Copyright:
Copyright © 1997 Christos Zoulas.
@@ -364,7 +306,6 @@ Files:
man/strtonum.3bsd
src/arc4random.c
src/arc4random_linux.h
- src/arc4random_openbsd.h
src/arc4random_uniform.c
src/arc4random_unix.h
src/arc4random_win.h
@@ -383,6 +324,8 @@ Files:
src/recallocarray.c
src/strlcat.c
src/strlcpy.c
+ test/explicit_bzero.c
+ test/strtonum.c
Copyright:
Copyright © 2004 Ted Unangst and Todd Miller
All rights reserved.
@@ -391,6 +334,7 @@ Copyright:
Copyright © 1998, 2000-2002, 2004-2005, 2007, 2010, 2012-2015
Todd C. Miller <Todd.Miller@courtesan.com>
Copyright © 2004 Ted Unangst
+ Copyright © 2004 Otto Moerbeek <otto@drijf.net>
Copyright © 2008 Damien Miller <djm@openbsd.org>
Copyright © 2008, 2010-2011, 2016-2017 Otto Moerbeek <otto@drijf.net>
Copyright © 2013 Markus Friedl <markus@openbsd.org>
@@ -398,8 +342,9 @@ Copyright:
Copyright © 2014 Brent Cook <bcook@openbsd.org>
Copyright © 2014 Pawel Jakub Dawidek <pjd@FreeBSD.org>
Copyright © 2014 Theo de Raadt <deraadt@openbsd.org>
+ Copyright © 2014 Google Inc.
Copyright © 2015 Michael Felt <aixtools@gmail.com>
- Copyright © 2015 Guillem Jover <guillem@hadrons.org>
+ Copyright © 2015, 2022 Guillem Jover <guillem@hadrons.org>
License: ISC
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
diff --git a/Makefile.am b/Makefile.am
index b839ae1..bdb8376 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,13 +1,18 @@
## Process this file with automake to produce Makefile.in
-SUBDIRS = include man src test
+SUBDIRS = \
+ include \
+ man \
+ src \
+ test \
+ # EOL
ACLOCAL_AMFLAGS = -I m4
EXTRA_DIST = \
autogen \
get-version \
- $(nil)
+ # EOL
dist-hook:
echo $(VERSION) >$(distdir)/.dist-version
diff --git a/README b/README
index 9b2bbdb..c545bdc 100644
--- a/README
+++ b/README
@@ -9,6 +9,7 @@ A BSD compatible message-digest library is required, on systems where
this is not provided by its libc or libmd libraries, the canonical
implementation to use is <https://www.hadrons.org/software/libmd/>.
+
Releases
--------
@@ -30,10 +31,44 @@ The mail address is:
Source Repository
-----------------
-The master repository can be browsed at:
+The primary repository can be browsed at:
<https://cgit.freedesktop.org/libbsd>
and cloned from:
<https://anongit.freedesktop.org/git/libbsd>
+
+
+Building from git source
+------------------------
+
+To prepare the libbsd source tree from git before starting the build process
+some required software needs to be installed:
+
+ GNU autoconf >= 2.67
+ GNU automake >= 1.9
+ GNU libtool >= 2.0
+
+After installing the needed software, and running the following command on
+the git tree:
+
+ $ ./autogen
+
+the source should be roughly equivalent to the distributed tar source.
+
+
+Building from tar source
+------------------------
+
+The minimum software required to configure and build dpkg from a tarball is:
+
+ C89 compiler
+ make
+
+The following software might be required depending on the system:
+
+ libmd (whenever the libc does not provide the needed digest functions)
+
+The build process is done by running the usual «./configure; make». To
+see all available configuration options please run «./configure --help».
diff --git a/configure.ac b/configure.ac
index 09cb310..2a15d72 100644
--- a/configure.ac
+++ b/configure.ac
@@ -6,17 +6,22 @@ AC_CONFIG_SRCDIR([src/strlcpy.c])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([m4])
-AM_INIT_AUTOMAKE([1.9 foreign nostdinc subdir-objects no-dist-gzip dist-xz])
-
-m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])],
- [AC_SUBST([AM_DEFAULT_VERBOSITY], [1])])
+AM_INIT_AUTOMAKE(
+ [1.11]
+ [-Wall]
+ [foreign]
+ [nostdinc]
+ [subdir-objects]
+ [no-dist-gzip dist-xz]
+)
+AM_SILENT_RULES([yes])
-LIBBSD_ABI_MAJOR=0
-LIBBSD_ABI_MINOR=11
-LIBBSD_ABI_PATCH=3
+SOVERSION_MAJOR=0
+SOVERSION_MINOR=12
+SOVERSION_PATCH=2
-LIBBSD_ABI="$LIBBSD_ABI_MAJOR:$LIBBSD_ABI_MINOR:$LIBBSD_ABI_PATCH"
-AC_SUBST([LIBBSD_ABI])
+SOVERSION="$SOVERSION_MAJOR:$SOVERSION_MINOR:$SOVERSION_PATCH"
+AC_SUBST([SOVERSION])
# Check and store if we got user supplied variables
user_CFLAGS=${CFLAGS-unset}
@@ -24,70 +29,447 @@ user_CFLAGS=${CFLAGS-unset}
# Checks for operating system services and capabilities.
AC_USE_SYSTEM_EXTENSIONS
AC_SYS_LARGEFILE
+LIBBSD_SYS_TIME64
+AM_PROG_AR
LT_INIT
+LIBBSD_LINKER_VERSION_SCRIPT
-AC_CACHE_CHECK([if ld supports --version-script flag],
- [libbsd_cv_version_script], [
- echo "{ global: symbol; local: *; };" >conftest.map
- save_LDFLAGS=$LDFLAGS
- LDFLAGS="$LDFLAGS -Wl,--version-script=conftest.map"
- AC_LINK_IFELSE([
- AC_LANG_PROGRAM([], [])
- ], [
- libbsd_cv_version_script=yes
- ], [
- libbsd_cv_version_script=no
- ])
- LDFLAGS="$save_LDFLAGS"
- rm -f conftest.map
- ]
+## Select library ABI to expose.
+#
+# The systems have DROP comments for interfaces that could be dropped on
+# the next SOVERSION bump.
+
+is_windows=no
+
+api_time_macros=unknown
+
+abi_accmode=unknown
+abi_arc4random=unknown
+abi_arc4random_stir=unknown
+abi_asprintf=unknown
+abi_bsd_getopt=unknown
+abi_closefrom=unknown
+abi_err=unknown
+abi_errc=unknown
+abi_expand_number=unknown
+abi_explicit_bzero=unknown
+abi_fgetln=unknown
+abi_flopen=unknown
+abi_fmtcheck=unknown
+abi_fpurge=unknown
+abi_freezero=unknown
+abi_funopen=unknown
+abi_getbsize=unknown
+abi_getpeereid=unknown
+abi_humanize_number=unknown
+abi_id_from_name=unknown
+abi_inet_net_pton=unknown
+abi_md5=unknown
+abi_name_from_id=unknown
+abi_nlist=unknown
+abi_pidfile=unknown
+abi_proctitle=unknown
+abi_progname=unknown
+abi_readpassphrase=unknown
+abi_reallocarray=unknown
+abi_reallocf=unknown
+abi_recallocarray=unknown
+abi_stringlist=unknown
+abi_sort=unknown
+abi_strl=unknown
+abi_strmode=unknown
+abi_strnstr=unknown
+abi_strtonum=unknown
+abi_strtox=unknown
+abi_timeconv=unknown
+abi_vis=unknown
+abi_wcsl=unknown
+
+AS_CASE([$host_os],
+ [*-gnu* | gnu*], [
+ api_time_macros=no
+
+ abi_accmode=yes
+ # DROP: On glibc >= 2.36.
+ #abi_arc4random=no
+ abi_arc4random=yes
+ abi_arc4random_stir=yes
+ abi_asprintf=no
+ abi_bsd_getopt=yes
+ # DROP: On glibc >= 2.34.
+ #abi_closefrom=no
+ abi_closefrom=yes
+ abi_err=no
+ abi_errc=yes
+ abi_expand_number=yes
+ # DROP: On glibc >= 2.25.
+ #abi_explicit_bzero=no
+ abi_explicit_bzero=yes
+ abi_fgetln=yes
+ abi_flopen=yes
+ abi_fmtcheck=yes
+ abi_fpurge=yes
+ abi_freezero=yes
+ abi_funopen=yes
+ abi_getbsize=yes
+ abi_getpeereid=yes
+ abi_humanize_number=yes
+ abi_id_from_name=yes
+ # DROP: On glibc.
+ #abi_inet_net_pton=no
+ abi_inet_net_pton=yes
+ # DROP: On libmd.
+ #abi_md5=no
+ abi_md5=yes
+ abi_name_from_id=yes
+ abi_nlist=yes
+ abi_pidfile=yes
+ abi_proctitle=yes
+ abi_progname=yes
+ abi_readpassphrase=yes
+ # DROP: On glibc >= 2.26.
+ #abi_reallocarray=no
+ abi_reallocarray=yes
+ abi_reallocf=yes
+ abi_recallocarray=yes
+ abi_stringlist=yes
+ abi_sort=yes
+ # DROP: On glibc >= 2.38.
+ #abi_strl=no
+ abi_strl=yes
+ abi_strmode=yes
+ abi_strnstr=yes
+ abi_strtonum=yes
+ abi_strtox=yes
+ abi_timeconv=yes
+ # DROP: On libmd.
+ abi_transparent_libmd=yes
+ abi_vis=yes
+ abi_wcsl=yes
+ ],
+ [*-musl*], [
+ api_time_macros=no
+
+ abi_accmode=yes
+ abi_arc4random=yes
+ abi_arc4random_stir=yes
+ abi_asprintf=no
+ # DROP: On musl >= 0.9.7, optreset got implemented.
+ #abi_bsd_getopt=no
+ abi_bsd_getopt=yes
+ abi_closefrom=yes
+ abi_err=no
+ abi_errc=yes
+ abi_expand_number=yes
+ # DROP: On musl >= 1.1.20.
+ #abi_explicit_bzero=no
+ abi_explicit_bzero=yes
+ # DROP: On musl >= 0.9.4.
+ #abi_fgetln=no
+ abi_fgetln=yes
+ abi_flopen=yes
+ abi_fmtcheck=yes
+ abi_fpurge=yes
+ abi_freezero=yes
+ # On musl >= 1.1.19, fopencookie() got implemented, and because we were
+ # checking for its presence to decide whether to build funopen(), it got
+ # included in builds even when previously it had not been included, which
+ # is partially an ABI issue, but given that disabling it now would be
+ # worse, we'll ignore this as this is only a problem with downgrades. And
+ # enable it explicitly
+ #abi_funopen=no
+ abi_funopen=yes
+ abi_getbsize=yes
+ abi_getpeereid=yes
+ abi_humanize_number=yes
+ abi_id_from_name=yes
+ abi_inet_net_pton=yes
+ # DROP: On libmd.
+ #abi_md5=no
+ abi_md5=yes
+ abi_name_from_id=yes
+ abi_nlist=yes
+ abi_pidfile=yes
+ abi_proctitle=yes
+ abi_progname=yes
+ abi_readpassphrase=yes
+ # DROP: On musl >= 1.2.2.
+ #abi_reallocarray=no
+ abi_reallocarray=yes
+ abi_reallocf=ues
+ abi_recallocarray=yes
+ abi_stringlist=yes
+ abi_sort=yes
+ # DROP: On musl >= 0.5.0, strlcpy() and strlcat() were already implemented.
+ #abi_strl=no
+ abi_strl=yes
+ abi_strmode=yes
+ abi_strnstr=yes
+ abi_strtonum=yes
+ abi_strtox=yes
+ abi_timeconv=yes
+ # DROP: On libmd.
+ abi_transparent_libmd=yes
+ abi_vis=yes
+ abi_wcsl=yes
+ ],
+ [darwin*], [
+ api_time_macros=no
+
+ abi_accmode=no
+ abi_arc4random=no
+ abi_arc4random_stir=no
+ abi_asprintf=no
+ abi_bsd_getopt=no
+ abi_closefrom=yes
+ abi_err=no
+ abi_errc=no
+ abi_expand_number=yes
+ abi_explicit_bzero=yes
+ abi_fgetln=no
+ abi_flopen=yes
+ abi_fmtcheck=no
+ abi_fpurge=no
+ abi_freezero=yes
+ abi_funopen=no
+ abi_getbsize=yes
+ abi_getpeereid=no
+ abi_humanize_number=yes
+ abi_id_from_name=yes
+ abi_inet_net_pton=no
+ # On libmd.
+ abi_md5=no
+ abi_name_from_id=no
+ abi_nlist=no
+ abi_pidfile=yes
+ abi_proctitle=yes
+ abi_progname=no
+ abi_readpassphrase=no
+ abi_reallocarray=yes
+ abi_reallocf=no
+ abi_recallocarray=yes
+ abi_stringlist=no
+ abi_sort=no
+ abi_strl=no
+ abi_strmode=no
+ abi_strnstr=no
+ abi_strtonum=no
+ abi_strtox=yes
+ abi_timeconv=no
+ # On libmd.
+ abi_transparent_libmd=no
+ abi_vis=no
+ abi_wcsl=no
+ ],
+ [solaris2*], [
+ api_time_macros=yes
+
+ abi_accmode=yes
+ abi_arc4random=no
+ abi_arc4random_stir=no
+ abi_asprintf=no
+ abi_bsd_getopt=yes
+ abi_closefrom=no
+ abi_err=no
+ abi_errc=yes
+ abi_expand_number=yes
+ abi_explicit_bzero=yes
+ abi_fgetln=yes
+ abi_flopen=yes
+ abi_fmtcheck=no
+ abi_fpurge=yes
+ abi_freezero=yes
+ abi_funopen=no
+ abi_getbsize=yes
+ abi_getpeereid=yes
+ abi_humanize_number=yes
+ abi_id_from_name=yes
+ abi_inet_net_pton=yes
+ # On libmd.
+ abi_md5=no
+ abi_name_from_id=yes
+ abi_nlist=no
+ abi_pidfile=yes
+ abi_proctitle=yes
+ abi_progname=no
+ abi_readpassphrase=yes
+ abi_reallocarray=yes
+ abi_reallocf=no
+ abi_recallocarray=yes
+ abi_stringlist=yes
+ abi_sort=yes
+ abi_strl=no
+ abi_strmode=yes
+ abi_strnstr=no
+ abi_strtonum=no
+ abi_strtox=yes
+ abi_timeconv=yes
+ # On libmd.
+ abi_transparent_libmd=no
+ abi_vis=yes
+ abi_wcsl=yes
+ ],
+ [aix*], [
+ api_time_macros=yes
+
+ abi_accmode=yes
+ abi_arc4random=yes
+ abi_arc4random_stir=yes
+ abi_asprintf=yes
+ abi_bsd_getopt=yes
+ abi_closefrom=yes
+ abi_err=yes
+ abi_errc=yes
+ abi_expand_number=yes
+ abi_explicit_bzero=yes
+ abi_fgetln=yes
+ abi_flopen=yes
+ abi_fmtcheck=yes
+ abi_fpurge=no
+ abi_freezero=yes
+ abi_funopen=no
+ abi_getbsize=yes
+ abi_getpeereid=yes
+ abi_humanize_number=yes
+ abi_id_from_name=yes
+ abi_inet_net_pton=no
+ # On libmd.
+ abi_md5=no
+ abi_name_from_id=yes
+ abi_nlist=no
+ abi_pidfile=yes
+ abi_proctitle=yes
+ abi_progname=yes
+ abi_readpassphrase=yes
+ abi_reallocarray=yes
+ abi_reallocf=yes
+ abi_recallocarray=yes
+ abi_stringlist=yes
+ abi_sort=yes
+ abi_strl=yes
+ abi_strmode=yes
+ abi_strnstr=yes
+ abi_strtonum=yes
+ abi_strtox=yes
+ abi_timeconv=yes
+ # On libmd.
+ abi_transparent_libmd=no
+ abi_vis=yes
+ abi_wcsl=yes
+ ],
+ [mingw*], [
+ is_windows=yes
+ ],
)
-AM_CONDITIONAL([HAVE_LINKER_VERSION_SCRIPT],
- [test "x$libbsd_cv_version_script" = "xyes"])
+
+# Handle artificial ABI selections that are combinations of others.
+AS_IF([test "$abi_name_from_id" = "yes" || test "$abi_id_from_name" = "yes"], [
+ abi_pwcache=yes
+], [
+ abi_pwcache=no
+])
+AS_IF([test "$abi_err" = "yes" || test "$abi_errc" = "yes"], [
+ abi_err_h=yes
+], [
+ abi_err_h=no
+])
+
+AM_CONDITIONAL([OS_WINDOWS], [test "x$is_windows" = "xyes"])
# Checks for programs.
+AC_CHECK_TOOL([OBJDUMP], [objdump])
AC_PROG_CC
+AC_PROG_SED
AC_PROG_INSTALL
AC_PROG_LN_S
# Set default compiler variables
-if test "$user_CFLAGS" = unset && test "$GCC" = yes; then
- CFLAGS="$CFLAGS -Wall -Wextra -Wno-unused-variable -Wno-unused-parameter"
-fi
+AS_IF([test "$user_CFLAGS" = unset], [
+ LIBBSD_CHECK_COMPILER_FLAG([-Wall])
+ LIBBSD_CHECK_COMPILER_FLAG([-Wextra])
+
+ LIBBSD_CHECK_COMPILER_FLAG([-Wbad-function-cast])
+ LIBBSD_CHECK_COMPILER_FLAG([-Wc99-c11-compat])
+ LIBBSD_CHECK_COMPILER_FLAG([-Wcast-align])
+ LIBBSD_CHECK_COMPILER_FLAG([-Wdeclaration-after-statement])
+ LIBBSD_CHECK_COMPILER_FLAG([-Wdocumentation])
+ LIBBSD_CHECK_COMPILER_FLAG([-Wduplicated-branches])
+ LIBBSD_CHECK_COMPILER_FLAG([-Wduplicated-cond])
+ LIBBSD_CHECK_COMPILER_FLAG([-Wformat -Wformat-security])
+ LIBBSD_CHECK_COMPILER_FLAG([-Wformat=2])
+ LIBBSD_CHECK_COMPILER_FLAG([-Winit-self])
+ LIBBSD_CHECK_COMPILER_FLAG([-Wlogical-not-parentheses])
+ LIBBSD_CHECK_COMPILER_FLAG([-Wlogical-op])
+ LIBBSD_CHECK_COMPILER_FLAG([-Wmissing-declarations])
+ LIBBSD_CHECK_COMPILER_FLAG([-Wmissing-format-attribute])
+ LIBBSD_CHECK_COMPILER_FLAG([-Wmissing-prototypes])
+ LIBBSD_CHECK_COMPILER_FLAG([-Wnested-externs])
+ LIBBSD_CHECK_COMPILER_FLAG([-Wno-missing-field-initializers])
+ LIBBSD_CHECK_COMPILER_FLAG([-Wno-nonnull-compare])
+ LIBBSD_CHECK_COMPILER_FLAG([-Wno-tautological-constant-out-of-range-compare])
+ LIBBSD_CHECK_COMPILER_FLAG([-Wno-unused-parameter])
+ LIBBSD_CHECK_COMPILER_FLAG([-Wnull-dereference])
+ LIBBSD_CHECK_COMPILER_FLAG([-Wold-style-definition])
+ LIBBSD_CHECK_COMPILER_FLAG([-Wpointer-arith])
+ LIBBSD_CHECK_COMPILER_FLAG([-Wregister])
+ LIBBSD_CHECK_COMPILER_FLAG([-Wrestrict])
+ LIBBSD_CHECK_COMPILER_FLAG([-Wshadow])
+ LIBBSD_CHECK_COMPILER_FLAG([-Wshift-negative-value])
+ LIBBSD_CHECK_COMPILER_FLAG([-Wsizeof-array-argument])
+ LIBBSD_CHECK_COMPILER_FLAG([-Wstrict-prototypes])
+ LIBBSD_CHECK_COMPILER_FLAG([-Wswitch-bool])
+ LIBBSD_CHECK_COMPILER_FLAG([-Wvla])
+ LIBBSD_CHECK_COMPILER_FLAG([-Wwrite-strings])
+
+ CFLAGS="$CFLAGS $LIBBSD_COMPILER_FLAGS"
+
+ AC_ARG_ENABLE([sanitize],
+ [AS_HELP_STRING([--enable-sanitize], [enable compiler sanitizer support])],
+ [
+ LIBBSD_COMPILER_FLAGS=''
+ LIBBSD_CHECK_COMPILER_FLAG([-fsanitize=address])
+ LIBBSD_CHECK_COMPILER_FLAG([-fsanitize=leak])
+ LIBBSD_CHECK_COMPILER_FLAG([-fsanitize=undefined])
+
+ CFLAGS="$CFLAGS $LIBBSD_COMPILER_FLAGS"
+ LDFLAGS="$LDFLAGS $LIBBSD_COMPILER_FLAGS"
+ ])
+])
# Checks for libraries.
AC_CHECK_LIB([testu01], [unif01_CreateExternGenBits],
- [TESTU01_LIBS="-ltestu01"])
+ [TESTU01_LIBS="-ltestu01"])
AC_SUBST([TESTU01_LIBS])
AM_CONDITIONAL([HAVE_LIBTESTU01],
- [test "x$ac_cv_lib_testu01_unif01_CreateExternGenBits" = "xyes"])
+ [test "x$ac_cv_lib_testu01_unif01_CreateExternGenBits" = "xyes"])
saved_LIBS="$LIBS"
-AC_SEARCH_LIBS([dlsym], [dl], [
- AS_IF([test "x$ac_cv_search_dlsym" != "xnone required"], [
- LIBBSD_LIBS="$LIBBSD_LIBS $ac_cv_search_dlsym"
- ])
-], [
- AC_MSG_ERROR([cannot find required dlsym function])
-])
-AC_SEARCH_LIBS([MD5Update], [md], [
- AS_IF([test "x$ac_cv_search_MD5Update" != "xnone required"], [
- LIBBSD_LIBS="$LIBBSD_LIBS $ac_cv_search_MD5Update"
+AS_IF([test "$abi_md5" = "yes"], [
+ AC_SEARCH_LIBS([MD5Update], [md], [
+ AS_IF([test "x$ac_cv_search_MD5Update" != "xnone required"], [
+ MD5_LIBS="$MD5_LIBS $ac_cv_search_MD5Update"
+ abi_transparent_libmd=yes
+ ])
+ ], [
+ AC_MSG_ERROR([cannot find required MD5 functions in libc or libmd])
])
-], [
- AC_MSG_ERROR([cannot find required MD5 functions in libc or libmd])
])
-AC_SEARCH_LIBS([SHA512Update], [md], [
- AS_IF([test "x$ac_cv_search_SHA512Update" != "xnone required"], [
- LIBBSD_LIBS="$LIBBSD_LIBS $ac_cv_search_SHA512Update"
+AS_IF([test "$abi_arc4random" = "yes"], [
+ AC_CHECK_FUNCS([getentropy])
+
+ AS_IF([test "$ac_cv_func_getentropy" != "yes"], [
+ AC_SEARCH_LIBS([SHA512Update], [md], [
+ AS_IF([test "x$ac_cv_search_SHA512Update" != "xnone required"], [
+ LIBBSD_LIBS="$SHA512_LIBS $ac_cv_search_SHA512Update"
+ ])
+ ], [
+ AC_MSG_ERROR([cannot find required SHA-2 functions in libc or libmd])
+ ])
])
-], [
- AC_MSG_ERROR([cannot find required SHA-2 functions in libc or libmd])
])
LIBS="$saved_LIBS"
-is_windows=no
AS_CASE([$host_os],
[*-gnu*], [
# In old glibc versions (< 2.17) clock_gettime() is in librt.
@@ -99,18 +481,28 @@ AS_CASE([$host_os],
])
LIBS="$saved_LIBS"
],
- [*-musl*], [
- # Upstream refuses to define this, we will do it ourselves then.
- AC_DEFINE([__MUSL__], [1], [Define to 1 if we are building for musl])
- ],
- [mingw*], [
- is_windows=yes
+ [aix*], [
+ saved_LIBS="$LIBS"
+ AC_SEARCH_LIBS([perfstat_cpu_total], [perfstat], [
+ AS_IF([test "x$ac_cv_search_perfstat_cpu_total" != "xnone required"], [
+ LIBBSD_LIBS="$LIBBSD_LIBS $ac_cv_search_perfstat_cpu_total"
+ ])
+ ])
+ LIBS="$saved_LIBS"
],
)
-AM_CONDITIONAL([OS_WINDOWS], [test "x$is_windows" = "xyes"])
# Checks for header files.
-AC_CHECK_HEADERS([sys/ndir.h sys/dir.h ndir.h dirent.h pwd.h grp.h])
+AC_CHECK_HEADERS([\
+ sys/ndir.h \
+ sys/dir.h \
+ ndir.h \
+ dirent.h \
+ pwd.h \
+ grp.h \
+ stdio_ext.h \
+ procinfo.h \
+])
# Checks for typedefs, structures, and compiler characteristics.
AC_C_INLINE
@@ -123,107 +515,115 @@ AC_TYPE_UID_T
AC_TYPE_SIZE_T
AC_TYPE_SSIZE_T
-AC_CHECK_DECL([F_CLOSEM],
- [AC_DEFINE([HAVE_FCNTL_CLOSEM], [1],
- [Define to 1 if you have fcntl(F_CLOSEM)])],
- [],
- [#include <limits.h>
- #include <fcntl.h>])
-
-AC_CACHE_CHECK(
- [for GNU .init_array section support],
- [libbsd_cv_gnu_init_array_support],
- [AC_RUN_IFELSE(
- [AC_LANG_SOURCE(
-[[
-static int rc = 1;
-static void init(int argc) { if (argc == 1) rc = 0; }
-void (*init_func)(int argc) __attribute__((__section__(".init_array"))) = init;
-int main() { return rc; }
-]]
- )],
- [libbsd_cv_gnu_init_array_support=yes],
- [libbsd_cv_gnu_init_array_support=no],
- [AC_PREPROC_IFELSE(
- [AC_LANG_SOURCE(
-[[
-/* Look for a known libc that supports .init_array with the GNU extension
- * to pass main() arguments to the init functions. */
-#include <stdlib.h>
-#if defined __GLIBC_PREREQ
-# if __GLIBC_PREREQ(2, 4)
-/* glibc supports GNU .init_array since 2.4. */
-# else
-# error glibc does not support GNU .init_array
-# endif
-#else
-/*
- * Basic SysV ABI .init_array support, init functions do not get arguments:
- * - Bionic since its inception.
- * - uClibc since 0.9.29.
- */
-# error unknown whether libc supports GNU .init_array
-#endif
-]]
- )],
- [libbsd_cv_gnu_init_array_support=yes],
- [libbsd_cv_gnu_init_array_support=no])
- ]
- )]
-)
-AM_CONDITIONAL([BUILD_LIBBSD_CTOR],
- [test "$libbsd_cv_gnu_init_array_support" = yes])
+AC_CHECK_DECL([F_CLOSEM], [
+ AC_DEFINE([HAVE_FCNTL_CLOSEM], [1],
+ [Define to 1 if you have fcntl(F_CLOSEM)])
+], [], [[
+#include <limits.h>
+#include <fcntl.h>
+]])
+
+AC_CHECK_DECLS([environ], [], [], [[
+#include <unistd.h>
+]])
+
+LIBBSD_HAS_GNU_INIT_ARRAY
# Checks for library functions.
-AC_MSG_CHECKING([for program_invocation_short_name])
-AC_LINK_IFELSE(
- [AC_LANG_PROGRAM([[#include <errno.h>]],
- [[const char *p = program_invocation_short_name;]])],
- [AC_DEFINE([HAVE_PROGRAM_INVOCATION_SHORT_NAME], [1],
- [Define to 1 if you have program_invocation_short_name])
- AC_MSG_RESULT([yes])],
- [AC_MSG_RESULT([no])])
-
-AC_MSG_CHECKING([for __progname])
-AC_LINK_IFELSE(
- [AC_LANG_PROGRAM([[extern char *__progname;]],
- [[printf("%s", __progname);]])],
- [AC_DEFINE([HAVE___PROGNAME], [1], [Define to 1 if you have __progname])
- AC_MSG_RESULT([yes])],
- [AC_MSG_RESULT([no])])
-
-AC_MSG_CHECKING([for __register_atfork])
-AC_LINK_IFELSE(
- [AC_LANG_PROGRAM([[
- #include <stddef.h>
- extern void *__dso_handle;
- extern int __register_atfork(void (*)(void), void(*)(void), void (*)(void), void *);
- ]], [[
- __register_atfork(NULL, NULL, NULL, __dso_handle);
- ]])],
- [AC_DEFINE([HAVE___REGISTER_ATFORK], [1],
- [Define to 1 if you have __register_atfork])
- AC_MSG_RESULT([yes])],
- [LIBBSD_LIBS="$LIBBSD_LIBS -pthread"
- AC_MSG_RESULT([no])
- ])
-
-AC_CHECK_FUNCS([clearenv dirfd fopencookie __fpurge \
- getauxval getentropy getexecname getline \
- pstat_getproc sysconf])
-AM_CONDITIONAL([HAVE_GETENTROPY], [test "x$ac_cv_func_getentropy" = "xtrue"])
+LIBBSD_CHECK_PROGNAME
+LIBBSD_CHECK_REGISTER_ATFORK
+
+AC_CHECK_FUNCS([\
+ vasprintf \
+ asprintf \
+ clearenv \
+ dirfd \
+ flock \
+ fopencookie \
+ __fpurge \
+ funopen \
+ getauxval \
+ getentropy \
+ getexecname \
+ getline \
+ open_memstream \
+ pstat_getproc \
+ sysconf \
+ uid_from_user \
+ gid_from_group \
+ user_from_uid \
+ group_from_gid \
+])
+
+AM_CONDITIONAL([HAVE_GETENTROPY], [test "x$ac_cv_func_getentropy" = "xyes"])
+
+# API selection
+LIBBSD_SELECT_API([time_macros], [time struct conversion macros])
+
+# ABI selection
+LIBBSD_SELECT_ABI([accmode], [setmode()/getmode()])
+LIBBSD_SELECT_ABI([arc4random], [arc4random() API])
+LIBBSD_SELECT_ABI([arc4random_stir], [arc4random_stir()/arc4random_addrandom()])
+LIBBSD_SELECT_ABI([asprintf], [vasprintf()/asprintf()])
+LIBBSD_SELECT_ABI([bsd_getopt], [BSD getopt()])
+LIBBSD_SELECT_ABI([closefrom], [closefrom()])
+LIBBSD_SELECT_ABI([err_h], [err.h header])
+LIBBSD_SELECT_ABI([err], [err API])
+LIBBSD_SELECT_ABI([errc], [errc API])
+LIBBSD_SELECT_ABI([expand_number], [expand_number()])
+LIBBSD_SELECT_ABI([explicit_bzero], [explicit_bzero()])
+LIBBSD_SELECT_ABI([fgetln], [fgetln/fgetwln()])
+LIBBSD_SELECT_ABI([flopen], [flopen()/flopenat()])
+LIBBSD_SELECT_ABI([fmtcheck], [fmtcheck()])
+LIBBSD_SELECT_ABI([fpurge], [fpurge()])
+LIBBSD_SELECT_ABI([freezero], [freezero()])
+LIBBSD_SELECT_ABI([funopen], [funopen()])
+LIBBSD_SELECT_ABI([getbsize], [getbsize()])
+LIBBSD_SELECT_ABI([getpeereid], [getpeereid()])
+LIBBSD_SELECT_ABI([humanize_number], [humanize_number()/dehumanize_number()])
+LIBBSD_SELECT_ABI([id_from_name], [uid_from_user()/gid_from_user()])
+LIBBSD_SELECT_ABI([inet_net_pton], [inet_net_pton()])
+LIBBSD_SELECT_ABI([md5], [MD5 digest functions])
+LIBBSD_SELECT_ABI([name_from_id], [user_from_uid()/group_from_gid()])
+LIBBSD_SELECT_ABI([nlist], [nlist()])
+LIBBSD_SELECT_ABI([pidfile], [pidfile API])
+LIBBSD_SELECT_ABI([proctitle], [setproctitle() API])
+LIBBSD_SELECT_ABI([progname], [setprogname()/getprogname()])
+LIBBSD_SELECT_ABI([pwcache], [password cache API])
+LIBBSD_SELECT_ABI([readpassphrase], [readpassphrase()])
+LIBBSD_SELECT_ABI([reallocarray], [reallocarray()])
+LIBBSD_SELECT_ABI([reallocf], [reallocf()])
+LIBBSD_SELECT_ABI([recallocarray], [recallocarray()])
+LIBBSD_SELECT_ABI([stringlist], [stringlist sl_*() API])
+LIBBSD_SELECT_ABI([sort], [BSD sort functions])
+LIBBSD_SELECT_ABI([strl], [strlcpy()/strlcat()])
+LIBBSD_SELECT_ABI([strmode], [strmode()])
+LIBBSD_SELECT_ABI([strnstr], [strnstr()])
+LIBBSD_SELECT_ABI([strtonum], [strtonum()])
+LIBBSD_SELECT_ABI([strtox], [strtoi()/strtou()])
+LIBBSD_SELECT_ABI([timeconv], [timeconv.h API])
+LIBBSD_SELECT_ABI([transparent_libmd], [transparent libmd support])
+LIBBSD_SELECT_ABI([vis], [vis API])
+LIBBSD_SELECT_ABI([wcsl], [wcslcpy()/wcslcat()])
+
+AS_IF([test "x$abi_funopen" = "xno" && \
+ test "x$ac_cv_func_funopen" != "xyes" && \
+ test "x$ac_cv_func_fopencookie" = "xyes"], [
+ AC_MSG_WARN([[can implement funopen() now based on newly added fopencooke(), report upstream]])
+])
+AC_SUBST([MD5_LIBS])
AC_SUBST([LIBBSD_LIBS])
AC_CONFIG_FILES([
- Makefile
- include/Makefile
- man/Makefile
- src/Makefile
- src/libbsd.pc
- src/libbsd-ctor.pc
- src/libbsd-overlay.pc
- test/Makefile
+ Makefile
+ include/Makefile
+ man/Makefile
+ src/Makefile
+ src/libbsd.pc
+ src/libbsd-ctor.pc
+ src/libbsd-overlay.pc
+ test/Makefile
])
AC_CONFIG_HEADERS([config.h])
AC_OUTPUT
diff --git a/include/Makefile.am b/include/Makefile.am
index e6f66bd..cf2713e 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -12,21 +12,77 @@ nobase_include_HEADERS = \
bsd/netinet/ip_icmp.h \
bsd/bitstring.h \
bsd/bsd.h \
- bsd/err.h \
- bsd/getopt.h \
- bsd/grp.h \
bsd/inttypes.h \
bsd/libutil.h \
- bsd/md5.h \
- bsd/nlist.h \
- bsd/pwd.h \
- bsd/readpassphrase.h \
bsd/stdio.h \
bsd/stdlib.h \
bsd/string.h \
+ bsd/unistd.h \
+ bsd/wchar.h \
+ # EOL
+
+if ABI_ERR_H
+nobase_include_HEADERS += \
+ bsd/err.h \
+ # EOL
+endif
+
+if ABI_BSD_GETOPT
+nobase_include_HEADERS += \
+ bsd/getopt.h \
+ # EOL
+endif
+
+if ABI_MD5
+nobase_include_HEADERS += \
+ bsd/md5.h \
+ # EOL
+endif
+
+if ABI_NLIST
+nobase_include_HEADERS += \
+ bsd/nlist.h \
+ # EOL
+endif
+
+if ABI_READPASSPHRASE
+nobase_include_HEADERS += \
+ bsd/readpassphrase.h \
+ # EOL
+endif
+
+if ABI_PWCACHE
+nobase_include_HEADERS += \
+ bsd/grp.h \
+ bsd/pwd.h \
+ # EOL
+endif
+
+if ABI_STRINGLIST
+nobase_include_HEADERS += \
bsd/stringlist.h \
+ # EOL
+endif
+
+if ABI_TIMECONV
+nobase_include_HEADERS += \
bsd/timeconv.h \
- bsd/unistd.h \
+ # EOL
+endif
+
+if ABI_VIS
+nobase_include_HEADERS += \
bsd/vis.h \
- bsd/wchar.h \
- $(nil)
+ # EOL
+endif
+
+do_header_subst = $(AM_V_GEN) $(SED) \
+ -e 's:^//\(.define LIBBSD_SYS_TIME_BITS\).*:\1 $(LIBBSD_SYS_TIME_BITS):' \
+ -e 's:^//\(.define LIBBSD_SYS_HAS_TIME64\).*:\1 $(LIBBSD_SYS_HAS_TIME64):' \
+ # EOL
+
+install-data-hook:
+ $(do_header_subst) <$(DESTDIR)$(includedir)/bsd/sys/cdefs.h \
+ >$(DESTDIR)$(includedir)/bsd/sys/cdefs.h.new
+ mv $(DESTDIR)$(includedir)/bsd/sys/cdefs.h.new \
+ $(DESTDIR)$(includedir)/bsd/sys/cdefs.h
diff --git a/include/bsd/grp.h b/include/bsd/grp.h
index b2705e5..acf3d25 100644
--- a/include/bsd/grp.h
+++ b/include/bsd/grp.h
@@ -44,8 +44,10 @@
__BEGIN_DECLS
int
gid_from_group(const char *, gid_t *);
+#ifndef __APPLE__
const char *
group_from_gid(gid_t, int);
+#endif
__END_DECLS
#endif
diff --git a/include/bsd/md5.h b/include/bsd/md5.h
index 5bd58d8..bfeecfd 100644
--- a/include/bsd/md5.h
+++ b/include/bsd/md5.h
@@ -24,8 +24,10 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#ifndef _AIX
#ifdef LIBBSD_OVERLAY
#include_next <md5.h>
#else
#include <md5.h>
#endif
+#endif
diff --git a/include/bsd/pwd.h b/include/bsd/pwd.h
index 798af4b..38214ae 100644
--- a/include/bsd/pwd.h
+++ b/include/bsd/pwd.h
@@ -44,8 +44,10 @@
__BEGIN_DECLS
int
uid_from_user(const char *, uid_t *);
+#ifndef __APPLE__
const char *
user_from_uid(uid_t, int);
+#endif
__END_DECLS
#endif
diff --git a/include/bsd/stdio.h b/include/bsd/stdio.h
index 8929bfa..eab415c 100644
--- a/include/bsd/stdio.h
+++ b/include/bsd/stdio.h
@@ -1,5 +1,5 @@
/*
- * Copyright © 2004-2005, 2009, 2011-2013 Guillem Jover <guillem@hadrons.org>
+ * Copyright © 2004-2024 Guillem Jover <guillem@hadrons.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -44,8 +44,18 @@
#include <bsd/sys/cdefs.h>
#endif
#include <sys/types.h>
+#if defined(_AIX)
+#include <stdarg.h>
+#endif
__BEGIN_DECLS
+#if defined(_AIX)
+int asprintf(char **strp, char const *fmt, ...)
+ __printflike(2, 3);
+int vasprintf(char **strp, char const *fmt, va_list args)
+ __printflike(2, 0);
+#endif
+
const char *fmtcheck(const char *, const char *);
/* XXX: The function requires cooperation from the system libc to store the
diff --git a/include/bsd/stdlib.h b/include/bsd/stdlib.h
index 2bee974..e404bdb 100644
--- a/include/bsd/stdlib.h
+++ b/include/bsd/stdlib.h
@@ -51,16 +51,24 @@
#include <stdint.h>
__BEGIN_DECLS
+#if !defined(__APPLE__) && !defined(__sun)
+#if !defined(__GLIBC__) || \
+ !__GLIBC_PREREQ(2, 36) || \
+ !defined(_DEFAULT_SOURCE)
uint32_t arc4random(void);
-void arc4random_stir(void);
-void arc4random_addrandom(unsigned char *dat, int datlen);
void arc4random_buf(void *_buf, size_t n);
uint32_t arc4random_uniform(uint32_t upper_bound);
+#endif
+void arc4random_stir(void);
+void arc4random_addrandom(unsigned char *dat, int datlen);
+#endif
int dehumanize_number(const char *str, int64_t *size);
+#if !defined(__APPLE__)
const char *getprogname(void);
void setprogname(const char *);
+#endif
int heapsort(void *, size_t, size_t, int (*)(const void *, const void *));
int mergesort(void *base, size_t nmemb, size_t size,
@@ -72,7 +80,9 @@ int sradixsort(const unsigned char **base, int nmemb,
void *reallocf(void *ptr, size_t size);
#if !defined(__GLIBC__) || \
- (defined(__GLIBC__) && (!__GLIBC_PREREQ(2, 26) || !defined(_GNU_SOURCE)))
+ !__GLIBC_PREREQ(2, 26) || \
+ (__GLIBC_PREREQ(2, 26) && !__GLIBC_PREREQ(2, 29) && !defined(_GNU_SOURCE)) || \
+ (__GLIBC_PREREQ(2, 29) && !defined(_DEFAULT_SOURCE))
void *reallocarray(void *ptr, size_t nmemb, size_t size);
#endif
void *recallocarray(void *ptr, size_t oldnmemb, size_t nmemb, size_t size);
diff --git a/include/bsd/string.h b/include/bsd/string.h
index f987fee..64b4e13 100644
--- a/include/bsd/string.h
+++ b/include/bsd/string.h
@@ -41,13 +41,19 @@
#include <sys/types.h>
__BEGIN_DECLS
+#if !defined(__APPLE__) && \
+ (!defined(__GLIBC__) || !__GLIBC_PREREQ(2, 38) || !defined(_DEFAULT_SOURCE))
size_t strlcpy(char *dst, const char *src, size_t siz);
size_t strlcat(char *dst, const char *src, size_t siz);
+#endif
char *strnstr(const char *str, const char *find, size_t str_len);
+#ifndef __APPLE__
void strmode(mode_t mode, char *str);
+#endif
#if !defined(__GLIBC__) || \
- (defined(__GLIBC__) && (!__GLIBC_PREREQ(2, 25) || !defined(_GNU_SOURCE)))
+ !__GLIBC_PREREQ(2, 25) || \
+ !defined(_DEFAULT_SOURCE)
void explicit_bzero(void *buf, size_t len);
#endif
__END_DECLS
diff --git a/include/bsd/sys/cdefs.h b/include/bsd/sys/cdefs.h
index ac18296..d2627c4 100644
--- a/include/bsd/sys/cdefs.h
+++ b/include/bsd/sys/cdefs.h
@@ -37,6 +37,9 @@
#ifndef __is_identifier
#define __is_identifier(x) 1
#endif
+#ifndef __has_builtin
+#define __has_builtin(x) !__is_identifier(x)
+#endif
#ifdef LIBBSD_OVERLAY
/*
@@ -83,6 +86,10 @@
#define _SYS_CDEFS_H
#endif
+/* Define the ABI for the current system. */
+//#define LIBBSD_SYS_TIME_BITS 0
+//#define LIBBSD_SYS_HAS_TIME64 0
+
#define LIBBSD_CONCAT(x, y) x ## y
#define LIBBSD_STRING(x) #x
@@ -182,7 +189,7 @@
* require it.
*/
#ifndef __offsetof
-# if LIBBSD_GCC_VERSION >= 0x0401 || !__is_identifier(__builtin_offsetof)
+# if LIBBSD_GCC_VERSION >= 0x0401 || __has_builtin(__builtin_offsetof)
# define __offsetof(type, field) __builtin_offsetof(type, field)
# else
# ifndef __cplusplus
diff --git a/include/bsd/timeconv.h b/include/bsd/timeconv.h
index a426bd3..755c89c 100644
--- a/include/bsd/timeconv.h
+++ b/include/bsd/timeconv.h
@@ -58,4 +58,17 @@ time_t _long_to_time(long tlong);
int _time_to_int(time_t t);
time_t _int_to_time(int tint);
+#if LIBBSD_SYS_TIME_BITS == 32 && LIBBSD_SYS_HAS_TIME64
+#if defined _TIME_BITS && _TIME_BITS == 64
+time_t LIBBSD_REDIRECT(_time32_to_time, (int32_t t32), _time32_to_time_time64);
+int32_t LIBBSD_REDIRECT(_time_to_time32, (time_t t), _time_to_time32_time64);
+time_t LIBBSD_REDIRECT(_time64_to_time, (int64_t t64), _time64_to_time_time64);
+int64_t LIBBSD_REDIRECT(_time_to_time64, (time_t t), _time_to_time64_time64);
+long LIBBSD_REDIRECT(_time_to_long, (time_t t), _time_to_long_time64);
+time_t LIBBSD_REDIRECT(_long_to_time, (long tlong), _long_to_time_time64);
+int LIBBSD_REDIRECT(_time_to_int, (time_t t), _time_to_int_time64);
+time_t LIBBSD_REDIRECT(_int_to_time, (int tint), _int_to_time_time64);
+#endif
+#endif
+
#endif /* LIBBSD_TIMECONV_H */
diff --git a/include/bsd/unistd.h b/include/bsd/unistd.h
index 847a0f7..3277fda 100644
--- a/include/bsd/unistd.h
+++ b/include/bsd/unistd.h
@@ -47,6 +47,7 @@
#endif
__BEGIN_DECLS
+#if !defined(__APPLE__)
extern int optreset;
#ifdef LIBBSD_OVERLAY
@@ -55,6 +56,7 @@ extern int optreset;
#endif
int bsd_getopt(int argc, char * const argv[], const char *shortopts);
+#endif
mode_t getmode(const void *set, mode_t mode);
@@ -65,7 +67,11 @@ mode_t getmode(const void *set, mode_t mode);
void *bsd_setmode(const char *mode_str);
+#if !defined(__GLIBC__) || \
+ !__GLIBC_PREREQ(2, 34) || \
+ !defined(_DEFAULT_SOURCE)
void closefrom(int lowfd);
+#endif
/* Compatibility with sendmail implementations. */
#define initsetproctitle(c, a, e) setproctitle_init((c), (a), (e))
diff --git a/include/bsd/vis.h b/include/bsd/vis.h
index fb9ad27..dd150d7 100644
--- a/include/bsd/vis.h
+++ b/include/bsd/vis.h
@@ -93,7 +93,7 @@
* existing one in OpenBSD and Freedesktop's libbsd (the former having existed
* for over ten years). Despite this incompatibility being reported during
* development (see http://gnats.netbsd.org/44977) they still shipped it.
- * Even more unfortunately FreeBSD and later MacOS picked up this incompatible
+ * Even more unfortunately FreeBSD and later macOS picked up this incompatible
* implementation.
*
* Provide both implementations and default for now on the historical one to
diff --git a/include/bsd/wchar.h b/include/bsd/wchar.h
index 7216503..8edef23 100644
--- a/include/bsd/wchar.h
+++ b/include/bsd/wchar.h
@@ -50,8 +50,10 @@
__BEGIN_DECLS
wchar_t *fgetwln(FILE *stream, size_t *len);
+#if !defined(__APPLE__)
size_t wcslcat(wchar_t *dst, const wchar_t *src, size_t size);
size_t wcslcpy(wchar_t *dst, const wchar_t *src, size_t size);
+#endif
__END_DECLS
#endif
diff --git a/m4/.gitignore b/m4/.gitignore
new file mode 100644
index 0000000..10fb5d4
--- /dev/null
+++ b/m4/.gitignore
@@ -0,0 +1,2 @@
+*.m4
+!libbsd*.m4
diff --git a/m4/libbsd-compiler.m4 b/m4/libbsd-compiler.m4
new file mode 100644
index 0000000..ace5ce1
--- /dev/null
+++ b/m4/libbsd-compiler.m4
@@ -0,0 +1,104 @@
+# Copyright © 2021 Guillem Jover <guillem@hadrons.org>
+
+# LIBBSD_CHECK_COMPILER_FLAG
+# --------------------------
+AC_DEFUN([LIBBSD_CHECK_COMPILER_FLAG], [
+ AS_VAR_PUSHDEF([libbsd_varname_cache], [libbsd_cv_cflags_$1])
+ AC_CACHE_CHECK([whether $CC accepts $1], [libbsd_varname_cache], [
+ m4_define([libbsd_check_flag], m4_bpatsubst([$1], [^-Wno-], [-W]))
+ AS_VAR_COPY([libbsd_save_CFLAGS], [CFLAGS])
+ AS_VAR_SET([CFLAGS], ["-Werror libbsd_check_flag"])
+ AC_COMPILE_IFELSE([
+ AC_LANG_SOURCE([[]])
+ ], [
+ AS_VAR_SET([libbsd_varname_cache], [yes])
+ ], [
+ AS_VAR_SET([libbsd_varname_cache], [no])
+ ])
+ AS_VAR_COPY([CFLAGS], [libbsd_save_CFLAGS])
+ ])
+ AS_VAR_IF([libbsd_varname_cache], [yes], [
+ AS_VAR_APPEND([LIBBSD_COMPILER_FLAGS], [" $1"])
+ ])
+ AS_VAR_POPDEF([libbsd_varname_cache])
+])
+
+# LIBBSD_HAS_GNU_INIT_ARRAY
+# -------------------------
+AC_DEFUN([LIBBSD_HAS_GNU_INIT_ARRAY], [
+ AC_CACHE_CHECK([for GNU .init_array section support],
+ [libbsd_cv_gnu_init_array_support], [
+ AC_RUN_IFELSE([
+ AC_LANG_SOURCE([[
+static int rc = 1;
+static void init(int argc) { if (argc == 1) rc = 0; }
+void (*init_func)(int argc) __attribute__((__section__(".init_array"), __used__)) = init;
+int main() { return rc; }
+ ]])
+ ], [
+ libbsd_cv_gnu_init_array_support=yes
+ ], [
+ libbsd_cv_gnu_init_array_support=no
+ ], [
+ AC_PREPROC_IFELSE([
+ AC_LANG_SOURCE([[
+/* Look for a known libc that supports .init_array with the GNU extension
+ * to pass main() arguments to the init functions. */
+#include <stdlib.h>
+#if defined __GLIBC_PREREQ
+# if __GLIBC_PREREQ(2, 4)
+/* glibc supports GNU .init_array since 2.4. */
+# else
+# error glibc does not support GNU .init_array
+# endif
+#else
+/*
+ * Basic SysV ABI .init_array support, init functions do not get arguments:
+ * - Bionic since its inception.
+ * - uClibc since 0.9.29.
+ */
+# error unknown whether libc supports GNU .init_array
+#endif
+ ]])
+ ], [
+ libbsd_cv_gnu_init_array_support=yes
+ ], [
+ libbsd_cv_gnu_init_array_support=no
+ ])
+ ])
+ ])
+ AM_CONDITIONAL([BUILD_LIBBSD_CTOR],
+ [test "$libbsd_cv_gnu_init_array_support" = yes])
+])
+
+# LIBBSD_SELECT_API(name, desc)
+# -----------------
+AC_DEFUN([LIBBSD_SELECT_API], [
+ AS_IF([test -z "$AS_TR_SH([api_$1])"], [
+ AC_MSG_ERROR([missing API selection for $1])
+ ], [test "$AS_TR_SH([api_$1])" = "unknown"], [
+ AC_MSG_ERROR([unknown ABI selection for $1])
+ ], [test "$AS_TR_SH([api_$1])" = "yes"], [
+ AC_DEFINE(AS_TR_CPP([LIBBSD_API_$1]), [1], [Provide API for $2])
+ ], [
+ AC_DEFINE(AS_TR_CPP([LIBBSD_API_$1]), [0])
+ ])
+ AM_CONDITIONAL(AS_TR_CPP([API_$1]),
+ [test "x$AS_TR_SH([api_$1])" = "xyes"])
+])
+
+# LIBBSD_SELECT_ABI(name, desc)
+# -----------------
+AC_DEFUN([LIBBSD_SELECT_ABI], [
+ AS_IF([test -z "$AS_TR_SH([abi_$1])"], [
+ AC_MSG_ERROR([missing ABI selection for $1])
+ ], [test "$AS_TR_SH([abi_$1])" = "unknown"], [
+ AC_MSG_ERROR([unknown ABI selection for $1])
+ ], [test "$AS_TR_SH([abi_$1])" = "yes"], [
+ AC_DEFINE(AS_TR_CPP([LIBBSD_ABI_$1]), [1], [Provide ABI for $2])
+ ], [
+ AC_DEFINE(AS_TR_CPP([LIBBSD_ABI_$1]), [0])
+ ])
+ AM_CONDITIONAL(AS_TR_CPP([ABI_$1]),
+ [test "x$AS_TR_SH([abi_$1])" = "xyes"])
+])
diff --git a/m4/libbsd-funcs.m4 b/m4/libbsd-funcs.m4
new file mode 100644
index 0000000..379afc5
--- /dev/null
+++ b/m4/libbsd-funcs.m4
@@ -0,0 +1,57 @@
+# Copyright © 2011-2024 Guillem Jover <guillem@hadrons.org>
+
+# LIBBSD_CHECK_PROGNAME
+# ---------------------
+AC_DEFUN([LIBBSD_CHECK_PROGNAME], [
+ AC_MSG_CHECKING([for program_invocation_short_name])
+ AC_LINK_IFELSE([
+ AC_LANG_PROGRAM([[
+#include <errno.h>
+ ]], [[
+const char *p = program_invocation_short_name;
+ ]])
+ ], [
+ AC_DEFINE([HAVE_PROGRAM_INVOCATION_SHORT_NAME], [1],
+ [Define to 1 if you have program_invocation_short_name])
+ AC_MSG_RESULT([yes])
+ ], [
+ AC_MSG_RESULT([no])
+ ])
+
+ AC_MSG_CHECKING([for __progname])
+ AC_LINK_IFELSE([
+ AC_LANG_PROGRAM([[
+#include <stdio.h>
+extern char *__progname;
+ ]], [[
+printf("%s", __progname);
+ ]])
+ ], [
+ AC_DEFINE([HAVE___PROGNAME], [1], [Define to 1 if you have __progname])
+ AC_MSG_RESULT([yes])
+ ], [
+ AC_MSG_RESULT([no])
+ ])
+])
+
+# LIBBSD_CHECK_REGISTER_ATFORK
+# ----------------------------
+AC_DEFUN([LIBBSD_CHECK_REGISTER_ATFORK], [
+ AC_MSG_CHECKING([for __register_atfork])
+ AC_LINK_IFELSE([
+ AC_LANG_PROGRAM([[
+#include <stddef.h>
+extern void *__dso_handle;
+extern int __register_atfork(void (*)(void), void(*)(void), void (*)(void), void *);
+ ]], [[
+__register_atfork(NULL, NULL, NULL, __dso_handle);
+ ]])
+ ], [
+ AC_DEFINE([HAVE___REGISTER_ATFORK], [1],
+ [Define to 1 if you have __register_atfork])
+ AC_MSG_RESULT([yes])
+ ], [
+ LIBBSD_LIBS="$LIBBSD_LIBS -pthread"
+ AC_MSG_RESULT([no])
+ ])
+])
diff --git a/m4/libbsd-large.m4 b/m4/libbsd-large.m4
new file mode 100644
index 0000000..213f2cb
--- /dev/null
+++ b/m4/libbsd-large.m4
@@ -0,0 +1,61 @@
+# Copyright © 2024 Guillem Jover <guillem@hadrons.org>
+
+# LIBBSD_SYS_TIME64
+# -----------------
+# Check for availability of time64 support.
+AC_DEFUN([LIBBSD_SYS_TIME64], [
+ # Check the default time_t size.
+ AC_CHECK_SIZEOF([time_t], [], [[
+#undef _TIME_BITS
+#include <time.h>
+]])
+ AS_IF([test $ac_cv_sizeof_time_t -eq 8], [
+ libbsd_sys_time_bits=64
+ ], [
+ libbsd_sys_time_bits=32
+ ])
+ AC_DEFINE_UNQUOTED([LIBBSD_SYS_TIME_BITS], [$libbsd_sys_time_bits],
+ [The number of bits for the default system time_t ABI])
+ AC_SUBST([LIBBSD_SYS_TIME_BITS], [$libbsd_sys_time_bits])
+ AS_UNSET([ac_cv_sizeof_time_t])
+ AM_CONDITIONAL([LIBBSD_SYS_IS_TIME32], [test "$libbsd_sys_time_bits" -eq 32])
+
+ # Check the whether the system supports 64-bit time_t.
+ AC_CHECK_SIZEOF([time_t], [], [[
+#define _FILE_OFFSET_BITS 64
+#define _TIME_BITS 64
+#include <time.h>
+]])
+ AS_IF([test $ac_cv_sizeof_time_t -eq 8], [
+ libbsd_sys_has_time64=1
+ ], [
+ libbsd_sys_has_time64=0
+ ])
+ AC_DEFINE_UNQUOTED([LIBBSD_SYS_HAS_TIME64], [$libbsd_sys_has_time64],
+ [Enable if the system supports 64-bit time_t])
+ AC_SUBST([LIBBSD_SYS_HAS_TIME64], [$libbsd_sys_has_time64])
+ AM_CONDITIONAL([LIBBSD_SYS_HAS_TIME64], [test "$libbsd_sys_has_time64" -eq 1])
+ AS_IF([test "$libbsd_sys_time_bits" -eq 32 && \
+ test "$libbsd_sys_has_time64" -eq 1], [
+ abi_time64=yes
+ ], [
+ abi_time64=no
+ ])
+ LIBBSD_SELECT_ABI([time64], [explicit time64 time_t support])
+
+ AC_CHECK_SIZEOF([off_t], [], [[
+#define _FILE_OFFSET_BITS 64
+#include <sys/types.h>
+]])
+ AS_IF([test $ac_cv_sizeof_off_t = 8], [
+ libbsd_sys_has_lfs=1
+ ], [
+ libbsd_sys_has_lfs=0
+ ])
+
+ AS_IF([test $libbsd_sys_has_lfs -eq 1 && \
+ test $libbsd_sys_time_bits -eq 32 && \
+ test $ac_cv_sizeof_time_t -eq 8], [
+ AC_DEFINE([_TIME_BITS], [64], [Enable 64-bit time_t support])
+ ])
+])
diff --git a/m4/libbsd-linker.m4 b/m4/libbsd-linker.m4
new file mode 100644
index 0000000..394bac5
--- /dev/null
+++ b/m4/libbsd-linker.m4
@@ -0,0 +1,27 @@
+# Copyright © 2019, 2022 Guillem Jover <guillem@hadrons.org>
+
+# LIBBSD_LINKER_VERSION_SCRIPT
+# ----------------------------
+AC_DEFUN([LIBBSD_LINKER_VERSION_SCRIPT], [
+ AC_CACHE_CHECK([if ld supports --version-script flag],
+ [libbsd_cv_version_script], [
+ echo "{ global: symbol; local: *; };" >conftest.map
+ save_LDFLAGS=$LDFLAGS
+ LDFLAGS="$LDFLAGS -Wl,--version-script=conftest.map"
+ AC_LINK_IFELSE([
+ AC_LANG_PROGRAM([[
+extern int symbol(void);
+int symbol(void) { return 0; }
+]], [[
+]])
+ ], [
+ libbsd_cv_version_script=yes
+ ], [
+ libbsd_cv_version_script=no
+ ])
+ LDFLAGS="$save_LDFLAGS"
+ rm -f conftest.map
+ ])
+ AM_CONDITIONAL([HAVE_LINKER_VERSION_SCRIPT],
+ [test "x$libbsd_cv_version_script" = "xyes"])
+])
diff --git a/man/Makefile.am b/man/Makefile.am
index 5dd37bf..02c8ffb 100644
--- a/man/Makefile.am
+++ b/man/Makefile.am
@@ -2,16 +2,16 @@
EXTRA_DIST = \
mdX.3bsd \
- $(nil)
+ # EOL
CLEANFILES = \
md5.3bsd \
- $(nil)
+ # EOL
SED_MD5_SUBST = -e 's/mdX/md5/g' -e 's/mdY/md4/g' -e 's/MDX/MD5/g'
md5.3bsd: $(srcdir)/mdX.3bsd
- $(AM_V_GEN) sed $(SED_MD5_SUBST) $< > $@
+ $(AM_V_GEN) $(SED) $(SED_MD5_SUBST) $< >$@
dist_man_MANS = \
LIST_CLASS_ENTRY.3bsd \
@@ -141,13 +141,6 @@ dist_man_MANS = \
TAILQ_PREV.3bsd \
TAILQ_REMOVE.3bsd \
TAILQ_SWAP.3bsd \
- TIMESPEC_TO_TIMEVAL.3bsd \
- TIMEVAL_TO_TIMESPEC.3bsd \
- arc4random.3bsd \
- arc4random_addrandom.3bsd \
- arc4random_buf.3bsd \
- arc4random_stir.3bsd \
- arc4random_uniform.3bsd \
be16dec.3bsd \
be16enc.3bsd \
be32dec.3bsd \
@@ -166,89 +159,277 @@ dist_man_MANS = \
bitstr_size.3bsd \
bitstring.3bsd \
byteorder.3bsd \
+ le16dec.3bsd \
+ le16enc.3bsd \
+ le32dec.3bsd \
+ le32enc.3bsd \
+ le64dec.3bsd \
+ le64enc.3bsd \
+ libbsd.7 \
+ queue.3bsd \
+ timeradd.3bsd \
+ timerclear.3bsd \
+ timercmp.3bsd \
+ timerisset.3bsd \
+ timersub.3bsd \
+ timespecadd.3bsd \
+ timespecclear.3bsd \
+ timespeccmp.3bsd \
+ timespecisset.3bsd \
+ timespecsub.3bsd \
+ tree.3bsd \
+ # EOL
+
+if API_TIME_MACROS
+dist_man_MANS += \
+ TIMESPEC_TO_TIMEVAL.3bsd \
+ TIMEVAL_TO_TIMESPEC.3bsd \
+ # EOL
+endif
+
+if ABI_ACCMODE
+dist_man_MANS += \
+ getmode.3bsd \
+ setmode.3bsd \
+ # EOL
+endif
+
+if ABI_ARC4RANDOM
+dist_man_MANS += \
+ arc4random.3bsd \
+ arc4random_addrandom.3bsd \
+ arc4random_buf.3bsd \
+ arc4random_stir.3bsd \
+ arc4random_uniform.3bsd \
+ # EOL
+endif
+
+if ABI_CLOSEFROM
+dist_man_MANS += \
closefrom.3bsd \
- dehumanize_number.3bsd \
+ # EOL
+endif
+
+if ABI_ERRC
+dist_man_MANS += \
errc.3bsd \
+ verrc.3bsd \
+ vwarnc.3bsd \
+ warnc.3bsd \
+ # EOL
+endif
+
+if ABI_EXPAND_NUMBER
+dist_man_MANS += \
expand_number.3bsd \
+ # EOL
+endif
+
+if ABI_EXPLICIT_BZERO
+dist_man_MANS += \
explicit_bzero.3bsd \
+ # EOL
+endif
+
+if ABI_FGETLN
+dist_man_MANS += \
fgetln.3bsd \
fgetwln.3bsd \
+ fparseln.3bsd \
+ # EOL
+endif
+
+if ABI_FLOPEN
+dist_man_MANS += \
flopen.3bsd \
- freezero.3bsd \
+ # EOL
+endif
+
+if ABI_FMTCHECK
+dist_man_MANS += \
fmtcheck.3bsd \
- fparseln.3bsd \
+ # EOL
+endif
+
+if ABI_FPURGE
+dist_man_MANS += \
fpurge.3bsd \
+ # EOL
+endif
+
+if ABI_FREEZERO
+dist_man_MANS += \
+ freezero.3bsd \
+ # EOL
+endif
+
+if ABI_FUNOPEN
+dist_man_MANS += \
funopen.3bsd \
+ # EOL
+endif
+
+if ABI_GETBSIZE
+dist_man_MANS += \
getbsize.3bsd \
- getmode.3bsd \
+ # EOL
+endif
+
+if ABI_GETPEEREID
+dist_man_MANS += \
getpeereid.3bsd \
- getprogname.3bsd \
- gid_from_group.3bsd \
- group_from_gid.3bsd \
- heapsort.3bsd \
+ # EOL
+endif
+
+if ABI_HUMANIZE_NUMBER
+dist_man_MANS += \
+ dehumanize_number.3bsd \
humanize_number.3bsd \
- le16dec.3bsd \
- le16enc.3bsd \
- le32dec.3bsd \
- le32enc.3bsd \
- le64dec.3bsd \
- le64enc.3bsd \
- libbsd.7 \
+ # EOL
+endif
+
+if ABI_MD5
+dist_man_MANS += \
md5.3bsd \
- mergesort.3bsd \
+ # EOL
+endif
+
+if ABI_NLIST
+dist_man_MANS += \
nlist.3bsd \
+ # EOL
+endif
+
+if ABI_PIDFILE
+dist_man_MANS += \
pidfile.3bsd \
pidfile_close.3bsd \
pidfile_open.3bsd \
pidfile_remove.3bsd \
pidfile_write.3bsd \
+ # EOL
+endif
+
+if ABI_PROCTITLE
+dist_man_MANS += \
+ setproctitle.3bsd \
+ setproctitle_init.3bsd \
+ # EOL
+endif
+
+if ABI_PROGNAME
+dist_man_MANS += \
+ getprogname.3bsd \
+ setprogname.3bsd \
+ # EOL
+endif
+
+if ABI_PWCACHE
+dist_man_MANS += \
pwcache.3bsd \
- queue.3bsd \
- radixsort.3bsd \
+ gid_from_group.3bsd \
+ uid_from_user.3bsd \
+ # EOL
+
+if ABI_NAME_FROM_ID
+dist_man_MANS += \
+ group_from_gid.3bsd \
+ user_from_uid.3bsd \
+ # EOL
+endif
+endif
+
+if ABI_READPASSPHRASE
+dist_man_MANS += \
readpassphrase.3bsd \
+ # EOL
+endif
+
+if ABI_REALLOCARRAY
+dist_man_MANS += \
reallocarray.3bsd \
+ # EOL
+endif
+
+if ABI_REALLOCF
+dist_man_MANS += \
reallocf.3bsd \
+ # EOL
+endif
+
+if ABI_RECALLOCARRAY
+dist_man_MANS += \
recallocarray.3bsd \
- setmode.3bsd \
- setproctitle.3bsd \
- setproctitle_init.3bsd \
- setprogname.3bsd \
+ # EOL
+endif
+
+if ABI_SORT
+dist_man_MANS += \
+ heapsort.3bsd \
+ mergesort.3bsd \
+ radixsort.3bsd \
+ sradixsort.3bsd \
+ # EOL
+endif
+
+if ABI_STRINGLIST
+dist_man_MANS += \
sl_add.3bsd \
sl_delete.3bsd \
sl_find.3bsd \
sl_free.3bsd \
sl_init.3bsd \
- sradixsort.3bsd \
stringlist.3bsd \
+ # EOL
+endif
+
+if ABI_STRL
+dist_man_MANS += \
strlcat.3bsd \
strlcpy.3bsd \
+ # EOL
+endif
+
+if ABI_STRMODE
+dist_man_MANS += \
strmode.3bsd \
+ # EOL
+endif
+
+if ABI_STRNSTR
+dist_man_MANS += \
strnstr.3bsd \
- strnunvis.3bsd \
- strnvis.3bsd \
+ # EOL
+endif
+
+if ABI_STRTOX
+dist_man_MANS += \
strtoi.3bsd \
- strtonum.3bsd \
strtou.3bsd \
+ # EOL
+endif
+
+if ABI_STRTONUM
+dist_man_MANS += \
+ strtonum.3bsd \
+ # EOL
+endif
+
+if ABI_VIS
+dist_man_MANS += \
+ strnunvis.3bsd \
+ strnvis.3bsd \
strunvis.3bsd \
strvis.3bsd \
strvisx.3bsd \
- timeradd.3bsd \
- timerclear.3bsd \
- timercmp.3bsd \
- timerisset.3bsd \
- timersub.3bsd \
- timespec.3bsd \
- timespecadd.3bsd \
- timespecclear.3bsd \
- timespeccmp.3bsd \
- timespecisset.3bsd \
- timespecsub.3bsd \
- timeval.3bsd \
- tree.3bsd \
- uid_from_user.3bsd \
unvis.3bsd \
- user_from_uid.3bsd \
vis.3bsd \
+ # EOL
+endif
+
+if ABI_WCSL
+dist_man_MANS += \
wcslcat.3bsd \
wcslcpy.3bsd \
- $(nil)
+ # EOL
+endif
diff --git a/man/TIMESPEC_TO_TIMEVAL.3bsd b/man/TIMESPEC_TO_TIMEVAL.3bsd
index e47176e..28ebcf4 100644
--- a/man/TIMESPEC_TO_TIMEVAL.3bsd
+++ b/man/TIMESPEC_TO_TIMEVAL.3bsd
@@ -1 +1,100 @@
-.so man3/timeval.3bsd
+.\" $NetBSD: timeval.3,v 1.12 2011/04/12 08:39:26 jruoho Exp $
+.\"
+.\" Copyright (c) 2010 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Jukka Ruohonen.
+.\"
+.\" 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 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.
+.\"
+.Dd April 12, 2011
+.Dt TIMEVAL_TO_TIMESPEC 3bsd
+.Os
+.Sh NAME
+.Nm TIMEVAL_TO_TIMESPEC ,
+.Nm TIMESPEC_TO_TIMEVAL
+.Nd time structures conversion macros
+.Sh LIBRARY
+.ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd)
+.ds doc-str-Lb-libbsd \*[str-Lb-libbsd]
+.Lb libbsd
+.Sh SYNOPSIS
+.In sys/time.h
+(See
+.Xr libbsd 7
+for include usage.)
+.Ft void
+.Fn TIMEVAL_TO_TIMESPEC "struct timeval *tv" "struct timespec *ts"
+.Ft void
+.Fn TIMESPEC_TO_TIMEVAL "struct timeval *tv" "struct timespec *ts"
+.Sh DESCRIPTION
+The
+.Va timeval
+structure represents elapsed time, in whole seconds,
+and the rest of the elapsed time in microseconds.
+.Pp
+The
+.Va timespec
+structure represents elapsed time, in whole seconds,
+and the rest of the elapsed time in nanoseconds.
+.Pp
+A microsecond is equal to one millionth of a second,
+1000 nanoseconds, or 1/1000 milliseconds.
+To ease the conversions, the macros
+.Fn TIMEVAL_TO_TIMESPEC
+and
+.Fn TIMESPEC_TO_TIMEVAL
+can be used to convert between
+.Em struct timeval
+and
+.Em struct timespec .
+.Sh EXAMPLES
+It can be stressed that the traditional
+.Tn UNIX
+.Va timeval
+and
+.Va timespec
+structures represent elapsed time, measured by the system clock.
+The following sketch implements a function suitable
+for use in a context where the
+.Va timespec
+structure is required for a conditional timeout:
+.Bd -literal -offset indent
+static void
+example(struct timespec *spec, time_t minutes)
+{
+ struct timeval elapsed;
+
+ (void)gettimeofday(&elapsed, NULL);
+
+ TIMEVAL_TO_TIMESPEC(&elapsed, spec);
+
+ /* Add the offset for timeout in minutes. */
+ spec->tv_sec = spec->tv_sec + minutes * 60;
+}
+.Ed
+.Pp
+A better alternative would use the more precise
+.Xr clock_gettime 2 .
+.Sh SEE ALSO
+.Xr timeradd 3bsd
diff --git a/man/TIMEVAL_TO_TIMESPEC.3bsd b/man/TIMEVAL_TO_TIMESPEC.3bsd
index e47176e..7741548 100644
--- a/man/TIMEVAL_TO_TIMESPEC.3bsd
+++ b/man/TIMEVAL_TO_TIMESPEC.3bsd
@@ -1 +1 @@
-.so man3/timeval.3bsd
+.so man3/TIMESPEC_TO_TIMEVAL.3bsd
diff --git a/man/arc4random.3bsd b/man/arc4random.3bsd
index c509a8e..7205f44 100644
--- a/man/arc4random.3bsd
+++ b/man/arc4random.3bsd
@@ -1,8 +1,11 @@
-.\" $OpenBSD: arc4random.3,v 1.34 2014/07/19 16:11:16 naddy Exp $
+.\" $NetBSD: arc4random.3,v 1.21 2016/07/15 21:19:19 wiz Exp $
.\"
-.\" Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
+.\" Copyright (c) 2014 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Taylor R. Campbell.
+.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
@@ -11,35 +14,29 @@
.\" 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 Niels Provos.
-.\" 4. The name of the author may not be used to endorse or promote products
-.\" derived from this software without specific prior written permission.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
.\"
-.\" Manual page, using -mandoc macros
+.\" 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.
.\"
-.Dd $Mdocdate: July 19 2014 $
-.Dt ARC4RANDOM 3bsd
+.Dd November 16, 2014
+.Dt arc4random 3bsd
.Os
.Sh NAME
.Nm arc4random ,
-.Nm arc4random_buf ,
.Nm arc4random_uniform ,
+.Nm arc4random_buf ,
.Nm arc4random_stir ,
.Nm arc4random_addrandom
-.Nd arc4 random number generator
+.Nd random number generator
.Sh LIBRARY
.ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd)
.ds doc-str-Lb-libbsd \*[str-Lb-libbsd]
@@ -51,83 +48,208 @@
for include usage.)
.Ft uint32_t
.Fn arc4random "void"
-.Ft void
-.Fn arc4random_buf "void *buf" "size_t nbytes"
.Ft uint32_t
-.Fn arc4random_uniform "uint32_t upper_bound"
+.Fn arc4random_uniform "uint32_t bound"
+.Ft void
+.Fn arc4random_buf "void *buf" "size_t len"
.Ft void
.Fn arc4random_stir "void"
.Ft void
-.Fn arc4random_addrandom "unsigned char *dat" "int datlen"
+.Fn arc4random_addrandom "unsigned char *buf" "int len"
.Sh DESCRIPTION
-This family of functions provides higher quality data than those
-described in
-.Xr rand 3 ,
-.Xr random 3 ,
-and
-.Xr rand48 3 .
-.Pp
-Use of these functions is encouraged for almost all random number
-consumption because the other interfaces are deficient in either
-quality, portability, standardization, or availability.
-These functions can be called in almost all coding environments,
-including
-.Xr pthreads 3
+The
+.Nm
+family of functions provides a cryptographic pseudorandom number
+generator automatically seeded from the system entropy pool and safe to
+use from multiple threads.
+.Nm
+is designed to prevent an adversary from guessing outputs,
+unlike
+.Xr rand 3
and
-.Xr chroot 2 .
-.Pp
-High quality 32-bit pseudo-random numbers are generated very quickly.
-On each call, a cryptographic pseudo-random number generator is used
-to generate a new result.
-One data pool is used for all consumers in a process, so that consumption
-under program flow can act as additional stirring.
-The subsystem is re-seeded from the kernel random number subsystem using
-.Xr getentropy 2
-on a regular basis, and also upon
-.Xr fork 2 .
+.Xr random 3 ,
+and is faster and more convenient than reading from
+.Pa /dev/urandom
+directly.
.Pp
-The
.Fn arc4random
-function returns a single 32-bit value.
-.Pp
-The
-.Fn arc4random_buf
-function fills the region
-.Fa buf
-of length
-.Fa nbytes
-with random data.
+returns an integer in [0, 2^32) chosen independently with uniform
+distribution.
.Pp
.Fn arc4random_uniform
-will return a single 32-bit value, uniformly distributed but less than
-.Fa upper_bound .
-This is recommended over constructions like
-.Dq Li arc4random() % upper_bound
-as it avoids "modulo bias" when the upper bound is not a power of two.
-In the worst case, this function may consume multiple iterations
-to ensure uniformity; see the source code to understand the problem
-and solution.
+returns an integer in [0,
+.Fa bound )
+chosen independently with uniform distribution.
+.Pp
+.Fn arc4random_buf
+stores
+.Fa len
+bytes into the memory pointed to by
+.Fa buf ,
+each byte chosen independently from [0, 256) with uniform
+distribution.
.Pp
-The
.Fn arc4random_stir
-function reads data from
-.Xr getentropy 2
-and uses it to re-seed the subsystem via
-.Fn arc4random_addrandom .
+draws entropy from the operating system and incorporates it into the
+library's PRNG state to influence future outputs.
.Pp
-There is no need to call
+.Fn arc4random_addrandom
+incorporates
+.Fa len
+bytes, which must be nonnegative, from the buffer
+.Fa buf ,
+into the library's PRNG state to influence future outputs.
+.Pp
+It is not necessary for an application to call
.Fn arc4random_stir
-before using
+or
+.Fn arc4random_addrandom
+before calling other
+.Nm
+functions.
+The first call to any
+.Nm
+function will initialize the PRNG state unpredictably from the system
+entropy pool.
+.Sh SECURITY MODEL
+The
+.Nm
+functions provide the following security properties against three
+different classes of attackers, assuming enough entropy is provided by
+the operating system:
+.Bl -enum -offset abcd
+.It
+An attacker who has seen some outputs of any of the
+.Nm
+functions cannot predict past or future unseen outputs.
+.It
+An attacker who has seen the library's PRNG state in memory cannot
+predict past outputs.
+.It
+An attacker who has seen one process's PRNG state cannot predict past
+or future outputs in other processes, particularly its parent or
+siblings.
+.El
+.Pp
+One
+.Sq output
+means the result of any single request to an
+.Nm
+function, no matter how short it is.
+.Pp
+The second property is sometimes called
+.Sq forward secrecy ,
+.Sq backtracking resistance ,
+or
+.Sq key erasure after each output .
+.Sh IMPLEMENTATION NOTES
+The
+.Nm
+functions are currently implemented using the ChaCha20 pseudorandom
+function family.
+For any 32-byte string
+.Fa s ,
+.Pf ChaCha20_ Fa s
+is a function from 16-byte strings to 64-byte strings.
+It is conjectured that if
+.Fa s
+is chosen with uniform distribution, then the distribution on
+.Pf ChaCha20_ Fa s
+is indistinguishable to a computationally bounded adversary from a
+uniform distribution on all functions from 16-byte strings to 64-byte
+strings.
+.Pp
+The PRNG state is a 32-byte ChaCha20 key
+.Fa s .
+Each request to
+an
+.Nm
+function
+.Bl -bullet -offset abcd -compact
+.It
+computes the 64-byte quantity
+.Fa x
+=
+.Pf ChaCha20_ Fa s Ns Pq 0 ,
+.It
+splits
+.Fa x
+into two 32-byte quantities
+.Fa s'
+and
+.Fa k ,
+.It
+replaces
+.Fa s
+by
+.Fa s' ,
+and
+.It
+uses
+.Fa k
+as output.
+.El
+.Pp
+.Fn arc4random
+yields the first four bytes of
+.Fa k
+as output directly.
+.Fn arc4random_buf
+either yields up to 32 bytes of
+.Fa k
+as output directly, or, for longer
+requests, uses
+.Fa k
+as a ChaCha20 key and yields the concatenation
+.Pf ChaCha20_ Fa k Ns Pq 0
+||
+.Pf ChaCha20_ Fa k Ns Pq 1
+|| ... as output.
+.Fn arc4random_uniform
+repeats
.Fn arc4random
-functions family, since
-they automatically initialize themselves.
-.Sh RETURN VALUES
-These functions are always successful, and no return value is
-reserved to indicate an error.
+until it obtains an integer in [2^32 %
+.Fa bound ,
+2^32), and reduces that modulo
+.Fa bound .
+.Pp
+The PRNG state is per-thread, unless memory allocation fails inside the
+library, in which case some threads may share global PRNG state with a
+mutex.
+The global PRNG state is zeroed on fork in the parent via
+.Xr pthread_atfork 3 ,
+and the per-thread PRNG state is zeroed on fork in the child via
+.Xr minherit 2
+with
+.Dv MAP_INHERIT_ZERO ,
+so that the child cannot reuse or see the parent's PRNG state.
+The PRNG state is reseeded automatically from the system entropy pool
+on the first use of an
+.Nm
+function after zeroing.
+.Pp
+The first use of an
+.Nm
+function may abort the process in the highly unlikely event that
+library initialization necessary to implement the security model fails.
+Additionally,
+.Fn arc4random_stir
+and
+.Fn arc4random_addrandom
+may abort the process in the highly unlikely event that the operating
+system fails to provide entropy.
.Sh SEE ALSO
.Xr rand 3 ,
-.Xr rand48 3 ,
-.Xr random 3
+.Xr random 3 ,
+.Xr rnd 4 ,
+.Xr cprng 9
+.Rs
+.%A Daniel J. Bernstein
+.%T ChaCha, a variant of Salsa20
+.%D 2008-01-28
+.%O Document ID: 4027b5256e17b9796842e6d0f68b0b5e
+.%U http://cr.yp.to/papers.html#chacha
+.Re
.Sh HISTORY
These functions first appeared in
.Ox 2.1 ,
@@ -135,12 +257,85 @@ These functions first appeared in
.Nx 1.6 ,
and
.Dx 1.0 .
+The functions
+.Fn arc4random ,
+.Fn arc4random_buf
+and
+.Fn arc4random_uniform
+appeared in glibc 2.36.
+.Sh BUGS
+There is no way to get deterministic, reproducible results out of
+.Nm
+for testing purposes.
+.Pp
+The name
+.Sq arc4random
+was chosen for hysterical raisins -- it was originally implemented
+using the RC4 stream cipher, which has been known since shortly after
+it was published in 1994 to have observable biases in the output, and
+is now known to be broken badly enough to admit practical attacks in
+the real world.
+.\" Bob Jenkins, sci.crypt post dated 1994-09-16, message-id
+.\" <359qjg$55v$1@mhadg.production.compuserve.com>,
+.\" https://groups.google.com/d/msg/sci.crypt/JsO3xEATGFA/-wO4ttv7BCYJ
+.\"
+.\" Andrew Roos, `A Class of Weak Keys in the RC4 Stream Cipher',
+.\" sci.crypt posts dated 1995-09-22, message-ids
+.\" <43u1eh$1j3@hermes.is.co.za> and <44ebge$llf@hermes.is.co.za>.
+.\"
+.\" Paul Crowley, `Small bias in RC4 experimentally verified', March
+.\" 1998, http://www.ciphergoth.org/crypto/rc4/
+Unfortunately, the library found widespread adoption and the name stuck
+before anyone recognized that it was silly.
+.Pp
+The signature of
+.Fn arc4random_addrandom
+is silly.
+There is no reason to require casts or accept negative lengths:
+it should take a
+.Vt void *
+buffer and a
+.Vt size_t
+length.
+But it's too late to change that now.
+.Pp
+.Fn arc4random_uniform
+does not help to choose integers in [0,
+.Fa n )
+uniformly at random when
+.Fa n
+> 2^32.
+.Pp
+The security model of
+.Nm
+is stronger than many applications need, and stronger than other
+operating systems provide.
+For example, applications encrypting messages with random, but not
+secret, initialization vectors need only prevent an adversary from
+guessing future outputs, since past outputs will have been published
+already.
+.Pp
+On the one hand,
+.Nm
+could be marginally faster if it were not necessary to prevent an
+adversary who sees the state from predicting past outputs.
+On the other hand, there are applications in the wild that use
+.Nm
+to generate key material, such as OpenSSH, so for the sake of
+.Nx
+users it would be imprudent to weaken the security model.
+On the third hand, relying on the security model of
+.Nm
+in
+.Nx
+may lead you to an unpleasant surprise on another operating system
+whose implementation of
+.Nm
+has a weaker security model.
.Pp
-The original version of this random number generator used the
-RC4 (also known as ARC4) algorithm.
-In
-.Ox 5.5
-it was replaced with the ChaCha20 cipher, and it may be replaced
-again in the future as cryptographic techniques advance.
-A good mnemonic is
-.Dq A Replacement Call for Random .
+One may be tempted to create new APIs to accommodate different
+security models and performance constraints without unpleasant
+surprises on different operating systems.
+This should not be done lightly, though, because there are already too
+many different choices, and too many opportunities for programmers to
+reach for one and pick the wrong one.
diff --git a/man/bitstring.3bsd b/man/bitstring.3bsd
index 6006af0..feb919d 100644
--- a/man/bitstring.3bsd
+++ b/man/bitstring.3bsd
@@ -31,7 +31,7 @@
.\" $FreeBSD$
.\"
.Dd July 19, 1993
-.Dt BITSTRING 3bsd
+.Dt bitstring 3bsd
.Os
.Sh NAME
.Nm bit_alloc ,
diff --git a/man/byteorder.3bsd b/man/byteorder.3bsd
index 5e5d6d3..635a6a1 100644
--- a/man/byteorder.3bsd
+++ b/man/byteorder.3bsd
@@ -25,7 +25,7 @@
.\" $FreeBSD$
.\"
.Dd April 29, 2002
-.Dt BYTEORDER 3bsd
+.Dt byteorder 3bsd
.Os
.Sh NAME
.Nm be16enc , be16dec , be32enc , be32dec , be64enc , be64dec ,
diff --git a/man/closefrom.3bsd b/man/closefrom.3bsd
index b2d3853..eff6c64 100644
--- a/man/closefrom.3bsd
+++ b/man/closefrom.3bsd
@@ -26,7 +26,7 @@
.\" $FreeBSD$
.\"
.Dd June 12, 2009
-.Dt CLOSEFROM 3bsd
+.Dt closefrom 3bsd
.Os
.Sh NAME
.Nm closefrom
@@ -51,8 +51,17 @@ from the per-process object reference table.
Any errors encountered while closing file descriptors are ignored.
.Sh SEE ALSO
.Xr close 2
+.Sh STANDARDS
+.Fn closefrom
+is a
+.Bx
+and Solaris extension.
.Sh HISTORY
The
.Fn closefrom
-function first appeared in
-.Fx 8.0 .
+function first appeared in Solaris 9,
+.Ox 3.5 ,
+.Dx 1.2 ,
+.Nx 3.0 ,
+.Fx 8.0
+and glibc 2.34.
diff --git a/man/errc.3bsd b/man/errc.3bsd
index b330b6b..964a528 100644
--- a/man/errc.3bsd
+++ b/man/errc.3bsd
@@ -28,7 +28,7 @@
.\" SUCH DAMAGE.
.\"
.Dd $Mdocdate: April 23 2014 $
-.Dt ERRC 3bsd
+.Dt errc 3bsd
.Os
.Sh NAME
.Nm errc ,
diff --git a/man/expand_number.3bsd b/man/expand_number.3bsd
index e0ba501..c8050f4 100644
--- a/man/expand_number.3bsd
+++ b/man/expand_number.3bsd
@@ -26,7 +26,7 @@
.\" $FreeBSD$
.\"
.Dd August 15, 2010
-.Dt EXPAND_NUMBER 3bsd
+.Dt expand_number 3bsd
.Os
.Sh NAME
.Nm expand_number
diff --git a/man/explicit_bzero.3bsd b/man/explicit_bzero.3bsd
index ca077b3..5b55dc9 100644
--- a/man/explicit_bzero.3bsd
+++ b/man/explicit_bzero.3bsd
@@ -30,7 +30,7 @@
.\" $OpenBSD: bzero.3,v 1.10 2014/01/22 21:06:45 tedu Exp $
.\"
.Dd $Mdocdate: January 22 2014 $
-.Dt EXPLICIT_BZERO 3bsd
+.Dt explicit_bzero 3bsd
.Os
.Sh NAME
.Nm explicit_bzero
diff --git a/man/fgetln.3bsd b/man/fgetln.3bsd
index c9f7059..685e05f 100644
--- a/man/fgetln.3bsd
+++ b/man/fgetln.3bsd
@@ -29,7 +29,7 @@
.\" $FreeBSD: /repoman/r/ncvs/src/lib/libc/stdio/fgetln.3,v 1.8 2004/07/16 06:07:12 tjr Exp $
.\"
.Dd April 19, 1994
-.Dt FGETLN 3bsd
+.Dt fgetln 3bsd
.Os
.Sh NAME
.Nm fgetln
diff --git a/man/fgetwln.3bsd b/man/fgetwln.3bsd
index 21b8695..0f1f3cb 100644
--- a/man/fgetwln.3bsd
+++ b/man/fgetwln.3bsd
@@ -29,7 +29,7 @@
.\" $FreeBSD$
.\"
.Dd July 16, 2004
-.Dt FGETWLN 3bsd
+.Dt fgetwln 3bsd
.Os
.Sh NAME
.Nm fgetwln
diff --git a/man/flopen.3bsd b/man/flopen.3bsd
index 6ee153c..e0816ba 100644
--- a/man/flopen.3bsd
+++ b/man/flopen.3bsd
@@ -26,7 +26,7 @@
.\" $FreeBSD$
.\"
.Dd July 28, 2017
-.Dt FLOPEN 3bsd
+.Dt flopen 3bsd
.Os
.Sh NAME
.Nm flopen ,
diff --git a/man/fmtcheck.3bsd b/man/fmtcheck.3bsd
index 93e7673..9fb769f 100644
--- a/man/fmtcheck.3bsd
+++ b/man/fmtcheck.3bsd
@@ -27,7 +27,7 @@
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd June 14, 2014
-.Dt FMTCHECK 3bsd
+.Dt fmtcheck 3bsd
.Os
.Sh NAME
.Nm fmtcheck
diff --git a/man/fparseln.3bsd b/man/fparseln.3bsd
index 0f9ebc8..b227f0d 100644
--- a/man/fparseln.3bsd
+++ b/man/fparseln.3bsd
@@ -23,7 +23,7 @@
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd November 30, 2002
-.Dt FPARSELN 3bsd
+.Dt fparseln 3bsd
.Os
.Sh NAME
.Nm fparseln
@@ -150,4 +150,6 @@ if it runs out of memory.
The
.Fn fparseln
function first appeared in
-.Nx 1.4 .
+.Nx 1.4
+and
+.Fx 4.0 .
diff --git a/man/fpurge.3bsd b/man/fpurge.3bsd
index eb3fc95..1a7dc58 100644
--- a/man/fpurge.3bsd
+++ b/man/fpurge.3bsd
@@ -32,7 +32,7 @@
.\" SUCH DAMAGE.
.\"
.Dd $Mdocdate: November 4 2015 $
-.Dt FPURGE 3bsd
+.Dt fpurge 3bsd
.Os
.Sh NAME
.Nm fpurge
diff --git a/man/funopen.3bsd b/man/funopen.3bsd
index b322525..234922f 100644
--- a/man/funopen.3bsd
+++ b/man/funopen.3bsd
@@ -31,7 +31,7 @@
.\" $FreeBSD$
.\"
.Dd March 19, 2004
-.Dt FUNOPEN 3bsd
+.Dt funopen 3bsd
.Os
.Sh NAME
.Nm funopen ,
@@ -168,9 +168,12 @@ functions first appeared in
.Sh BUGS
The
.Fn funopen
-function
-may not be portable to systems other than
-.Bx .
+function may not be portable to systems other than
+.Bx ,
+glibc- and musl-based ones
+(as the libbsd implementation is only provided when the system has
+.Fn fopencookie
+available).
.Pp
On
.Fx ,
diff --git a/man/getbsize.3bsd b/man/getbsize.3bsd
index d091db3..b371a7f 100644
--- a/man/getbsize.3bsd
+++ b/man/getbsize.3bsd
@@ -29,7 +29,7 @@
.\" $FreeBSD$
.\"
.Dd November 16, 2012
-.Dt GETBSIZE 3bsd
+.Dt getbsize 3bsd
.Os
.Sh NAME
.Nm getbsize
diff --git a/man/getpeereid.3bsd b/man/getpeereid.3bsd
index cce3909..4cc7cc6 100644
--- a/man/getpeereid.3bsd
+++ b/man/getpeereid.3bsd
@@ -26,7 +26,7 @@
.\" $FreeBSD$
.\"
.Dd July 15, 2001
-.Dt GETPEEREID 3bsd
+.Dt getpeereid 3bsd
.Os
.Sh NAME
.Nm getpeereid
@@ -139,4 +139,7 @@ or the kernel returned invalid data.
The
.Fn getpeereid
function appeared in
-.Fx 4.6 .
+.Fx 4.6 ,
+.Nx 5.0
+and
+.Ox 3.0 .
diff --git a/man/getprogname.3bsd b/man/getprogname.3bsd
index d2a3e34..e933f34 100644
--- a/man/getprogname.3bsd
+++ b/man/getprogname.3bsd
@@ -1,6 +1,4 @@
-.\"
-.\" Copyright (c) 2001 Christopher G. Demetriou
-.\" All rights reserved.
+.\" Copyright (c) 2022 Guillem Jover <guillem@hadrons.org>
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
@@ -10,34 +8,27 @@
.\" 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 for the
-.\" NetBSD Project. See http://www.netbsd.org/ for
-.\" information about NetBSD.
-.\" 4. The name of the author may not be used to endorse or promote products
+.\" 3. The name of the author may not be used to endorse or promote products
.\" derived from this software without specific prior written permission.
+.\" .
+.\" THIS SOFTWARE IS PROVIDED ``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 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.
.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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$
-.\"
-.Dd May 1, 2001
-.Dt GETPROGNAME 3bsd
+.Dd August 03, 2022
+.Dt getprogname 3bsd
.Os
.Sh NAME
.Nm getprogname ,
.Nm setprogname
-.Nd get or set the program name
+.Nd get and set program name
.Sh LIBRARY
.ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd)
.ds doc-str-Lb-libbsd \*[str-Lb-libbsd]
@@ -54,46 +45,39 @@ for include usage.)
.Sh DESCRIPTION
The
.Fn getprogname
-and
-.Fn setprogname
-functions manipulate the name of the current program.
-They are used by error-reporting routines to produce
-consistent output.
-.Pp
-The
-.Fn getprogname
-function returns the name of the program.
-If the name has not been set yet, it will return
-.Dv NULL .
+returns a string with the current program name,
+excluding any directory component.
+The function will return
+.Dv NULL
+if it was unable to get the program name from any known source.
.Pp
The
.Fn setprogname
-function sets the name of the program to be the last component of the
-.Fa progname
-argument.
-Since a pointer to the given string is kept as the program name,
-it should not be modified for the rest of the program's lifetime.
+function sets the current program name,
+stripping any directory component prefix.
+The function will keep a reference to the passed string pointer,
+so it must not be freed or modified while these functions might
+be called.
.Pp
-In
-.Fx ,
-the name of the program is set by the start-up code that is run before
-.Fn main ;
-thus,
-running
-.Fn setprogname
-is not necessary.
-Programs that desire maximum portability should still call it;
-on another operating system,
-these functions may be implemented in a portability library.
-Calling
-.Fn setprogname
-allows the aforementioned library to learn the program name without
-modifications to the start-up code.
+The implementations on most BSDs will try to initialize the program name
+at program startup time, and
+.Nm libbsd
+will try to infer it from various known sources depending on the
+target system.
+But it is not a portable assumption that the program name will be set
+without calling
+.Fn setprogname ,
+so portable programs should always call it after starting up.
.Sh SEE ALSO
-.Xr err 3 ,
-.Xr setproctitle 3bsd
+.Xr setproctitle 3bsd .
.Sh HISTORY
-These functions first appeared in
+The
+.Fn setprogname
+and
+.Fn getprogname
+functions first appeared in
.Nx 1.6 ,
-and made their way into
-.Fx 4.4 .
+.Fx 4.4 ,
+.Dx 2.1
+and
+.Ox 5.4 .
diff --git a/man/heapsort.3bsd b/man/heapsort.3bsd
index 106de56..58c9092 100644
--- a/man/heapsort.3bsd
+++ b/man/heapsort.3bsd
@@ -33,7 +33,7 @@
.\" $FreeBSD$
.\"
.Dd September 30, 2003
-.Dt HEAPSORT 3bsd
+.Dt heapsort 3bsd
.Os
.Sh NAME
.Nm heapsort , mergesort
diff --git a/man/humanize_number.3bsd b/man/humanize_number.3bsd
index ff1db2b..02ce9af 100644
--- a/man/humanize_number.3bsd
+++ b/man/humanize_number.3bsd
@@ -28,7 +28,7 @@
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd February 9, 2008
-.Dt HUMANIZE_NUMBER 3bsd
+.Dt humanize_number 3bsd
.Os
.Sh NAME
.Nm dehumanize_number ,
@@ -166,7 +166,9 @@ represented a number that does not fit in
.Sh HISTORY
.Fn humanize_number
first appeared in
-.Nx 2.0 .
+.Nx 2.0
+and
+.Fx 5.3 .
.Pp
.Fn dehumanize_number
first appeared in
diff --git a/man/libbsd.7 b/man/libbsd.7
index cad9e7c..b3c848e 100644
--- a/man/libbsd.7
+++ b/man/libbsd.7
@@ -1,6 +1,6 @@
.\" libbsd man page
.\"
-.\" Copyright © 2017-2021 Guillem Jover <guillem@hadrons.org>
+.\" Copyright © 2017-2024 Guillem Jover <guillem@hadrons.org>
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
@@ -24,8 +24,8 @@
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd Feb 13, 2021
-.Dt LIBBSD 7
+.Dd January 8, 2024
+.Dt libbsd 7
.Os
.Sh NAME
.Nm libbsd
@@ -42,7 +42,7 @@ The library can be used in an overlay mode, which is the preferred way, so
that the code is portable and requires no modification to the original BSD
code.
This can be done easily with the
-.Xr pkg-config 1
+.Xr pkgconf 1
library named
.Pa libbsd-overlay .
Or by adding the system-specific include directory with the
@@ -59,12 +59,12 @@ The includes in this case should be the usual system ones, such as
.In unistd.h .
.Pp
The other way to use the library is to use the namespaced headers,
-this is less portable as it makes using
+which is a discouraged way, being less portable as it makes using
.Nm libbsd
mandatory and it will not work on BSD-based systems, and requires
modifying original BSD code.
This can be done with the
-.Xr pkg-config 1
+.Xr pkgconf 1
library named
.Pa libbsd .
The includes in this case should be namespaced with
@@ -76,10 +76,10 @@ The package also provides a
.Nm libbsd-ctor
static library that can be used to inject automatic constructors into a
program so that the
-.Fn setproctitle_init 3
+.Xr setproctitle_init 3bsd
function gets invoked automatically at startup time.
This can be done with the
-.Xr pkg-config 1
+.Xr pkgconf 1
library named
.Pa libbsd-ctor .
.Sh HEADERS
@@ -128,20 +128,21 @@ It only works in non-overlay mode.
.Bl -tag -width 4m -compact
.It In bsd/bsd.h
.El
-.Sh ALTERNATIVES
+.Sh VARIANTS
Some functions have different prototypes depending on the BSD where they
originated from, and these various implementations provided are selectable
at build-time.
.Pp
This is the list of functions that provide multiple implementations:
-.Bl -tag -width 4m
-.It Fn strnvis 3
-.It Fn strnunvis 3
+.Pp
+.Bl -tag -width 4m -compact
+.It Xr strnvis 3bsd
+.It Xr strnunvis 3bsd
.Nx
added
-.Fn strnvis 3
+.Xr strnvis 3bsd
and
-.Fn strnunvis 3
+.Xr strnunvis 3bsd
but unfortunately made it incompatible with the existing one in
.Ox
and Freedesktop's libbsd (the former having existed for over ten years).
@@ -149,18 +150,19 @@ Despite this incompatibility being reported during development (see
http://gnats.netbsd.org/44977) they still shipped it.
Even more unfortunately
.Fx
-and later MacOS picked up this incompatible implementation.
+and later macOS picked up this incompatible implementation.
.Pp
Provide both implementations and default for now to the historical one to
avoid breakage, but we will switch to the
.Nx
one in a later release, which is internally consistent with the other
-.Xr vis 3
+.Xr vis 3bsd
functions and is now more widespread.
Define
.Dv LIBBSD_NETBSD_VIS
to switch to the
-.Nx one now.
+.Nx
+one now.
Define
.Dv LIBBSD_OPENBSD_VIS
to keep using the
@@ -176,30 +178,30 @@ or non-buggy way; or because there are better more portable replacements now.
.Pp
This is the list of currently deprecated macros and functions:
.Bl -tag -width 4m
-.It Fn fgetln 3
+.It Xr fgetln 3bsd
Unportable, requires assistance from the stdio layer.
An implementation has to choose between leaking buffers or being reentrant
for a limited amount of streams (this implementation chose the latter with
a limit of 32).
Use
-.Fn getline 3
+.Xr getline 3
instead, which is available in many systems and required by
.St -p1003.1-2008 .
-.It Fn fgetwln 3
+.It Xr fgetwln 3bsd
Unportable, requires assistance from the stdio layer.
An implementation has to choose between leaking buffers or being reentrant
for a limited amount of streams (this implementation chose the latter with
a limit of 32).
Use
-.Fn fgetwc 3
+.Xr fgetwc 3
instead, which is available in many systems and required by
.St -isoC-99
and
.St -p1003.1-2001 .
-.It Fn funopen 3
+.It Xr funopen 3bsd
Unportable, requires assistance from the stdio layer or some hook framework.
-On GNU systems the
-.Fn fopencookie 3
+On glibc- and musl-based systems the
+.Xr fopencookie 3
function can be used.
Otherwise the code needs to be prepared for neither of these functions being
available.
@@ -213,27 +215,53 @@ are present in all major
for example.
.Pp
.Bl -tag -width 4m -compact
-.It Fn MD5Init 3
-.It Fn MD5Update 3
-.It Fn MD5Pad 3
-.It Fn MD5Final 3
-.It Fn MD5Transform 3
-.It Fn MD5End 3
-.It Fn MD5File 3
-.It Fn MD5FileChunk 3
-.It Fn MD5Data 3
+.It Xr MD5Init 3
+.It Xr MD5Update 3
+.It Xr MD5Pad 3
+.It Xr MD5Final 3
+.It Xr MD5Transform 3
+.It Xr MD5End 3
+.It Xr MD5File 3
+.It Xr MD5FileChunk 3
+.It Xr MD5Data 3
The set of MD5 digest functions are now proxies for the implementations
provided by the
.Nm libmd
companion library, so it is advised to switch to use that directly instead.
-.It Fn explicit_bzero 3
+.It Xr explicit_bzero 3bsd
This function is provided by
.Nm glibc
-2.25.
-.It Fn reallocarray 3
+2.25, and
+.Nm musl
+1.1.20.
+.It Xr reallocarray 3bsd
This function is provided by
.Nm glibc
-2.26.
+2.26, and
+.Nm musl
+1.2.2.
+.It Xr closefrom 3bsd
+This function is provided by
+.Nm glibc
+2.34.
+.It Xr arc4random 3bsd
+.It Xr arc4random_buf 3bsd
+.It Xr arc4random_uniform 3bsd
+These functions are provided by
+.Nm glibc
+2.36.
+Note that it does not provide the
+.Xr arc4random_stir 3bsd
+and
+.Xr arc4random_addrandom 3bsd
+functions.
+.It Xr strlcpy 3bsd
+.It Xr strlcat 3bsd
+These functions are provided by
+.Nm glibc
+2.38, and
+.Nm musl
+0.5.0.
.El
.Sh SEE ALSO
.Xr arc4random 3bsd ,
diff --git a/man/nlist.3bsd b/man/nlist.3bsd
index beb32a3..fb11d50 100644
--- a/man/nlist.3bsd
+++ b/man/nlist.3bsd
@@ -29,7 +29,7 @@
.\" $FreeBSD: /repoman/r/ncvs/src/lib/libc/gen/nlist.3,v 1.7 2001/10/01 16:08:51 ru Exp $
.\"
.Dd April 19, 1994
-.Dt NLIST 3bsd
+.Dt nlist 3bsd
.Os
.Sh NAME
.Nm nlist
diff --git a/man/pidfile.3bsd b/man/pidfile.3bsd
index 489419b..547c556 100644
--- a/man/pidfile.3bsd
+++ b/man/pidfile.3bsd
@@ -25,7 +25,7 @@
.\" $FreeBSD$
.\"
.Dd February 8, 2012
-.Dt PIDFILE 3bsd
+.Dt pidfile 3bsd
.Os
.Sh NAME
.Nm pidfile_open ,
@@ -292,6 +292,20 @@ Probably called not from the process which used
.Xr open 2 ,
.Xr daemon 3 ,
.Xr flopen 3bsd
+.Sh HISTORY
+The functions
+.Fn pidfile_open ,
+.Fn pidfile_write ,
+.Fn pidfile_close
+and
+.Fn pidfile_remove
+first appeared in
+.Fx 5.5 .
+.Pp
+The function
+.Fn pidfile_fileno
+first appeared in
+.Fx 10.0 .
.Sh AUTHORS
.An -nosplit
The
diff --git a/man/pwcache.3bsd b/man/pwcache.3bsd
index dac9bcd..06c54e1 100644
--- a/man/pwcache.3bsd
+++ b/man/pwcache.3bsd
@@ -28,7 +28,7 @@
.\" SUCH DAMAGE.
.\"
.Dd $Mdocdate: September 13 2018 $
-.Dt USER_FROM_UID 3
+.Dt user_from_uid 3
.Os
.Sh NAME
.Nm user_from_uid ,
@@ -137,7 +137,7 @@ The
.Fn uid_from_user
and
.Fn gid_from_group
-functions were ported from
-.Nx
-and first appeared in
+functions first appeared in
+.Nx 1.4
+and
.Ox 6.4 .
diff --git a/man/queue.3bsd b/man/queue.3bsd
index 46a0503..5128a2c 100644
--- a/man/queue.3bsd
+++ b/man/queue.3bsd
@@ -29,7 +29,7 @@
.\" $FreeBSD$
.\"
.Dd September 8, 2016
-.Dt QUEUE 3bsd
+.Dt queue 3bsd
.Os
.Sh NAME
.Nm SLIST_CLASS_ENTRY ,
diff --git a/man/radixsort.3bsd b/man/radixsort.3bsd
index 306a311..ff0c826 100644
--- a/man/radixsort.3bsd
+++ b/man/radixsort.3bsd
@@ -30,7 +30,7 @@
.\" from: @(#)radixsort.3 8.2 (Berkeley) 1/27/94
.\"
.Dd January 27, 1994
-.Dt RADIXSORT 3bsd
+.Dt radixsort 3bsd
.Os
.Sh NAME
.Nm radixsort ,
diff --git a/man/readpassphrase.3bsd b/man/readpassphrase.3bsd
index 9887eb9..3c9275d 100644
--- a/man/readpassphrase.3bsd
+++ b/man/readpassphrase.3bsd
@@ -19,7 +19,7 @@
.\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
.\"
.Dd $Mdocdate: March 6 2014 $
-.Dt READPASSPHRASE 3bsd
+.Dt readpassphrase 3bsd
.Os
.Sh NAME
.Nm readpassphrase
@@ -165,10 +165,12 @@ will reprint the prompt and the user may then enter a passphrase.
The
.Fn readpassphrase
function is an
-.Ox
+.Bx
extension and should not be used if portability is desired.
.Sh HISTORY
The
.Fn readpassphrase
function first appeared in
-.Ox 2.9 .
+.Ox 2.9
+and
+.Fx 4.6 .
diff --git a/man/reallocarray.3bsd b/man/reallocarray.3bsd
index b4e5cbe..a63de81 100644
--- a/man/reallocarray.3bsd
+++ b/man/reallocarray.3bsd
@@ -33,7 +33,7 @@
.\" $OpenBSD: malloc.3,v 1.126 2019/09/14 13:16:50 otto Exp $
.\"
.Dd $Mdocdate: September 14 2019 $
-.Dt REALLOCARRAY 3bsd
+.Dt reallocarray 3bsd
.Os
.Sh NAME
.Nm reallocarray ,
@@ -283,12 +283,18 @@ The
.Fn reallocarray
function appeared in
.Ox 5.6 ,
+.Dx 5.5
and glibc 2.26.
+.Pp
The
.Fn recallocarray
function appeared in
-.Ox 6.1 .
+.Ox 6.1
+and
+.Dx 5.5 .
The
.Fn freezero
function appeared in
-.Ox 6.2 .
+.Ox 6.2
+and
+.Dx 5.5 .
diff --git a/man/reallocf.3bsd b/man/reallocf.3bsd
index 5d8b66d..8509b5e 100644
--- a/man/reallocf.3bsd
+++ b/man/reallocf.3bsd
@@ -33,7 +33,7 @@
.\" $FreeBSD: src/lib/libc/stdlib/malloc.3,v 1.80.2.2.2.1 2010/06/14 02:09:06 kensmith Exp $
.\"
.Dd September 26, 2009
-.Dt REALLOCF 3bsd
+.Dt reallocf 3bsd
.Os
.Sh NAME
.Nm reallocf
diff --git a/man/setmode.3bsd b/man/setmode.3bsd
index 0710f2a..6177a0f 100644
--- a/man/setmode.3bsd
+++ b/man/setmode.3bsd
@@ -31,7 +31,7 @@
.\" $FreeBSD: src/lib/libc/gen/setmode.3,v 1.12 2007/01/09 00:27:55 imp Exp $
.\"
.Dd January 4, 2009
-.Dt SETMODE 3bsd
+.Dt setmode 3bsd
.Os
.Sh NAME
.Nm getmode ,
diff --git a/man/setproctitle.3bsd b/man/setproctitle.3bsd
index ad1f44f..c8aeb4b 100644
--- a/man/setproctitle.3bsd
+++ b/man/setproctitle.3bsd
@@ -20,8 +20,8 @@
.\" $FreeBSD$
.\"
.\" The following requests are required for all man pages.
-.Dd December 16, 1995
-.Dt SETPROCTITLE 3bsd
+.Dd December 7, 2022
+.Dt setproctitle 3bsd
.Os
.Sh NAME
.Nm setproctitle
@@ -31,7 +31,6 @@
.ds doc-str-Lb-libbsd \*[str-Lb-libbsd]
.Lb libbsd
.Sh SYNOPSIS
-.In sys/types.h
.In unistd.h
(See
.Xr libbsd 7
@@ -54,7 +53,7 @@ library routine only needs to be called (before any call to
and with
.Fn main
arguments), if the automatic constructor support has not
-been linked in through the libbsd-ctor pkg-config file.
+been linked in through the libbsd-ctor pkgconf file.
.Pp
The title is set from the executable's name, followed by the
result of a
@@ -113,6 +112,8 @@ The
.Fn setproctitle
function
first appeared in
+.Nx 1.0
+and
.Fx 2.2 .
Other operating systems have
similar functions.
diff --git a/man/stringlist.3bsd b/man/stringlist.3bsd
index d5c0756..ec06b1a 100644
--- a/man/stringlist.3bsd
+++ b/man/stringlist.3bsd
@@ -27,7 +27,7 @@
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd May 6, 2010
-.Dt STRINGLIST 3bsd
+.Dt stringlist 3bsd
.Os
.Sh NAME
.Nm stringlist ,
diff --git a/man/strlcpy.3bsd b/man/strlcpy.3bsd
index fd5d71d..c3eee4f 100644
--- a/man/strlcpy.3bsd
+++ b/man/strlcpy.3bsd
@@ -14,8 +14,8 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: May 31 2007 $
-.Dt STRLCPY 3bsd
+.Dd $Mdocdate: January 7 2024 $
+.Dt strlcpy 3bsd
.Os
.Sh NAME
.Nm strlcpy ,
@@ -192,4 +192,7 @@ and
functions first appeared in
.Ox 2.4 ,
and made their appearance in
-.Fx 3.3 .
+.Nx 1.4.3 ,
+.Fx 3.3
+and
+glibc 2.38.
diff --git a/man/strmode.3bsd b/man/strmode.3bsd
index 224e099..7f613a2 100644
--- a/man/strmode.3bsd
+++ b/man/strmode.3bsd
@@ -29,7 +29,7 @@
.\" $FreeBSD: src/lib/libc/string/strmode.3,v 1.9 2003/07/01 15:28:05 maxim Exp $
.\"
.Dd July 28, 1994
-.Dt STRMODE 3bsd
+.Dt strmode 3bsd
.Os
.Sh NAME
.Nm strmode
diff --git a/man/strnstr.3bsd b/man/strnstr.3bsd
index e7a116d..95e729e 100644
--- a/man/strnstr.3bsd
+++ b/man/strnstr.3bsd
@@ -34,7 +34,7 @@
.\" $FreeBSD$
.\"
.Dd October 11, 2001
-.Dt STRSTR 3bsd
+.Dt strstr 3bsd
.Os
.Sh NAME
.Nm strnstr
@@ -112,3 +112,8 @@ ptr = strnstr(largestring, smallstring, 4);
.Xr strspn 3 ,
.Xr strtok 3 ,
.Xr wcsstr 3
+.Sh HISTORY
+The
+.Fn strnstr
+function originated in
+.Fx .
diff --git a/man/strtoi.3bsd b/man/strtoi.3bsd
index 80aab7b..5988361 100644
--- a/man/strtoi.3bsd
+++ b/man/strtoi.3bsd
@@ -1,4 +1,4 @@
-.\" $NetBSD: strtoi.3,v 1.7 2017/07/03 21:32:50 wiz Exp $
+.\" $NetBSD: strtoi.3,v 1.10 2024/02/10 18:43:51 andvar Exp $
.\"
.\" Copyright (c) 1990, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -36,12 +36,12 @@
.\" Created by Kamil Rytarowski, based on ID:
.\" NetBSD: strtol.3,v 1.31 2015/03/11 09:57:35 wiz Exp
.\"
-.Dd November 13, 2015
-.Dt STRTOI 3bsd
+.Dd January 20, 2024
+.Dt strtoi 3bsd
.Os
.Sh NAME
.Nm strtoi
-.Nd convert string value to an intmax_t integer
+.Nd convert a string value to an intmax_t integer
.Sh LIBRARY
.ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd)
.ds doc-str-Lb-libbsd \*[str-Lb-libbsd]
@@ -63,8 +63,7 @@ for include usage.)
.Sh DESCRIPTION
The
.Fn strtoi
-function
-converts the string in
+function converts the string in
.Fa nptr
to an
.Ft intmax_t
@@ -77,7 +76,7 @@ and ensures that the result is always in the range [
.Fa lo ..
.Fa hi
].
-In adddition it always places
+In addition it always places
.Dv 0
on success or a conversion status in the
.Fa rstatus
@@ -122,10 +121,11 @@ is taken as 10 (decimal) unless the next character is
.Ql 0 ,
in which case it is taken as 8 (octal).
.Pp
-The remainder of the string is converted to a
+The remainder of the string is converted to an
.Em intmax_t
value in the obvious manner,
-stopping at the first character which is not a valid digit
+stopping at the end of the string
+or at the first character which is not a valid digit
in the given base.
(In bases above 10, the letter
.Ql A
@@ -206,6 +206,12 @@ or the range given was invalid, i.e.
>
.Fa hi .
.El
+.Pp
+The range check is more important than the unconverted characters check,
+and it is performed first.
+If a program needs to know if there were unconverted characters when an
+out of range number has been provided, it needs to supply and test
+.Fa endptr.
.Sh SEE ALSO
.Xr atof 3 ,
.Xr atoi 3 ,
@@ -233,7 +239,7 @@ function first appeared in
.Nx 7.0 .
.Ox
introduced the
-.Fn strtonum 3bsd
+.Xr strtonum 3bsd
function for the same purpose, but the interface makes it impossible to
properly differentiate illegal returns.
.Sh BUGS
diff --git a/man/strtonum.3bsd b/man/strtonum.3bsd
index d216d00..a4ed2bb 100644
--- a/man/strtonum.3bsd
+++ b/man/strtonum.3bsd
@@ -16,7 +16,7 @@
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd January 18, 2015
-.Dt STRTONUM 3bsd
+.Dt strtonum 3bsd
.Os
.Sh NAME
.Nm strtonum
@@ -141,8 +141,8 @@ The string did not consist solely of digit characters.
.Xr strtoull 3
.Sh STANDARDS
.Fn strtonum
-is an
-.Ox
+is a
+.Bx
extension.
.Sh HISTORY
.ds doc-operating-system-NetBSD-8.0 8.0
@@ -154,9 +154,9 @@ function first appeared in
was redesigned in
.Nx 8.0
as
-.Fn strtoi 3bsd
+.Xr strtoi 3bsd
and
-.Fn strtou 3bsd .
+.Xr strtou 3bsd .
.Sh CAVEATS
The
.Fn strtonum
@@ -186,6 +186,6 @@ To overcome the shortcomings of
.Fn strtonum
.Nx
provides
-.Fn strtou 3bsd
+.Xr strtou 3bsd
and
-.Fn strtoi 3bsd .
+.Xr strtoi 3bsd .
diff --git a/man/strtou.3bsd b/man/strtou.3bsd
index 09cc458..0291568 100644
--- a/man/strtou.3bsd
+++ b/man/strtou.3bsd
@@ -1,4 +1,4 @@
-.\" $NetBSD: strtou.3,v 1.7 2017/07/03 21:32:50 wiz Exp $
+.\" $NetBSD: strtou.3,v 1.8 2024/01/20 16:13:39 christos Exp $
.\"
.\" Copyright (c) 1990, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -36,12 +36,12 @@
.\" Created by Kamil Rytarowski, based on ID:
.\" NetBSD: strtoul.3,v 1.29 2015/03/10 13:00:58 christos Exp
.\"
-.Dd November 13, 2015
-.Dt STRTOU 3bsd
+.Dd January 20, 2024
+.Dt strtou 3bsd
.Os
.Sh NAME
.Nm strtou
-.Nd convert a string to an uintmax_t integer
+.Nd convert a string value to an uintmax_t integer
.Sh LIBRARY
.ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd)
.ds doc-str-Lb-libbsd \*[str-Lb-libbsd]
@@ -76,7 +76,7 @@ and ensures that the result is always in the range [
.Fa lo ..
.Fa hi
].
-In adddition it always places
+In addition it always places
.Dv 0
on success or a conversion status in the
.Fa rstatus
@@ -125,7 +125,7 @@ The remainder of the string is converted to an
.Em uintmax_t
value in the obvious manner,
stopping at the end of the string
-or at the first character that does not produce a valid digit
+or at the first character which is not a valid digit
in the given base.
(In bases above 10, the letter
.Ql A
@@ -200,12 +200,18 @@ In this case,
.Fa endptr
points to the first unconverted character.
.It Bq Er ERANGE
-The given string was out of range; the value converted has been clamped; or
-the range given was invalid, i.e.
+The given string was out of range; the value converted has been clamped;
+or the range given was invalid, i.e.
.Fa lo
>
.Fa hi .
.El
+.Pp
+The range check is more important than the unconverted characters check,
+and it is performed first.
+If a program needs to know if there were unconverted characters when an
+out of range number has been provided, it needs to supply and test
+.Fa endptr.
.Sh SEE ALSO
.Xr atof 3 ,
.Xr atoi 3 ,
@@ -220,20 +226,20 @@ the range given was invalid, i.e.
.Xr strtoull 3 ,
.Xr strtoumax 3
.Sh STANDARDS
-.ds doc-operating-system-NetBSD-7.0 7.0
The
.Fn strtou
function is a
.Nx
extension.
.Sh HISTORY
+.ds doc-operating-system-NetBSD-7.0 7.0
The
.Fn strtou
function first appeared in
.Nx 7.0 .
.Ox
introduced the
-.Fn strtonum 3bsd
+.Xr strtonum 3bsd
function for the same purpose, but the interface makes it impossible to
properly differentiate illegal returns.
.Sh BUGS
diff --git a/man/timeradd.3bsd b/man/timeradd.3bsd
index e9e78e9..2dd43c5 100644
--- a/man/timeradd.3bsd
+++ b/man/timeradd.3bsd
@@ -31,7 +31,7 @@
.\" $FreeBSD: src/share/man/man3/timeradd.3,v 1.3 2003/09/08 19:57:19 ru Exp $
.\"
.Dd June 7, 2010
-.Dt TIMERADD 3bsd
+.Dt timeradd 3bsd
.Os
.Sh NAME
.Nm timeradd ,
diff --git a/man/timespec.3bsd b/man/timespec.3bsd
deleted file mode 100644
index e47176e..0000000
--- a/man/timespec.3bsd
+++ /dev/null
@@ -1 +0,0 @@
-.so man3/timeval.3bsd
diff --git a/man/timeval.3bsd b/man/timeval.3bsd
deleted file mode 100644
index 31431a3..0000000
--- a/man/timeval.3bsd
+++ /dev/null
@@ -1,134 +0,0 @@
-.\" $NetBSD: timeval.3,v 1.12 2011/04/12 08:39:26 jruoho Exp $
-.\"
-.\" Copyright (c) 2010 The NetBSD Foundation, Inc.
-.\" All rights reserved.
-.\"
-.\" This code is derived from software contributed to The NetBSD Foundation
-.\" by Jukka Ruohonen.
-.\"
-.\" 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 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.
-.\"
-.Dd April 12, 2011
-.Dt TIMEVAL 3bsd
-.Os
-.Sh NAME
-.Nm timeval ,
-.Nm timespec
-.Nd time structures
-.Sh LIBRARY
-.ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd)
-.ds doc-str-Lb-libbsd \*[str-Lb-libbsd]
-.Lb libbsd
-.Sh SYNOPSIS
-.In sys/time.h
-(See
-.Xr libbsd 7
-for include usage.)
-.Ft void
-.Fn TIMEVAL_TO_TIMESPEC "struct timeval *tv" "struct timespec *ts"
-.Ft void
-.Fn TIMESPEC_TO_TIMEVAL "struct timeval *tv" "struct timespec *ts"
-.Sh DESCRIPTION
-The
-.In sys/time.h
-header, included by
-.In time.h ,
-defines various structures related to time and timers.
-.Bl -enum -offset 1n
-.It
-The following structure is used by
-.Xr gettimeofday 2 ,
-among others:
-.Bd -literal -offset indent
-struct timeval {
- time_t tv_sec;
- suseconds_t tv_usec;
-};
-.Ed
-.Pp
-The
-.Va tv_sec
-member represents the elapsed time, in whole seconds.
-The
-.Va tv_usec
-member captures rest of the elapsed time,
-represented as the number of microseconds.
-.It
-The following structure is used by
-.Xr nanosleep 2 ,
-among others:
-.Bd -literal -offset indent
-struct timespec {
- time_t tv_sec;
- long tv_nsec;
-};
-.Ed
-.Pp
-The
-.Va tv_sec
-member is again the elapsed time in whole seconds.
-The
-.Va tv_nsec
-member represents the rest of the elapsed time in nanoseconds.
-.Pp
-A microsecond is equal to one millionth of a second,
-1000 nanoseconds, or 1/1000 milliseconds.
-To ease the conversions, the macros
-.Fn TIMEVAL_TO_TIMESPEC
-and
-.Fn TIMESPEC_TO_TIMEVAL
-can be used to convert between
-.Em struct timeval
-and
-.Em struct timespec .
-.El
-.Sh EXAMPLES
-It can be stressed that the traditional
-.Tn UNIX
-.Va timeval
-and
-.Va timespec
-structures represent elapsed time, measured by the system clock.
-The following sketch implements a function suitable
-for use in a context where the
-.Va timespec
-structure is required for a conditional timeout:
-.Bd -literal -offset indent
-static void
-example(struct timespec *spec, time_t minutes)
-{
- struct timeval elapsed;
-
- (void)gettimeofday(&elapsed, NULL);
-
- _DIAGASSERT(spec != NULL);
- TIMEVAL_TO_TIMESPEC(&elapsed, spec);
-
- /* Add the offset for timeout in minutes. */
- spec->tv_sec = spec->tv_sec + minutes * 60;
-}
-.Ed
-.Pp
-A better alternative would use the more precise
-.Xr clock_gettime 2 .
-.Sh SEE ALSO
-.Xr timeradd 3bsd
diff --git a/man/tree.3bsd b/man/tree.3bsd
index 6800c74..4c9dfb6 100644
--- a/man/tree.3bsd
+++ b/man/tree.3bsd
@@ -1,37 +1,30 @@
-.\" $OpenBSD: tree.3,v 1.7 2002/06/12 01:09:20 provos Exp $
-.\"
-.\" Copyright 2002 Niels Provos <provos@citi.umich.edu>
-.\" 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. All advertising materials mentioning features or use of this software
-.\" must display the following acknowledgement:
-.\" This product includes software developed by Niels Provos.
-.\" 4. The name of the author may not be used to endorse or promote products
-.\" derived from this software without specific prior written permission.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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$
-.\"
-.Dd December 27, 2007
-.Dt TREE 3bsd
+.\" $OpenBSD: tree.3,v 1.30 2019/05/10 13:13:14 florian Exp $
+.\"/*
+.\" * Copyright 2002 Niels Provos <provos@citi.umich.edu>
+.\" * 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 ``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 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.
+.\" */
+.Dd May 10, 2019
+.Dt tree 3bsd
.Os
.Sh NAME
.Nm SPLAY_PROTOTYPE ,
@@ -70,7 +63,9 @@
.Nm RB_RIGHT ,
.Nm RB_PARENT ,
.Nm RB_FOREACH ,
+.Nm RB_FOREACH_SAFE ,
.Nm RB_FOREACH_REVERSE ,
+.Nm RB_FOREACH_REVERSE_SAFE ,
.Nm RB_INIT ,
.Nm RB_INSERT ,
.Nm RB_REMOVE
@@ -84,88 +79,92 @@
(See
.Xr libbsd 7
for include usage.)
-.Fn SPLAY_PROTOTYPE NAME TYPE FIELD CMP
-.Fn SPLAY_GENERATE NAME TYPE FIELD CMP
-.Fn SPLAY_ENTRY TYPE
-.Fn SPLAY_HEAD HEADNAME TYPE
+.Pp
+.Fn SPLAY_PROTOTYPE "NAME" "TYPE" "FIELD" "CMP"
+.Fn SPLAY_GENERATE "NAME" "TYPE" "FIELD" "CMP"
+.Fn SPLAY_ENTRY "TYPE"
+.Fn SPLAY_HEAD "HEADNAME" "TYPE"
.Ft "struct TYPE *"
.Fn SPLAY_INITIALIZER "SPLAY_HEAD *head"
.Fn SPLAY_ROOT "SPLAY_HEAD *head"
-.Ft bool
+.Ft "int"
.Fn SPLAY_EMPTY "SPLAY_HEAD *head"
.Ft "struct TYPE *"
-.Fn SPLAY_NEXT NAME "SPLAY_HEAD *head" "struct TYPE *elm"
+.Fn SPLAY_NEXT "NAME" "SPLAY_HEAD *head" "struct TYPE *elm"
.Ft "struct TYPE *"
-.Fn SPLAY_MIN NAME "SPLAY_HEAD *head"
+.Fn SPLAY_MIN "NAME" "SPLAY_HEAD *head"
.Ft "struct TYPE *"
-.Fn SPLAY_MAX NAME "SPLAY_HEAD *head"
+.Fn SPLAY_MAX "NAME" "SPLAY_HEAD *head"
.Ft "struct TYPE *"
-.Fn SPLAY_FIND NAME "SPLAY_HEAD *head" "struct TYPE *elm"
+.Fn SPLAY_FIND "NAME" "SPLAY_HEAD *head" "struct TYPE *elm"
.Ft "struct TYPE *"
.Fn SPLAY_LEFT "struct TYPE *elm" "SPLAY_ENTRY NAME"
.Ft "struct TYPE *"
.Fn SPLAY_RIGHT "struct TYPE *elm" "SPLAY_ENTRY NAME"
-.Fn SPLAY_FOREACH VARNAME NAME "SPLAY_HEAD *head"
+.Fn SPLAY_FOREACH "VARNAME" "NAME" "SPLAY_HEAD *head"
.Ft void
.Fn SPLAY_INIT "SPLAY_HEAD *head"
.Ft "struct TYPE *"
-.Fn SPLAY_INSERT NAME "SPLAY_HEAD *head" "struct TYPE *elm"
+.Fn SPLAY_INSERT "NAME" "SPLAY_HEAD *head" "struct TYPE *elm"
.Ft "struct TYPE *"
-.Fn SPLAY_REMOVE NAME "SPLAY_HEAD *head" "struct TYPE *elm"
-.Fn RB_PROTOTYPE NAME TYPE FIELD CMP
-.Fn RB_PROTOTYPE_STATIC NAME TYPE FIELD CMP
-.Fn RB_GENERATE NAME TYPE FIELD CMP
-.Fn RB_GENERATE_STATIC NAME TYPE FIELD CMP
-.Fn RB_ENTRY TYPE
-.Fn RB_HEAD HEADNAME TYPE
+.Fn SPLAY_REMOVE "NAME" "SPLAY_HEAD *head" "struct TYPE *elm"
+.Pp
+.Fn RB_PROTOTYPE "NAME" "TYPE" "FIELD" "CMP"
+.Fn RB_PROTOTYPE_STATIC "NAME" "TYPE" "FIELD" "CMP"
+.Fn RB_GENERATE "NAME" "TYPE" "FIELD" "CMP"
+.Fn RB_GENERATE_STATIC "NAME" "TYPE" "FIELD" "CMP"
+.Fn RB_ENTRY "TYPE"
+.Fn RB_HEAD "HEADNAME" "TYPE"
.Fn RB_INITIALIZER "RB_HEAD *head"
.Ft "struct TYPE *"
.Fn RB_ROOT "RB_HEAD *head"
-.Ft "bool"
+.Ft "int"
.Fn RB_EMPTY "RB_HEAD *head"
.Ft "struct TYPE *"
-.Fn RB_NEXT NAME "RB_HEAD *head" "struct TYPE *elm"
+.Fn RB_NEXT "NAME" "RB_HEAD *head" "struct TYPE *elm"
.Ft "struct TYPE *"
-.Fn RB_PREV NAME "RB_HEAD *head" "struct TYPE *elm"
+.Fn RB_PREV "NAME" "RB_HEAD *head" "struct TYPE *elm"
.Ft "struct TYPE *"
-.Fn RB_MIN NAME "RB_HEAD *head"
+.Fn RB_MIN "NAME" "RB_HEAD *head"
.Ft "struct TYPE *"
-.Fn RB_MAX NAME "RB_HEAD *head"
+.Fn RB_MAX "NAME" "RB_HEAD *head"
.Ft "struct TYPE *"
-.Fn RB_FIND NAME "RB_HEAD *head" "struct TYPE *elm"
+.Fn RB_FIND "NAME" "RB_HEAD *head" "struct TYPE *elm"
.Ft "struct TYPE *"
-.Fn RB_NFIND NAME "RB_HEAD *head" "struct TYPE *elm"
+.Fn RB_NFIND "NAME" "RB_HEAD *head" "struct TYPE *elm"
.Ft "struct TYPE *"
.Fn RB_LEFT "struct TYPE *elm" "RB_ENTRY NAME"
.Ft "struct TYPE *"
.Fn RB_RIGHT "struct TYPE *elm" "RB_ENTRY NAME"
.Ft "struct TYPE *"
.Fn RB_PARENT "struct TYPE *elm" "RB_ENTRY NAME"
-.Fn RB_FOREACH VARNAME NAME "RB_HEAD *head"
-.Fn RB_FOREACH_REVERSE VARNAME NAME "RB_HEAD *head"
+.Fn RB_FOREACH "VARNAME" "NAME" "RB_HEAD *head"
+.Fn RB_FOREACH_SAFE "VARNAME" "NAME" "RB_HEAD *head" "TEMP_VARNAME"
+.Fn RB_FOREACH_REVERSE "VARNAME" "NAME" "RB_HEAD *head"
+.Fn RB_FOREACH_REVERSE_SAFE "VARNAME" "NAME" "RB_HEAD *head" "TEMP_VARNAME"
.Ft void
.Fn RB_INIT "RB_HEAD *head"
.Ft "struct TYPE *"
-.Fn RB_INSERT NAME "RB_HEAD *head" "struct TYPE *elm"
+.Fn RB_INSERT "NAME" "RB_HEAD *head" "struct TYPE *elm"
.Ft "struct TYPE *"
-.Fn RB_REMOVE NAME "RB_HEAD *head" "struct TYPE *elm"
+.Fn RB_REMOVE "NAME" "RB_HEAD *head" "struct TYPE *elm"
.Sh DESCRIPTION
These macros define data structures for different types of trees:
splay trees and red-black trees.
.Pp
In the macro definitions,
.Fa TYPE
-is the name tag of a user defined structure that must contain a field of type
-.Vt SPLAY_ENTRY ,
+is the name tag of a user defined structure that must contain a field named
+.Fa FIELD ,
+of type
+.Li SPLAY_ENTRY
or
-.Vt RB_ENTRY ,
-named
-.Fa ENTRYNAME .
+.Li RB_ENTRY .
The argument
.Fa HEADNAME
is the name tag of a user defined structure that must be declared
using the macros
-.Fn SPLAY_HEAD ,
+.Fn SPLAY_HEAD
or
.Fn RB_HEAD .
The argument
@@ -173,46 +172,38 @@ The argument
has to be a unique name prefix for every tree that is defined.
.Pp
The function prototypes are declared with
-.Fn SPLAY_PROTOTYPE ,
-.Fn RB_PROTOTYPE ,
+.Li SPLAY_PROTOTYPE ,
+.Li RB_PROTOTYPE ,
or
-.Fn RB_PROTOTYPE_STATIC .
+.Li RB_PROTOTYPE_STATIC .
The function bodies are generated with
-.Fn SPLAY_GENERATE ,
-.Fn RB_GENERATE ,
+.Li SPLAY_GENERATE ,
+.Li RB_GENERATE ,
or
-.Fn RB_GENERATE_STATIC .
+.Li RB_GENERATE_STATIC .
See the examples below for further explanation of how these macros are used.
.Sh SPLAY TREES
A splay tree is a self-organizing data structure.
Every operation on the tree causes a splay to happen.
-The splay moves the requested
-node to the root of the tree and partly rebalances it.
+The splay moves the requested node to the root of the tree and partly
+rebalances it.
.Pp
This has the benefit that request locality causes faster lookups as
the requested nodes move to the top of the tree.
On the other hand, every lookup causes memory writes.
.Pp
-The Balance Theorem bounds the total access time for
-.Ar m
-operations and
-.Ar n
-inserts on an initially empty tree as
-.Fn O "\*[lp]m + n\*[rp]lg n" .
-The
-amortized cost for a sequence of
-.Ar m
-accesses to a splay tree is
-.Fn O "lg n" .
+The Balance Theorem bounds the total access time for m operations
+and n inserts on an initially empty tree as O((m + n)lg n).
+The amortized cost for a sequence of m accesses to a splay tree is O(lg n).
.Pp
A splay tree is headed by a structure defined by the
.Fn SPLAY_HEAD
macro.
A
+.Fa SPLAY_HEAD
structure is declared as follows:
-.Bd -ragged -offset indent
-.Fn SPLAY_HEAD HEADNAME TYPE
-.Va head ;
+.Bd -literal -offset indent
+SPLAY_HEAD(HEADNAME, TYPE) head;
.Ed
.Pp
where
@@ -251,16 +242,15 @@ macro, but should be used only once.
Finally,
the
.Fa CMP
-argument is the name of a function used to compare tree nodes
+argument is the name of a function used to compare trees' nodes
with each other.
The function takes two arguments of type
-.Vt "struct TYPE *" .
+.Fa "struct TYPE *" .
If the first argument is smaller than the second, the function returns a
value smaller than zero.
If they are equal, the function returns zero.
Otherwise, it should return a value greater than zero.
-The compare
-function defines the order of the tree elements.
+The compare function defines the order of the tree elements.
.Pp
The
.Fn SPLAY_INIT
@@ -270,11 +260,8 @@ macro initializes the tree referenced by
The splay tree can also be initialized statically by using the
.Fn SPLAY_INITIALIZER
macro like this:
-.Bd -ragged -offset indent
-.Fn SPLAY_HEAD HEADNAME TYPE
-.Va head
-=
-.Fn SPLAY_INITIALIZER &head ;
+.Bd -literal -offset indent
+SPLAY_HEAD(HEADNAME, TYPE) head = SPLAY_INITIALIZER(&head);
.Ed
.Pp
The
@@ -282,6 +269,11 @@ The
macro inserts the new element
.Fa elm
into the tree.
+Upon success,
+.Va NULL
+is returned.
+If a matching element already exists in the tree, the insertion is
+aborted, and a pointer to the existing element is returned.
.Pp
The
.Fn SPLAY_REMOVE
@@ -289,6 +281,11 @@ macro removes the element
.Fa elm
from the tree pointed by
.Fa head .
+Upon success, a pointer to the removed element is returned.
+.Va NULL
+is returned if
+.Fa elm
+is not present in the tree.
.Pp
The
.Fn SPLAY_FIND
@@ -296,7 +293,7 @@ macro can be used to find a particular element in the tree.
.Bd -literal -offset indent
struct TYPE find, *res;
find.key = 30;
-res = SPLAY_FIND(NAME, head, &find);
+res = SPLAY_FIND(NAME, &head, &find);
.Ed
.Pp
The
@@ -313,8 +310,8 @@ for (np = SPLAY_MIN(NAME, &head); np != NULL; np = SPLAY_NEXT(NAME, &head, np))
Or, for simplicity, one can use the
.Fn SPLAY_FOREACH
macro:
-.Bd -ragged -offset indent
-.Fn SPLAY_FOREACH np NAME head
+.Bd -literal -offset indent
+SPLAY_FOREACH(np, NAME, &head)
.Ed
.Pp
The
@@ -324,29 +321,28 @@ macro should be used to check whether a splay tree is empty.
A red-black tree is a binary search tree with the node color as an
extra attribute.
It fulfills a set of conditions:
-.Bl -enum -offset indent
+.Pp
+.Bl -enum -compact -offset indent
.It
-Every search path from the root to a leaf consists of the same number of
-black nodes.
+every search path from the root to a leaf consists of the same number of
+black nodes,
.It
-Each red node (except for the root) has a black parent.
+each red node (except for the root) has a black parent,
.It
-Each leaf node is black.
+each leaf node is black.
.El
.Pp
-Every operation on a red-black tree is bounded as
-.Fn O "lg n" .
-The maximum height of a red-black tree is
-.Fn 2lg "n + 1" .
+Every operation on a red-black tree is bounded as O(lg n).
+The maximum height of a red-black tree is 2lg (n+1).
.Pp
A red-black tree is headed by a structure defined by the
.Fn RB_HEAD
macro.
A
+.Fa RB_HEAD
structure is declared as follows:
-.Bd -ragged -offset indent
-.Fn RB_HEAD HEADNAME TYPE
-.Va head ;
+.Bd -literal -offset indent
+RB_HEAD(HEADNAME, TYPE) head;
.Ed
.Pp
where
@@ -364,7 +360,7 @@ their prototypes need to be declared with the
.Fn RB_PROTOTYPE
or
.Fn RB_PROTOTYPE_STATIC
-macro,
+macros,
where
.Fa NAME
is a unique identifier for this particular tree.
@@ -381,7 +377,7 @@ The function bodies are generated with the
.Fn RB_GENERATE
or
.Fn RB_GENERATE_STATIC
-macro.
+macros.
These macros take the same arguments as the
.Fn RB_PROTOTYPE
and
@@ -391,16 +387,15 @@ macros, but should be used only once.
Finally,
the
.Fa CMP
-argument is the name of a function used to compare tree nodes
+argument is the name of a function used to compare trees' nodes
with each other.
The function takes two arguments of type
-.Vt "struct TYPE *" .
+.Fa "struct TYPE *" .
If the first argument is smaller than the second, the function returns a
value smaller than zero.
If they are equal, the function returns zero.
Otherwise, it should return a value greater than zero.
-The compare
-function defines the order of the tree elements.
+The compare function defines the order of the tree elements.
.Pp
The
.Fn RB_INIT
@@ -410,11 +405,8 @@ macro initializes the tree referenced by
The red-black tree can also be initialized statically by using the
.Fn RB_INITIALIZER
macro like this:
-.Bd -ragged -offset indent
-.Fn RB_HEAD HEADNAME TYPE
-.Va head
-=
-.Fn RB_INITIALIZER &head ;
+.Bd -literal -offset indent
+RB_HEAD(HEADNAME, TYPE) head = RB_INITIALIZER(&head);
.Ed
.Pp
The
@@ -422,6 +414,11 @@ The
macro inserts the new element
.Fa elm
into the tree.
+Upon success,
+.Va NULL
+is returned.
+If a matching element already exists in the tree, the insertion is
+aborted, and a pointer to the existing element is returned.
.Pp
The
.Fn RB_REMOVE
@@ -429,16 +426,24 @@ macro removes the element
.Fa elm
from the tree pointed by
.Fa head .
+.Fn RB_REMOVE
+returns
+.Fa elm .
.Pp
The
.Fn RB_FIND
and
.Fn RB_NFIND
macros can be used to find a particular element in the tree.
+.Fn RB_FIND
+finds the node with the same key as
+.Fa elm .
+.Fn RB_NFIND
+finds the first node greater than or equal to the search key.
.Bd -literal -offset indent
struct TYPE find, *res;
find.key = 30;
-res = RB_FIND(NAME, head, &find);
+res = RB_FIND(NAME, &head, &find);
.Ed
.Pp
The
@@ -449,26 +454,122 @@ The
and
.Fn RB_PREV
macros can be used to traverse the tree:
-.Pp
-.Dl "for (np = RB_MIN(NAME, &head); np != NULL; np = RB_NEXT(NAME, &head, np))"
+.Bd -literal -offset indent
+for (np = RB_MIN(NAME, &head); np != NULL; np = RB_NEXT(NAME, &head, np))
+.Ed
.Pp
Or, for simplicity, one can use the
.Fn RB_FOREACH
or
.Fn RB_FOREACH_REVERSE
-macro:
-.Bd -ragged -offset indent
-.Fn RB_FOREACH np NAME head
+macros:
+.Bd -literal -offset indent
+RB_FOREACH(np, NAME, &head)
.Ed
.Pp
+The macros
+.Fn RB_FOREACH_SAFE
+and
+.Fn RB_FOREACH_REVERSE_SAFE
+traverse the tree referenced by head
+in a forward or reverse direction respectively,
+assigning each element in turn to np.
+However, unlike their unsafe counterparts,
+they permit both the removal of np
+as well as freeing it from within the loop safely
+without interfering with the traversal.
+.Pp
The
.Fn RB_EMPTY
macro should be used to check whether a red-black tree is empty.
+.Sh EXAMPLES
+The following example demonstrates how to declare a red-black tree
+holding integers.
+Values are inserted into it and the contents of the tree are printed
+in order.
+Lastly, the internal structure of the tree is printed.
+.Bd -literal -offset 3n
+#include <sys/tree.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+struct node {
+ RB_ENTRY(node) entry;
+ int i;
+};
+
+int intcmp(struct node *, struct node *);
+void print_tree(struct node *);
+
+int
+intcmp(struct node *e1, struct node *e2)
+{
+ return (e1->i < e2->i ? -1 : e1->i > e2->i);
+}
+
+RB_HEAD(inttree, node) head = RB_INITIALIZER(&head);
+RB_PROTOTYPE(inttree, node, entry, intcmp)
+RB_GENERATE(inttree, node, entry, intcmp)
+
+int testdata[] = {
+ 20, 16, 17, 13, 3, 6, 1, 8, 2, 4, 10, 19, 5, 9, 12, 15, 18,
+ 7, 11, 14
+};
+
+void
+print_tree(struct node *n)
+{
+ struct node *left, *right;
+
+ if (n == NULL) {
+ printf("nil");
+ return;
+ }
+ left = RB_LEFT(n, entry);
+ right = RB_RIGHT(n, entry);
+ if (left == NULL && right == NULL)
+ printf("%d", n->i);
+ else {
+ printf("%d(", n->i);
+ print_tree(left);
+ printf(",");
+ print_tree(right);
+ printf(")");
+ }
+}
+
+int
+main(void)
+{
+ int i;
+ struct node *n;
+
+ for (i = 0; i < sizeof(testdata) / sizeof(testdata[0]); i++) {
+ if ((n = malloc(sizeof(struct node))) == NULL)
+ err(1, NULL);
+ n->i = testdata[i];
+ RB_INSERT(inttree, &head, n);
+ }
+
+ RB_FOREACH(n, inttree, &head) {
+ printf("%d\en", n->i);
+ }
+ print_tree(RB_ROOT(&head));
+ printf("\en");
+ return (0);
+}
+.Ed
+.Sh SEE ALSO
+.Xr queue 3bsd
+.Sh HISTORY
+The tree macros first appeared in
+.Fx 4.6 .
.Sh NOTES
Trying to free a tree in the following way is a common error:
.Bd -literal -offset indent
-SPLAY_FOREACH(var, NAME, head) {
- SPLAY_REMOVE(NAME, head, var);
+SPLAY_FOREACH(var, NAME, &head) {
+ SPLAY_REMOVE(NAME, &head, var);
free(var);
}
free(head);
@@ -476,36 +577,17 @@ free(head);
.Pp
Since
.Va var
-is freed, the
+is free'd, the
.Fn FOREACH
macro refers to a pointer that may have been reallocated already.
Proper code needs a second variable.
.Bd -literal -offset indent
-for (var = SPLAY_MIN(NAME, head); var != NULL; var = nxt) {
- nxt = SPLAY_NEXT(NAME, head, var);
- SPLAY_REMOVE(NAME, head, var);
+for (var = SPLAY_MIN(NAME, &head); var != NULL; var = nxt) {
+ nxt = SPLAY_NEXT(NAME, &head, var);
+ SPLAY_REMOVE(NAME, &head, var);
free(var);
}
.Ed
-.Pp
-Both
-.Fn RB_INSERT
-and
-.Fn SPLAY_INSERT
-return
-.Dv NULL
-if the element was inserted in the tree successfully, otherwise they
-return a pointer to the element with the colliding key.
-.Pp
-Accordingly,
-.Fn RB_REMOVE
-and
-.Fn SPLAY_REMOVE
-return the pointer to the removed element otherwise they return
-.Dv NULL
-to indicate an error.
-.Sh SEE ALSO
-.Xr queue 3bsd
.Sh AUTHORS
The author of the tree macros is
.An Niels Provos .
diff --git a/man/unvis.3bsd b/man/unvis.3bsd
index 22ed7c9..fd3f729 100644
--- a/man/unvis.3bsd
+++ b/man/unvis.3bsd
@@ -30,7 +30,7 @@
.\" @(#)unvis.3 8.2 (Berkeley) 12/11/93
.\"
.Dd March 12, 2011
-.Dt UNVIS 3bsd
+.Dt unvis 3bsd
.Os
.Sh NAME
.Nm unvis ,
diff --git a/man/verrc.3bsd b/man/verrc.3bsd
new file mode 100644
index 0000000..3777fac
--- /dev/null
+++ b/man/verrc.3bsd
@@ -0,0 +1 @@
+.so man3/errc.3bsd
diff --git a/man/vis.3bsd b/man/vis.3bsd
index 7895af4..56d520a 100644
--- a/man/vis.3bsd
+++ b/man/vis.3bsd
@@ -30,7 +30,7 @@
.\" @(#)vis.3 8.1 (Berkeley) 6/9/93
.\"
.Dd April 22, 2017
-.Dt VIS 3bsd
+.Dt vis 3bsd
.Os
.Sh NAME
.Nm vis ,
diff --git a/man/vwarnc.3bsd b/man/vwarnc.3bsd
new file mode 100644
index 0000000..3777fac
--- /dev/null
+++ b/man/vwarnc.3bsd
@@ -0,0 +1 @@
+.so man3/errc.3bsd
diff --git a/man/warnc.3bsd b/man/warnc.3bsd
new file mode 100644
index 0000000..3777fac
--- /dev/null
+++ b/man/warnc.3bsd
@@ -0,0 +1 @@
+.so man3/errc.3bsd
diff --git a/man/wcslcpy.3bsd b/man/wcslcpy.3bsd
index c112ff3..61e1e97 100644
--- a/man/wcslcpy.3bsd
+++ b/man/wcslcpy.3bsd
@@ -36,7 +36,7 @@
.\" $FreeBSD$
.\"
.Dd March 4, 2009
-.Dt WCSLCPY 3bsd
+.Dt wcslcpy 3bsd
.Os
.Sh NAME
.Nm wcslcat ,
@@ -69,3 +69,14 @@ counterpart, such as
and
.Fn wcslcpy ,
which are BSD extensions.
+.Sh HISTORY
+The
+.Fn wcslcpy
+and
+.Fn wcslcat
+functions first appeared in
+.Ox 3.8 ,
+.Nx 1.6 ,
+.Fx 5.0
+and
+.Dx 2.1 .
diff --git a/src/Makefile.am b/src/Makefile.am
index 1c12ea4..00181bd 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -5,13 +5,14 @@ AM_CPPFLAGS = \
-isystem $(top_srcdir)/include/bsd/ \
-include $(top_builddir)/config.h \
-DLIBBSD_OVERLAY -DLIBBSD_DISABLE_DEPRECATED \
- -D__REENTRANT
+ -D__REENTRANT \
+ # EOL
if OS_WINDOWS
AM_CPPFLAGS += \
-D_CRT_SECURE_NO_WARNINGS \
-D_CRT_NONSTDC_NO_WARNINGS \
- $(nil)
+ # EOL
endif
libbsd_la_included_sources = \
@@ -23,21 +24,22 @@ libbsd_la_included_sources = \
getentropy_osx.c \
getentropy_solaris.c \
getentropy_win.c \
- $(nil)
+ # EOL
+CLEANFILES =
EXTRA_DIST = \
- libbsd.map \
+ libbsd.map.in \
libbsd.pc.in \
libbsd-ctor.pc.in \
libbsd-overlay.pc.in \
$(libbsd_la_included_sources) \
- $(nil)
+ # EOL
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = \
libbsd.pc \
libbsd-overlay.pc \
- $(nil)
+ # EOL
lib_LTLIBRARIES = libbsd.la
lib_LIBRARIES =
@@ -48,87 +50,351 @@ pkgconfig_DATA += libbsd-ctor.pc
lib_LIBRARIES += libbsd-ctor.a
endif
-libbsd_la_DEPENDENCIES = \
+EXTRA_libbsd_la_DEPENDENCIES = \
$(libbsd_la_included_sources) \
- libbsd.map
+ libbsd.map \
+ libbsd.map.in \
+ # EOL
libbsd_la_LIBADD = \
+ $(MD5_LIBS) \
$(LIBBSD_LIBS) \
- $(nil)
+ # EOL
libbsd_la_LDFLAGS = \
- -version-number $(LIBBSD_ABI)
+ -no-undefined \
+ -version-number $(SOVERSION) \
+ # EOL
if HAVE_LINKER_VERSION_SCRIPT
libbsd_la_LDFLAGS += \
- -Wl,--version-script=$(srcdir)/libbsd.map
+ -Wl,--version-script=libbsd.map \
+ # EOL
+else
+libbsd_la_LDFLAGS += \
+ -export-symbols libbsd.sym \
+ # EOL
+EXTRA_libbsd_la_DEPENDENCIES += \
+ libbsd.sym \
+ # EOL
endif
-libbsd_la_LDFLAGS += --shared -no-undefined -Wl,-no-undefined
libbsd_la_SOURCES = \
+ local-elf.h \
+ local-link.h \
+ # EOL
+
+if ABI_ACCMODE
+libbsd_la_SOURCES += \
+ setmode.c \
+ # EOL
+endif
+
+if ABI_ARC4RANDOM
+if !HAVE_GETENTROPY
+libbsd_la_SOURCES += \
+ getentropy.c \
+ # EOL
+endif
+libbsd_la_SOURCES += \
arc4random.c \
arc4random.h \
arc4random_linux.h \
- arc4random_openbsd.h \
arc4random_uniform.c \
arc4random_unix.h \
arc4random_win.h \
- bsd_getopt.c \
chacha_private.h \
+ # EOL
+endif
+
+if ABI_ASPRINTF
+libbsd_la_SOURCES += \
+ asprintf.c \
+ vasprintf.c \
+ # EOL
+endif
+
+if ABI_BSD_GETOPT
+libbsd_la_SOURCES += \
+ bsd_getopt.c \
+ # EOL
+endif
+
+if ABI_CLOSEFROM
+libbsd_la_SOURCES += \
closefrom.c \
- dehumanize_number.c \
+ # EOL
+endif
+
+if ABI_ERR
+libbsd_la_SOURCES += \
err.c \
+ # EOL
+endif
+
+if ABI_ERRC
+libbsd_la_SOURCES += \
+ errc.c \
+ # EOL
+endif
+
+if ABI_EXPAND_NUMBER
+libbsd_la_SOURCES += \
expand_number.c \
+ # EOL
+endif
+
+if ABI_EXPLICIT_BZERO
+libbsd_la_SOURCES += \
explicit_bzero.c \
- freezero.c \
+ # EOL
+endif
+
+if ABI_FGETLN
+libbsd_la_SOURCES += \
+ fgetln.c \
fgetwln.c \
- fmtcheck.c \
fparseln.c \
+ # EOL
+endif
+
+if ABI_FLOPEN
+libbsd_la_SOURCES += \
+ flopen.c \
+ # EOL
+endif
+
+if ABI_FMTCHECK
+libbsd_la_SOURCES += \
+ fmtcheck.c \
+ # EOL
+endif
+
+if ABI_FPURGE
+libbsd_la_SOURCES += \
+ fpurge.c \
+ # EOL
+endif
+
+if ABI_FREEZERO
+libbsd_la_SOURCES += \
+ freezero.c \
+ # EOL
+endif
+
+if ABI_FUNOPEN
+libbsd_la_SOURCES += \
+ funopen.c \
+ # EOL
+endif
+
+if ABI_GETBSIZE
+libbsd_la_SOURCES += \
getbsize.c \
- heapsort.c \
+ # EOL
+endif
+
+if ABI_GETPEEREID
+libbsd_la_SOURCES += \
+ getpeereid.c \
+ # EOL
+endif
+
+if ABI_HUMANIZE_NUMBER
+libbsd_la_SOURCES += \
+ dehumanize_number.c \
humanize_number.c \
+ # EOL
+endif
+
+if ABI_INET_NET_PTON
+libbsd_la_SOURCES += \
inet_net_pton.c \
- local-elf.h \
- local-link.h \
- merge.c \
+ # EOL
+endif
+
+if ABI_MD5
+libbsd_la_SOURCES += \
+ md5.c \
+ # EOL
+endif
+
+if ABI_NLIST
+libbsd_la_SOURCES += \
+ nlist.c \
+ # EOL
+endif
+
+if ABI_PIDFILE
+libbsd_la_SOURCES += \
+ pidfile.c \
+ # EOL
+endif
+
+if ABI_PROCTITLE
+libbsd_la_SOURCES += \
+ setproctitle.c \
+ # EOL
+endif
+
+if ABI_PROGNAME
+libbsd_la_SOURCES += \
progname.c \
- radixsort.c \
+ # EOL
+endif
+
+if ABI_PWCACHE
+libbsd_la_SOURCES += \
+ pwcache.c \
+ # EOL
+endif
+
+if ABI_READPASSPHRASE
+libbsd_la_SOURCES += \
+ readpassphrase.c \
+ # EOL
+endif
+
+if ABI_REALLOCARRAY
+libbsd_la_SOURCES += \
reallocarray.c \
+ # EOL
+endif
+
+if ABI_REALLOCF
+libbsd_la_SOURCES += \
reallocf.c \
+ # EOL
+endif
+
+if ABI_RECALLOCARRAY
+libbsd_la_SOURCES += \
recallocarray.c \
- setproctitle.c \
+ # EOL
+endif
+
+if ABI_SORT
+libbsd_la_SOURCES += \
+ heapsort.c \
+ merge.c \
+ radixsort.c \
+ # EOL
+endif
+
+if ABI_STRINGLIST
+libbsd_la_SOURCES += \
+ stringlist.c \
+ # EOL
+endif
+
+if ABI_STRL
+libbsd_la_SOURCES += \
strlcat.c \
strlcpy.c \
- stringlist.c \
+ # EOL
+endif
+
+if ABI_STRMODE
+libbsd_la_SOURCES += \
+ strmode.c \
+ # EOL
+endif
+
+if ABI_STRNSTR
+libbsd_la_SOURCES += \
strnstr.c \
- strtoi.c \
+ # EOL
+endif
+
+if ABI_STRTONUM
+libbsd_la_SOURCES += \
strtonum.c \
+ # EOL
+endif
+
+if ABI_STRTOX
+libbsd_la_SOURCES += \
+ strtoi.c \
strtou.c \
+ # EOL
+endif
+
+if ABI_TIMECONV
+libbsd_la_SOURCES += \
timeconv.c \
+ # EOL
+endif
+
+if ABI_VIS
+libbsd_la_SOURCES += \
unvis.c \
vis.c \
+ # EOL
+endif
+
+if ABI_WCSL
+libbsd_la_SOURCES += \
wcslcat.c \
wcslcpy.c \
- $(nil)
+ # EOL
+endif
-#if !HAVE_GETENTROPY
-#libbsd_la_SOURCES += \
-# getentropy.c \
-# $(nil)
-#endif
+if ABI_TRANSPARENT_LIBMD
+CLEANFILES += \
+ format.ld \
+ # EOL
+endif
+
+DISTCLEANFILES = \
+ libbsd.sym \
+ libbsd.map \
+ # EOL
libbsd_ctor_a_SOURCES = \
setproctitle_ctor.c \
- $(nil)
+ # EOL
+
+# Generate the library map file with the pre-processor to selectively include
+# symbols depending on the host system, otherwise some linkers might fail.
+libbsd.map: libbsd.map.in
+ $(AM_V_GEN) $(CPP) $(AM_CPPFLAGS) $(CPPFLAGS) -P - <$(srcdir)/libbsd.map.in >$@
+
+# Generate a simple libtool symbol export list to be used as a fallback if
+# there is no version script support.
+libbsd.sym: libbsd.map
+ $(AM_V_GEN) $(SED) -ne 's/^[[:space:]]\{1,\}\([A-Za-z0-9_]\{1,\}\);/\1/p' libbsd.map >$@
+
+if ABI_TRANSPARENT_LIBMD
+TRANSPARENT_LIBMD_DEPENDS = format.ld
+
+format.ld:
+ $(CC) -shared -nostdlib -nostartfiles -x assembler /dev/null -o $@.so
+ $(OBJDUMP) -f $@.so | sed -n 's/.*file format \(.*\)/OUTPUT_FORMAT(\1)/;T;p' >$@
+ rm -f $@.so
+endif
runtimelibdir = $(libdir)
-install-exec-hook:
+install-exec-hook: $(TRANSPARENT_LIBMD_DEPENDS)
if [ "$(libdir)" != "$(runtimelibdir)" ]; then \
$(MKDIR_P) $(DESTDIR)$(runtimelibdir); \
mv $(DESTDIR)$(libdir)/libbsd*.so.* \
$(DESTDIR)$(runtimelibdir)/; \
+ fi
+if ABI_TRANSPARENT_LIBMD
+# The "GNU ld script" magic is required so that GNU ldconfig does not complain
+# about an unknown format file.
+ soname=`readlink $(DESTDIR)$(libdir)/libbsd.so`; \
+ $(RM) $(DESTDIR)$(libdir)/libbsd.so; \
+ (echo '/* GNU ld script'; \
+ echo ' * The MD5 functions are provided by the libmd library. */'; \
+ cat format.ld; \
+ echo "GROUP($(runtimelibdir)/$$soname AS_NEEDED($(MD5_LIBS)))"; \
+ )>$(DESTDIR)$(libdir)/libbsd.so
+else
+ if [ "$(libdir)" != "$(runtimelibdir)" ]; then \
soname=`readlink $(DESTDIR)$(libdir)/libbsd.so`; \
- sorelprefix=`echo $(libdir) | sed -r -e 's:(^/)?[^/]+:..:g'`; \
+ sorelprefix=`echo $(libdir) | $(SED) -r -e 's:(^/)?[^/]+:..:g'`; \
ln -sf $$sorelprefix$(runtimelibdir)/$$soname \
$(DESTDIR)$(libdir)/libbsd.so; \
fi
+endif
uninstall-hook:
rm -f $(DESTDIR)$(runtimelibdir)/libbsd*.so*
diff --git a/src/arc4random.c b/src/arc4random.c
index 1a7b72f..b046a82 100644
--- a/src/arc4random.c
+++ b/src/arc4random.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: arc4random.c,v 1.53 2015/09/10 18:53:50 bcook Exp $ */
+/* $OpenBSD: arc4random.c,v 1.58 2022/07/31 13:41:45 tb Exp $ */
/*
* Copyright (c) 1996, David Mazieres <dm@uun.org>
@@ -50,6 +50,8 @@
#define BLOCKSZ 64
#define RSBUFSZ (16*BLOCKSZ)
+#define REKEY_BASE (1024*1024) /* NB. should be a power of 2 */
+
/* Marked MAP_INHERIT_ZERO, so zero'd out in fork children. */
static struct _rs {
size_t rs_have; /* valid bytes at end of rs_buf */
@@ -74,10 +76,10 @@ _rs_init(unsigned char *buf, size_t n)
if (rs == NULL) {
if (_rs_allocate(&rs, &rsx) == -1)
- abort();
+ _exit(1);
}
- chacha_keysetup(&rsx->rs_chacha, buf, KEYSZ * 8, 0);
+ chacha_keysetup(&rsx->rs_chacha, buf, KEYSZ * 8);
chacha_ivsetup(&rsx->rs_chacha, buf + KEYSZ);
}
@@ -108,6 +110,7 @@ static void
_rs_stir(void)
{
unsigned char rnd[KEYSZ + IVSZ];
+ uint32_t rekey_fuzz = 0;
if (getentropy(rnd, sizeof rnd) == -1)
_getentropy_fail();
@@ -122,7 +125,10 @@ _rs_stir(void)
rs->rs_have = 0;
memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf));
- rs->rs_count = 1600000;
+ /* rekey interval should not be predictable */
+ chacha_encrypt_bytes(&rsx->rs_chacha, (uint8_t *)&rekey_fuzz,
+ (uint8_t *)&rekey_fuzz, sizeof(rekey_fuzz));
+ rs->rs_count = REKEY_BASE + (rekey_fuzz % REKEY_BASE);
}
static inline void
diff --git a/src/arc4random.h b/src/arc4random.h
index 812188b..b8675b4 100644
--- a/src/arc4random.h
+++ b/src/arc4random.h
@@ -32,9 +32,7 @@
int
getentropy(void *buf, size_t len);
-#if defined(__OpenBSD__)
-#include "arc4random_openbsd.h"
-#elif defined(__linux__)
+#if defined(__linux__)
#include "arc4random_linux.h"
#elif defined(_WIN32)
#include "arc4random_win.h"
diff --git a/src/arc4random_openbsd.h b/src/arc4random_openbsd.h
deleted file mode 100644
index 9cd8b68..0000000
--- a/src/arc4random_openbsd.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* $OpenBSD: arc4random.h,v 1.3 2014/07/20 20:51:13 bcook Exp $ */
-
-/*
- * Copyright (c) 1996, David Mazieres <dm@uun.org>
- * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
- * Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
- * Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-/*
- * Stub functions for portability.
- */
-#include <sys/mman.h>
-
-#include <signal.h>
-
-#include "thread_private.h"
-
-static inline void
-_getentropy_fail(void)
-{
- raise(SIGKILL);
-}
-
-static inline int
-_rs_allocate(struct _rs **rsp, struct _rsx **rsxp)
-{
- struct {
- struct _rs rs;
- struct _rsx rsx;
- } *p;
-
- if ((p = mmap(NULL, sizeof(*p), PROT_READ|PROT_WRITE,
- MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
- return (-1);
- if (minherit(p, sizeof(*p), MAP_INHERIT_ZERO) == -1) {
- munmap(p, sizeof(*p));
- return (-1);
- }
-
- *rsp = &p->rs;
- *rsxp = &p->rsx;
- return (0);
-}
-
-static inline void
-_rs_forkdetect(void)
-{
-}
diff --git a/src/asprintf.c b/src/asprintf.c
new file mode 100644
index 0000000..23576e3
--- /dev/null
+++ b/src/asprintf.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright © 2010-2024 Guillem Jover <guillem@hadrons.org>
+ *
+ * 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 author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``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 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 <config.h>
+
+#include <stdarg.h>
+#include <stdio.h>
+
+int
+asprintf(char **strp, char const *fmt, ...)
+{
+ va_list args;
+ int n;
+
+ va_start(args, fmt);
+ n = vasprintf(strp, fmt, args);
+ va_end(args);
+
+ return n;
+}
diff --git a/src/chacha_private.h b/src/chacha_private.h
index 3b4ec93..ef1b931 100644
--- a/src/chacha_private.h
+++ b/src/chacha_private.h
@@ -4,7 +4,7 @@ D. J. Bernstein
Public domain.
*/
-/* $OpenBSD: chacha_private.h,v 1.2 2013/10/04 07:02:27 djm Exp $ */
+/* $OpenBSD: chacha_private.h,v 1.3 2022/02/28 21:56:29 dtucker Exp $ */
typedef unsigned char u8;
typedef unsigned int u32;
@@ -52,7 +52,7 @@ static const char sigma[16] = "expand 32-byte k";
static const char tau[16] = "expand 16-byte k";
static void
-chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits,u32 ivbits)
+chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits)
{
const char *constants;
diff --git a/src/closefrom.c b/src/closefrom.c
index 2df5d03..41c9668 100644
--- a/src/closefrom.c
+++ b/src/closefrom.c
@@ -153,6 +153,9 @@ closefrom_procfs(int lowfd)
const char *errstr;
int fd;
+ if (dent->d_name[0] == '.')
+ continue;
+
fd = strtonum(dent->d_name, lowfd, INT_MAX, &errstr);
if (errstr != NULL || fd == dirfd(dirp))
continue;
diff --git a/src/err.c b/src/err.c
index 8f09972..44359e8 100644
--- a/src/err.c
+++ b/src/err.c
@@ -1,6 +1,5 @@
/*
- * Copyright © 2006 Robert Millan
- * Copyright © 2011, 2019 Guillem Jover <guillem@hadrons.org>
+ * Copyright © 2019 Guillem Jover <guillem@hadrons.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -26,59 +25,13 @@
*/
#include <err.h>
-#ifdef LIBBSD_NEED_ERR_H_FUNCS
#include <errno.h>
-#endif
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
void
-vwarnc(int code, const char *format, va_list ap)
-{
- fprintf(stderr, "%s: ", getprogname());
- if (format) {
- vfprintf(stderr, format, ap);
- fprintf(stderr, ": ");
- }
- fprintf(stderr, "%s\n", strerror(code));
-}
-
-void
-warnc(int code, const char *format, ...)
-{
- va_list ap;
-
- va_start(ap, format);
- vwarnc(code, format, ap);
- va_end(ap);
-}
-
-void
-verrc(int status, int code, const char *format, va_list ap)
-{
- fprintf(stderr, "%s: ", getprogname());
- if (format) {
- vfprintf(stderr, format, ap);
- fprintf(stderr, ": ");
- }
- fprintf(stderr, "%s\n", strerror(code));
- exit(status);
-}
-
-void
-errc(int status, int code, const char *format, ...)
-{
- va_list ap;
-
- va_start(ap, format);
- verrc(status, code, format, ap);
- va_end(ap);
-}
-
-#ifdef LIBBSD_NEED_ERR_H_FUNCS
-void
vwarn(const char *format, va_list ap)
{
vwarnc(errno, format, ap);
@@ -148,4 +101,3 @@ errx(int eval, const char *format, ...)
verrx(eval, format, ap);
va_end(ap);
}
-#endif
diff --git a/src/errc.c b/src/errc.c
new file mode 100644
index 0000000..45f1b61
--- /dev/null
+++ b/src/errc.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright © 2006 Robert Millan
+ * Copyright © 2011, 2019 Guillem Jover <guillem@hadrons.org>
+ *
+ * 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 author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``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 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 <err.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+void
+vwarnc(int code, const char *format, va_list ap)
+{
+ fprintf(stderr, "%s: ", getprogname());
+ if (format) {
+ vfprintf(stderr, format, ap);
+ fprintf(stderr, ": ");
+ }
+ fprintf(stderr, "%s\n", strerror(code));
+}
+
+void
+warnc(int code, const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ vwarnc(code, format, ap);
+ va_end(ap);
+}
+
+void
+verrc(int status, int code, const char *format, va_list ap)
+{
+ fprintf(stderr, "%s: ", getprogname());
+ if (format) {
+ vfprintf(stderr, format, ap);
+ fprintf(stderr, ": ");
+ }
+ fprintf(stderr, "%s\n", strerror(code));
+ exit(status);
+}
+
+void
+errc(int status, int code, const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ verrc(status, code, format, ap);
+ va_end(ap);
+}
diff --git a/src/explicit_bzero.c b/src/explicit_bzero.c
index 52a7517..d223631 100644
--- a/src/explicit_bzero.c
+++ b/src/explicit_bzero.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: explicit_bzero.c,v 1.3 2014/06/21 02:34:26 matthew Exp $ */
+/* $OpenBSD: explicit_bzero.c,v 1.4 2015/08/31 02:53:57 guenther Exp $ */
/*
* Public domain.
* Written by Matthew Dempsky.
@@ -7,6 +7,9 @@
#include <string.h>
__attribute__((__weak__)) void
+__explicit_bzero_hook(void *, size_t);
+
+__attribute__((__weak__)) void
__explicit_bzero_hook(void *buf, size_t len)
{
}
diff --git a/src/fgetln.c b/src/fgetln.c
index 502eb6f..3b62666 100644
--- a/src/fgetln.c
+++ b/src/fgetln.c
@@ -25,10 +25,11 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <stdio.h>
#include <sys/cdefs.h>
#include <sys/types.h>
+
#include <string.h>
+#include <stdio.h>
#include "local-link.h"
@@ -76,7 +77,7 @@ fgetln(FILE *stream, size_t *len)
}
}
libbsd_link_warning(fgetln,
- "This function cannot be safely ported, use getline(3) "
+ "The fgetln() function cannot be safely ported, use getline(3) "
"instead, as it is supported by GNU and POSIX.1-2008.");
#else
#error "Function fgetln() needs to be ported."
diff --git a/src/fgetwln.c b/src/fgetwln.c
index e6a0a17..0b8e7d9 100644
--- a/src/fgetwln.c
+++ b/src/fgetwln.c
@@ -87,6 +87,9 @@ fgetwln(FILE *stream, size_t *lenp)
*lenp = wused;
return wused ? fb->wbuf : NULL;
}
+/* XXX: Ideally we'd recommend getwline(3), but unfortunately even though it
+ * was part of the ISO/IEC TR 24731-2:2010 draft, it did not make it into C11
+ * and is not widely implemented. */
libbsd_link_warning(fgetwln,
- "This function cannot be safely ported, use fgetwc(3) "
+ "The fgetwln() function cannot be safely ported, use fgetwc(3) "
"instead, as it is supported by C99 and POSIX.1-2001.");
diff --git a/src/flopen.c b/src/flopen.c
index ff20d07..679445f 100644
--- a/src/flopen.c
+++ b/src/flopen.c
@@ -38,6 +38,27 @@
#include <libutil.h>
+static int
+lock_file(int fd, int flags)
+{
+ int operation;
+
+#if HAVE_FLOCK
+ operation = LOCK_EX;
+ if (flags & O_NONBLOCK)
+ operation |= LOCK_NB;
+
+ return flock(fd, operation);
+#else
+ if (flags & O_NONBLOCK)
+ operation = F_TLOCK;
+ else
+ operation = F_LOCK;
+
+ return lockf(fd, operation, 0);
+#endif
+}
+
/*
* Reliably open and lock a file.
*
@@ -49,7 +70,7 @@
static int
vflopenat(int dirfd, const char *path, int flags, va_list ap)
{
- int fd, operation, serrno, trunc;
+ int fd, serrno, trunc;
struct stat sb, fsb;
mode_t mode;
@@ -62,10 +83,6 @@ vflopenat(int dirfd, const char *path, int flags, va_list ap)
mode = (mode_t)va_arg(ap, int); /* mode_t promoted to int */
}
- operation = LOCK_EX;
- if (flags & O_NONBLOCK)
- operation |= LOCK_NB;
-
trunc = (flags & O_TRUNC);
flags &= ~O_TRUNC;
@@ -73,7 +90,7 @@ vflopenat(int dirfd, const char *path, int flags, va_list ap)
if ((fd = openat(dirfd, path, flags, mode)) == -1)
/* non-existent or no access */
return (-1);
- if (flock(fd, operation) == -1) {
+ if (lock_file(fd, flags) == -1) {
/* unsupported or interrupted */
serrno = errno;
(void)close(fd);
diff --git a/src/fpurge.c b/src/fpurge.c
index 462535a..4a20c51 100644
--- a/src/fpurge.c
+++ b/src/fpurge.c
@@ -26,13 +26,15 @@
#include <errno.h>
#include <stdio.h>
+#if HAVE_STDIO_EXT_H
#include <stdio_ext.h>
+#endif
#ifdef HAVE___FPURGE
int
fpurge(FILE *fp)
{
- if (fp == NULL || fileno(fp) < 0) {
+ if (fp == NULL) {
errno = EBADF;
return EOF;
}
diff --git a/src/funopen.c b/src/funopen.c
index 1e6f43a..fdcdcba 100644
--- a/src/funopen.c
+++ b/src/funopen.c
@@ -65,7 +65,7 @@ funopen_write(void *cookie, const char *buf, size_t size)
}
static int
-funopen_seek(void *cookie, off64_t *offset, int whence)
+funopen_seek(void *cookie, off_t *offset, int whence)
{
struct funopen_cookie *cookiewrap = cookie;
off_t soff = *offset;
@@ -137,12 +137,6 @@ funopen(const void *cookie,
return fopencookie(cookiewrap, mode, funcswrap);
}
-#elif defined(__MUSL__)
-/*
- * This is unimplementable on musl based systems, and upstream has stated
- * they will not add the needed support to implement it. Just ignore this
- * interface there, as it has never been provided anyway.
- */
#else
-#error "Function funopen() needs to be ported or disabled."
+#error "Function funopen() needs to be ported."
#endif
diff --git a/src/getentropy_bsd.c b/src/getentropy_bsd.c
index 705f65b..551b646 100644
--- a/src/getentropy_bsd.c
+++ b/src/getentropy_bsd.c
@@ -26,6 +26,8 @@
#include <errno.h>
#include <stddef.h>
+int getentropy(void *buf, size_t len);
+
/*
* Derived from lib/libc/gen/arc4random.c from FreeBSD.
*/
diff --git a/src/getentropy_hurd.c b/src/getentropy_hurd.c
index 2f76baa..8f2ba16 100644
--- a/src/getentropy_hurd.c
+++ b/src/getentropy_hurd.c
@@ -415,17 +415,17 @@ getentropy_fallback(void *buf, size_t len)
#ifdef HAVE_GETAUXVAL
#ifdef AT_RANDOM
/* Not as random as you think but we take what we are given */
- p = (char *) getauxval(AT_RANDOM);
+ p = (char *) ((intptr_t) getauxval(AT_RANDOM));
if (p)
HR(p, 16);
#endif
#ifdef AT_SYSINFO_EHDR
- p = (char *) getauxval(AT_SYSINFO_EHDR);
+ p = (char *) ((intptr_t) getauxval(AT_SYSINFO_EHDR));
if (p)
HR(p, pgs);
#endif
#ifdef AT_BASE
- p = (char *) getauxval(AT_BASE);
+ p = (char *) ((intptr_t) getauxval(AT_BASE));
if (p)
HD(p);
#endif
diff --git a/src/libbsd-overlay.pc.in b/src/libbsd-overlay.pc.in
index 01b7ea5..7ef4e4d 100644
--- a/src/libbsd-overlay.pc.in
+++ b/src/libbsd-overlay.pc.in
@@ -8,5 +8,6 @@ Description: Utility functions from BSD systems (overlay)
Version: @VERSION@
URL: https://libbsd.freedesktop.org/
Libs: -L${libdir} -lbsd
-Libs.private: @LIBBSD_LIBS@
+Libs.private: @LIBBSD_LIBS@ @MD5_LIBS@
+# We use -isystem instead of -I due the overlay via #include_next usage.
Cflags: -isystem ${includedir}/bsd -DLIBBSD_OVERLAY
diff --git a/src/libbsd.map b/src/libbsd.map
deleted file mode 100644
index 9281b3a..0000000
--- a/src/libbsd.map
+++ /dev/null
@@ -1,197 +0,0 @@
-LIBBSD_0.0 {
- global:
- arc4random;
- arc4random_stir;
- arc4random_addrandom;
-
- bsd_getopt;
- optreset;
-
- errc;
- warnc;
- verrc;
- vwarnc;
-
- fgetln;
- fmtcheck;
- heapsort;
- humanize_number;
-
- inet_net_pton; /* XXX: Already provided by glibc, remove. */
-
- getprogname;
- setprogname;
-
- strlcpy;
- strlcat;
-
- /*setmode;*/
- getmode;
-
- vis;
- strvis;
- strvisx;
- unvis;
- strunvis;
- strunvisx;
-
- /* The following functions are provided via the system libc or libmd
- * implementations. */
- MD5Init;
- MD5Update;
- MD5Pad;
- MD5Final;
- MD5Transform;
- MD5End;
- MD5File;
- MD5FileChunk;
- MD5Data;
-
- local:
- *;
-};
-
-LIBBSD_0.1 {
- strmode;
-
- __fdnlist; /* Private symbol, but libkvm uses it. */
- nlist;
-} LIBBSD_0.0;
-
-LIBBSD_0.2 {
- strtonum;
-
- strnvis;
- strnunvis;
-
- dehumanize_number;
-
- readpassphrase;
-
- flopen;
-
- pidfile_open;
- pidfile_write;
- pidfile_close;
- pidfile_remove;
-
- arc4random_buf;
- arc4random_uniform;
-} LIBBSD_0.1;
-
-LIBBSD_0.3 {
- reallocf;
- /*getpeereid;*/
-
- mergesort;
- radixsort;
- sradixsort;
-
- fpurge;
-} LIBBSD_0.2;
-
-LIBBSD_0.4 {
- closefrom;
- expand_number;
-} LIBBSD_0.3;
-
-LIBBSD_0.5 {
- fgetwln;
- fparseln;
-
- /* Introduced in 0.2 as a stub, implemented in 0.5. */
- setproctitle;
-
- strnstr;
-
- wcslcat;
- wcslcpy;
-} LIBBSD_0.4;
-
-LIBBSD_0.6 {
- /* Exported to cope with the constructor+dlopen+threads mess. */
- setproctitle_init;
-} LIBBSD_0.5;
-
-LIBBSD_0.7 {
- getbsize;
-
- /* This symbol might not be present on some specific systems, such
- * as musl based ones. It might need to be removed on SOVERSION bump,
- * as it cannot be portabily implemented everywhere. */
- /*funopen;*/
-
- reallocarray;
-
- sl_init;
- sl_add;
- sl_free;
- sl_find;
-
- _time32_to_time;
- _time_to_time32;
- _time64_to_time;
- _time_to_time64;
- _time_to_long;
- _long_to_time;
- _time_to_int;
- _int_to_time;
-} LIBBSD_0.6;
-
-LIBBSD_0.8 {
- explicit_bzero;
-} LIBBSD_0.7;
-
-LIBBSD_0.9 {
- flopenat;
-
- pidfile_fileno;
-
- strtoi;
- strtou;
-
- nvis;
- snvis;
- stravis;
- strenvisx;
- strnunvisx;
- strsenvisx;
- strsnvis;
- strsnvisx;
- strsvis;
- strsvisx;
- svis;
-} LIBBSD_0.8;
-
-LIBBSD_0.9.1 {
- /* The strnvis() and strnunvis() symbols changed prototype to match
- * the NetBSD implementation. Provided as versioned nodes in 0.9.1, and
- * exposed here explicitly so that we can redirect at compile-time. */
- strnvis_netbsd;
- strnunvis_netbsd;
-} LIBBSD_0.9;
-
-LIBBSD_0.10.0 {
- /* These BSD extensions are available on GNU systems, but not on other
- * systems such as Windows or musl libc based ones. */
- vwarn;
- vwarnx;
- warn;
- warnx;
- verr;
- verrx;
- err;
- errx;
-} LIBBSD_0.9.1;
-
-LIBBSD_0.11.0 {
- strnvisx;
-
- recallocarray;
- freezero;
-
- gid_from_group;
- group_from_gid;
- uid_from_user;
- user_from_uid;
-} LIBBSD_0.10.0;
diff --git a/src/libbsd.map.in b/src/libbsd.map.in
new file mode 100644
index 0000000..d7047dc
--- /dev/null
+++ b/src/libbsd.map.in
@@ -0,0 +1,319 @@
+#include "config.h"
+
+LIBBSD_0.0 {
+ global:
+#if LIBBSD_ABI_ARC4RANDOM
+ arc4random;
+#endif
+#if LIBBSD_ABI_ARC4RANDOM_STIR
+ arc4random_stir;
+ arc4random_addrandom;
+#endif
+
+#if LIBBSD_ABI_BSD_GETOPT
+ bsd_getopt;
+ optreset;
+#endif
+
+#if LIBBSD_ABI_ERRC
+ errc;
+ warnc;
+ verrc;
+ vwarnc;
+#endif
+
+#if LIBBSD_ABI_FGETLN
+ fgetln;
+#endif
+
+#if LIBBSD_ABI_FMTCHECK
+ fmtcheck;
+#endif
+
+#if LIBBSD_ABI_SORT
+ heapsort;
+#endif
+
+#if LIBBSD_ABI_HUMANIZE_NUMBER
+ humanize_number;
+#endif
+
+#if LIBBSD_ABI_INET_NET_PTON
+ inet_net_pton;
+#endif
+
+#if LIBBSD_ABI_PROGNAME
+ getprogname;
+ setprogname;
+#endif
+
+#if LIBBSD_ABI_STRL
+ strlcpy;
+ strlcat;
+#endif
+
+#if LIBBSD_ABI_ACCMODE
+ setmode;
+ getmode;
+#endif
+
+#if LIBBSD_ABI_VIS
+ vis;
+ strvis;
+ strvisx;
+ unvis;
+ strunvis;
+ strunvisx;
+#endif
+
+#if LIBBSD_ABI_MD5
+ MD5Init;
+ MD5Update;
+ MD5Pad;
+ MD5Final;
+ MD5Transform;
+ MD5End;
+ MD5File;
+ MD5FileChunk;
+ MD5Data;
+#endif
+
+ local:
+ *;
+};
+
+LIBBSD_0.1 {
+#if LIBBSD_ABI_STRMODE
+ strmode;
+#endif
+
+#if LIBBSD_ABI_NLIST
+ /* Private symbol, but libkvm uses it. */
+ __fdnlist;
+ nlist;
+#endif
+} LIBBSD_0.0;
+
+LIBBSD_0.2 {
+#if LIBBSD_ABI_STRTONUM
+ strtonum;
+#endif
+
+#if LIBBSD_ABI_VIS
+ strnvis;
+ strnunvis;
+#endif
+
+#if LIBBSD_ABI_HUMANIZE_NUMBER
+ dehumanize_number;
+#endif
+
+#if LIBBSD_ABI_READPASSPHRASE
+ readpassphrase;
+#endif
+
+#if LIBBSD_ABI_FLOPEN
+ flopen;
+#endif
+
+#if LIBBSD_ABI_PIDFILE
+ pidfile_open;
+ pidfile_write;
+ pidfile_close;
+ pidfile_remove;
+#endif
+
+#if LIBBSD_ABI_ARC4RANDOM
+ arc4random_buf;
+ arc4random_uniform;
+#endif
+} LIBBSD_0.1;
+
+LIBBSD_0.3 {
+#if LIBBSD_ABI_REALLOCF
+ reallocf;
+#endif
+
+#if LIBBSD_ABI_GETPEEREID
+ getpeereid;
+#endif
+
+#if LIBBSD_ABI_SORT
+ mergesort;
+ radixsort;
+ sradixsort;
+#endif
+
+#if LIBBSD_ABI_FPURGE
+ fpurge;
+#endif
+} LIBBSD_0.2;
+
+LIBBSD_0.4 {
+#if LIBBSD_ABI_CLOSEFROM
+ closefrom;
+#endif
+
+#if LIBBSD_ABI_EXPAND_NUMBER
+ expand_number;
+#endif
+} LIBBSD_0.3;
+
+LIBBSD_0.5 {
+#if LIBBSD_ABI_FGETLN
+ fgetwln;
+ fparseln;
+#endif
+
+#if LIBBSD_ABI_PROCTITLE
+ /* Introduced in 0.2 as a stub, implemented in 0.5. */
+ setproctitle;
+#endif
+
+#if LIBBSD_ABI_STRNSTR
+ strnstr;
+#endif
+
+#if LIBBSD_ABI_WCSL
+ wcslcat;
+ wcslcpy;
+#endif
+} LIBBSD_0.4;
+
+LIBBSD_0.6 {
+#if LIBBSD_ABI_PROCTITLE
+ /* Exported to cope with the constructor+dlopen+threads mess. */
+ setproctitle_init;
+#endif
+} LIBBSD_0.5;
+
+LIBBSD_0.7 {
+#if LIBBSD_ABI_GETBSIZE
+ getbsize;
+#endif
+
+#if LIBBSD_ABI_FUNOPEN
+ funopen;
+#endif
+
+#if LIBBSD_ABI_REALLOCARRAY
+ reallocarray;
+#endif
+
+#if LIBBSD_ABI_STRINGLIST
+ sl_init;
+ sl_add;
+ sl_free;
+ sl_find;
+#endif
+
+#if LIBBSD_ABI_TIMECONV
+ _time32_to_time;
+ _time_to_time32;
+ _time64_to_time;
+ _time_to_time64;
+ _time_to_long;
+ _long_to_time;
+ _time_to_int;
+ _int_to_time;
+#endif
+} LIBBSD_0.6;
+
+LIBBSD_0.8 {
+#if LIBBSD_ABI_EXPLICIT_BZERO
+ explicit_bzero;
+#endif
+} LIBBSD_0.7;
+
+LIBBSD_0.9 {
+#if LIBBSD_ABI_FLOPEN
+ flopenat;
+#endif
+
+#if LIBBSD_ABI_PIDFILE
+ pidfile_fileno;
+#endif
+
+#if LIBBSD_ABI_STRTOX
+ strtoi;
+ strtou;
+#endif
+
+#if LIBBSD_ABI_VIS
+ nvis;
+ snvis;
+ stravis;
+ strenvisx;
+ strnunvisx;
+ strsenvisx;
+ strsnvis;
+ strsnvisx;
+ strsvis;
+ strsvisx;
+ svis;
+#endif
+} LIBBSD_0.8;
+
+LIBBSD_0.9.1 {
+#if LIBBSD_ABI_VIS
+ /* The strnvis() and strnunvis() symbols changed prototype to match
+ * the NetBSD implementation. Provided as versioned nodes in 0.9.1, and
+ * exposed here explicitly so that we can redirect at compile-time. */
+ strnvis_netbsd;
+ strnunvis_netbsd;
+#endif
+} LIBBSD_0.9;
+
+LIBBSD_0.10.0 {
+#if LIBBSD_ABI_ERR
+ vwarn;
+ vwarnx;
+ warn;
+ warnx;
+ verr;
+ verrx;
+ err;
+ errx;
+#endif
+} LIBBSD_0.9.1;
+
+LIBBSD_0.11.0 {
+#if LIBBSD_ABI_VIS
+ strnvisx;
+#endif
+
+#if LIBBSD_ABI_RECALLOCARRAY
+ recallocarray;
+#endif
+
+#if LIBBSD_ABI_FREEZERO
+ freezero;
+#endif
+
+#if LIBBSD_ABI_ID_FROM_NAME
+ gid_from_group;
+ uid_from_user;
+#endif
+#if LIBBSD_ABI_NAME_FROM_ID
+ user_from_uid;
+ group_from_gid;
+#endif
+} LIBBSD_0.10.0;
+
+LIBBSD_0.12.0 {
+#if LIBBSD_ABI_ASPRINTF
+ vasprintf;
+ asprintf;
+#endif
+
+#if LIBBSD_ABI_TIMECONV && LIBBSD_ABI_TIME64
+ _time32_to_time_time64;
+ _time_to_time32_time64;
+ _time64_to_time_time64;
+ _time_to_time64_time64;
+ _time_to_long_time64;
+ _long_to_time_time64;
+ _time_to_int_time64;
+ _int_to_time_time64;
+#endif
+} LIBBSD_0.11.0;
diff --git a/src/libbsd.pc.in b/src/libbsd.pc.in
index 2c0ac17..4bca715 100644
--- a/src/libbsd.pc.in
+++ b/src/libbsd.pc.in
@@ -8,5 +8,5 @@ Description: Utility functions from BSD systems
Version: @VERSION@
URL: https://libbsd.freedesktop.org/
Libs: -L${libdir} -lbsd
-Libs.private: @LIBBSD_LIBS@
+Libs.private: @LIBBSD_LIBS@ @MD5_LIBS@
Cflags: -I${includedir}
diff --git a/src/local-elf.h b/src/local-elf.h
index 98a2962..8c4794f 100644
--- a/src/local-elf.h
+++ b/src/local-elf.h
@@ -124,6 +124,16 @@
#define ELF_TARG_CLASS ELFCLASS64
#define ELF_TARG_DATA ELFDATA2LSB
+#elif defined(__loongarch__)
+
+#define ELF_TARG_MACH EM_LOONGARCH
+#if defined(__loongarch64)
+#define ELF_TARG_CLASS ELFCLASS64
+#else
+#error Unsupported ELF class
+#endif
+#define ELF_TARG_DATA ELFDATA2LSB
+
#elif defined(__m32r__)
#define ELF_TARG_MACH EM_M32R
@@ -220,7 +230,7 @@
#if defined(__LITTLE_ENDIAN__)
#define ELF_TARG_DATA ELFDATA2LSB
#elif defined(__BIG_ENDIAN__)
-#define ELF_TARG_DATA ELFDATA2LMSB
+#define ELF_TARG_DATA ELFDATA2MSB
#else
#error Unknown SH endianness
#endif
diff --git a/src/local-link.h b/src/local-link.h
index 55fd028..dd67c70 100644
--- a/src/local-link.h
+++ b/src/local-link.h
@@ -27,21 +27,58 @@
#ifndef LIBBSD_LOCAL_LINK_H
#define LIBBSD_LOCAL_LINK_H
+#include <sys/cdefs.h>
+
+#ifdef __ELF__
#define libbsd_link_warning(symbol, msg) \
static const char libbsd_emit_link_warning_##symbol[] \
__attribute__((__used__,__section__(".gnu.warning." #symbol))) = msg
+#else
+#define libbsd_link_warning(symbol, msg)
+#endif
-#ifdef __ELF__
-#define libbsd_symver_default(alias, symbol, version) \
+#if defined(__APPLE__)
+#define libbsd_strong_alias(symbol, alias) \
+ __asm__(".globl _" #alias); \
+ __asm__(".set _" #alias ", _" #symbol); \
+ extern __typeof(symbol) alias
+#elif !defined(_MSC_VER)
+#define libbsd_strong_alias(symbol, alias) \
+ extern __typeof__(symbol) alias __attribute__((__alias__(#symbol)))
+#endif
+
+#if defined(__ELF__) && !defined(__sun)
+# if __has_attribute(symver)
+/* The symver attribute is supported since gcc 10.x. */
+#define libbsd_symver_default(symbol, alias, version) \
+ extern __typeof__(symbol) symbol \
+ __attribute__((__symver__(#alias "@@" #version)))
+#define libbsd_symver_variant(symbol, alias, version) \
+ extern __typeof__(symbol) symbol \
+ __attribute__((__symver__(#alias "@" #version)))
+
+#define libbsd_symver_weak(symbol, alias, version) \
+ extern __typeof__(symbol) symbol \
+ __attribute__((__symver__(#alias "@" #version), __weak__))
+# else
+#define libbsd_symver_default(symbol, alias, version) \
__asm__(".symver " #symbol "," #alias "@@" #version)
-#define libbsd_symver_variant(alias, symbol, version) \
+#define libbsd_symver_variant(symbol, alias, version) \
__asm__(".symver " #symbol "," #alias "@" #version)
+
+#define libbsd_symver_weak(symbol, alias, version) \
+ libbsd_symver_variant(symbol, alias, version); \
+ extern __typeof__(symbol) alias \
+ __attribute__((__weak__))
+# endif
#else
-#define libbsd_symver_default(alias, symbol, version) \
- extern __typeof(symbol) alias __attribute__((__alias__(#symbol)))
+#define libbsd_symver_default(symbol, alias, version) \
+ libbsd_strong_alias(symbol, alias)
+
+#define libbsd_symver_variant(symbol, alias, version)
-#define libbsd_symver_variant(alias, symbol, version)
+#define libbsd_symver_weak(symbol, alias, version)
#endif
#endif
diff --git a/src/md5.c b/src/md5.c
index 00769aa..289cba4 100644
--- a/src/md5.c
+++ b/src/md5.c
@@ -24,119 +24,97 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <stddef.h>
-#include <stdlib.h>
-#include <dlfcn.h>
#include <md5.h>
#include "local-link.h"
-static void (*libmd_MD5Init)(MD5_CTX *);
-static void (*libmd_MD5Update)(MD5_CTX *, const uint8_t *, size_t);
-static void (*libmd_MD5Pad)(MD5_CTX *);
-static void (*libmd_MD5Final)(uint8_t [MD5_DIGEST_LENGTH], MD5_CTX *);
-static void (*libmd_MD5Transform)(uint32_t [4], const uint8_t [MD5_BLOCK_LENGTH]);
-static char *(*libmd_MD5End)(MD5_CTX *, char *);
-static char *(*libmd_MD5File)(const char *, char *);
-static char *(*libmd_MD5FileChunk)(const char *, char *, off_t, off_t);
-static char *(*libmd_MD5Data)(const uint8_t *, size_t, char *);
-
-static void *
-libmd_loader(const char *symbol)
-{
- void *func;
-
- func = dlsym(RTLD_NEXT, symbol);
- if (func == NULL) {
- fprintf(stderr,
- "libbsd: cannot find wrapped symbol %s in libc or libmd\n",
- symbol);
- abort();
- }
-
- return func;
-}
-
-#define libmd_wrapper(symbol) \
- if (libmd_ ## symbol == NULL) \
- libmd_ ## symbol = libmd_loader(#symbol)
+#pragma GCC diagnostic ignored "-Wmissing-prototypes"
void
-MD5Init(MD5_CTX *context)
+libbsd_MD5Init(MD5_CTX *context)
{
- libmd_wrapper(MD5Init);
- libmd_MD5Init(context);
+ MD5Init(context);
}
libbsd_link_warning(MD5Init,
- "This function is a deprecated wrapper, use libmd instead.");
+ "The MD5Init() function in libbsd is a deprecated wrapper, "
+ "use libmd instead.");
+libbsd_symver_weak(libbsd_MD5Init, MD5Init, LIBBSD_0.0);
void
-MD5Update(MD5_CTX *context, const uint8_t *data, size_t len)
+libbsd_MD5Update(MD5_CTX *context, const uint8_t *data, size_t len)
{
- libmd_wrapper(MD5Update);
- libmd_MD5Update(context, data, len);
+ MD5Update(context, data, len);
}
libbsd_link_warning(MD5Update,
- "This function is a deprecated wrapper, use libmd instead.");
+ "The MD5Update() function in libbsd is a deprecated wrapper, "
+ "use libmd instead.");
+libbsd_symver_weak(libbsd_MD5Update, MD5Update, LIBBSD_0.0);
void
-MD5Pad(MD5_CTX *context)
+libbsd_MD5Pad(MD5_CTX *context)
{
- libmd_wrapper(MD5Pad);
- libmd_MD5Pad(context);
+ MD5Pad(context);
}
libbsd_link_warning(MD5Pad,
- "This function is a deprecated wrapper, use libmd instead.");
+ "The MD5Pad() function in libbsd is a deprecated wrapper, "
+ "use libmd instead.");
+libbsd_symver_weak(libbsd_MD5Pad, MD5Pad, LIBBSD_0.0);
void
-MD5Final(uint8_t digest[MD5_DIGEST_LENGTH], MD5_CTX *context)
+libbsd_MD5Final(uint8_t digest[MD5_DIGEST_LENGTH], MD5_CTX *context)
{
- libmd_wrapper(MD5Final);
- libmd_MD5Final(digest, context);
+ MD5Final(digest, context);
}
libbsd_link_warning(MD5Final,
- "This function is a deprecated wrapper, use libmd instead.");
+ "The MD5Final() function in libbsd is a deprecated wrapper, "
+ "use libmd instead.");
+libbsd_symver_weak(libbsd_MD5Final, MD5Final, LIBBSD_0.0);
void
-MD5Transform(uint32_t state[4], const uint8_t block[MD5_BLOCK_LENGTH])
+libbsd_MD5Transform(uint32_t state[4], const uint8_t block[MD5_BLOCK_LENGTH])
{
- libmd_wrapper(MD5Transform);
- libmd_MD5Transform(state, block);
+ MD5Transform(state, block);
}
libbsd_link_warning(MD5Transform,
- "This function is a deprecated wrapper, use libmd instead.");
+ "The MD5Transform() function in libbsd is a deprecated wrapper, "
+ "use libmd instead.");
+libbsd_symver_weak(libbsd_MD5Transform, MD5Transform, LIBBSD_0.0);
char *
-MD5End(MD5_CTX *context, char *buf)
+libbsd_MD5End(MD5_CTX *context, char *buf)
{
- libmd_wrapper(MD5End);
- return libmd_MD5End(context, buf);
+ return MD5End(context, buf);
}
libbsd_link_warning(MD5End,
- "This function is a deprecated wrapper, use libmd instead.");
+ "The MD5End() function in libbsd is a deprecated wrapper, "
+ "use libmd instead.");
+libbsd_symver_weak(libbsd_MD5End, MD5End, LIBBSD_0.0);
char *
-MD5File(const char *filename, char *buf)
+libbsd_MD5File(const char *filename, char *buf)
{
- libmd_wrapper(MD5File);
return MD5File(filename, buf);
}
libbsd_link_warning(MD5File,
- "This function is a deprecated wrapper, use libmd instead.");
+ "The MD5File() function in libbsd is a deprecated wrapper, "
+ "use libmd instead.");
+libbsd_symver_weak(libbsd_MD5File, MD5File, LIBBSD_0.0);
char *
-MD5FileChunk(const char *filename, char *buf, off_t offset, off_t length)
+libbsd_MD5FileChunk(const char *filename, char *buf, off_t offset, off_t length)
{
- libmd_wrapper(MD5FileChunk);
- return libmd_MD5FileChunk(filename, buf, offset, length);
+ return MD5FileChunk(filename, buf, offset, length);
}
libbsd_link_warning(MD5FileChunk,
- "This function is a deprecated wrapper, use libmd instead.");
+ "The MD5FileChunk() function in libbsd is a deprecated wrapper, "
+ "use libmd instead.");
+libbsd_symver_weak(libbsd_MD5FileChunk, MD5FileChunk, LIBBSD_0.0);
char *
-MD5Data(const uint8_t *data, size_t len, char *buf)
+libbsd_MD5Data(const uint8_t *data, size_t len, char *buf)
{
- libmd_wrapper(MD5Data);
- return libmd_MD5Data(data, len, buf);
+ return MD5Data(data, len, buf);
}
libbsd_link_warning(MD5Data,
- "This function is a deprecated wrapper, use libmd instead.");
+ "The MD5Data() function in libbsd is a deprecated wrapper, "
+ "use libmd instead.");
+libbsd_symver_weak(libbsd_MD5Data, MD5Data, LIBBSD_0.0);
diff --git a/src/merge.c b/src/merge.c
index c43866f..3f1b3fb 100644
--- a/src/merge.c
+++ b/src/merge.c
@@ -84,9 +84,8 @@ static void insertionsort(unsigned char *, size_t, size_t,
*/
/* Assumption: PSIZE is a power of 2. */
#define EVAL(p) (unsigned char **) \
- ((unsigned char *)0 + \
(((unsigned char *)p + PSIZE - 1 - \
- (unsigned char *)0) & ~(PSIZE - 1)))
+ (unsigned char *)0) & ~(PSIZE - 1))
/*
* Arguments are as for qsort.
diff --git a/src/nlist.c b/src/nlist.c
index 8012d5a..1cb9d18 100644
--- a/src/nlist.c
+++ b/src/nlist.c
@@ -43,10 +43,6 @@
#include "local-elf.h"
-#ifndef SIZE_T_MAX
-#define SIZE_T_MAX 0xffffffffU
-#endif
-
/* Note: This function is used by libkvm0, so we need to export it.
* It is not declared in the include files though. */
int __fdnlist(int, struct nlist *);
@@ -153,7 +149,7 @@ __fdnlist(int fd, struct nlist *list)
shdr_size = ehdr.e_shentsize * ehdr.e_shnum;
/* Make sure it's not too big to mmap */
- if (shdr_size > SIZE_T_MAX || shdr_size > st.st_size) {
+ if (shdr_size > st.st_size) {
errno = EFBIG;
return (-1);
}
@@ -186,7 +182,7 @@ __fdnlist(int fd, struct nlist *list)
}
/* Check for files too large to mmap. */
- if (symstrsize > SIZE_T_MAX || symstrsize > st.st_size) {
+ if (symstrsize > st.st_size) {
errno = EFBIG;
goto done;
}
diff --git a/src/progname.c b/src/progname.c
index bebf714..83e8652 100644
--- a/src/progname.c
+++ b/src/progname.c
@@ -35,6 +35,9 @@
#include <errno.h>
#include <string.h>
#include <stdlib.h>
+#ifdef HAVE_PROCINFO_H
+#include <procinfo.h>
+#endif
#ifdef _WIN32
#include <Windows.h>
#include <shlwapi.h>
@@ -62,6 +65,14 @@ getprogname(void)
/* getexecname(3) returns an absolute pathname, normalize it. */
if (__progname == NULL)
setprogname(getexecname());
+#elif defined(_AIX)
+ if (__progname == NULL) {
+ struct procentry64 procs;
+ pid_t pid = getpid ();
+
+ if (getprocs64(&procs, sizeof procs, NULL, 0, &pid, 1) > 0)
+ __progname = strdup(procs.pi_comm);
+ }
#elif defined(_WIN32)
if (__progname == NULL) {
WCHAR *wpath = NULL;
@@ -126,6 +137,8 @@ done:
free(wpath);
free(mbname);
}
+#else
+#error "Function getprogname() needs to be ported."
#endif
return __progname;
diff --git a/src/pwcache.c b/src/pwcache.c
index d54daa0..8ed855c 100644
--- a/src/pwcache.c
+++ b/src/pwcache.c
@@ -83,8 +83,12 @@ typedef struct gidc {
* cache both hits and misses.
*/
+#ifndef HAVE_USER_FROM_UID
static UIDC **uidtb; /* uid to name cache */
+#endif
+#ifndef HAVE_GROUP_FROM_GID
static GIDC **gidtb; /* gid to name cache */
+#endif
static UIDC **usrtb; /* user name to uid cache */
static GIDC **grptb; /* group name to gid cache */
@@ -103,6 +107,7 @@ st_hash(const char *name, size_t len, int tabsz)
return key % tabsz;
}
+#ifndef HAVE_USER_FROM_UID
/*
* uidtb_start
* creates an an empty uidtb
@@ -124,7 +129,9 @@ uidtb_start(void)
}
return 0;
}
+#endif
+#ifndef HAVE_GROUP_FROM_GID
/*
* gidtb_start
* creates an an empty gidtb
@@ -146,6 +153,7 @@ gidtb_start(void)
}
return 0;
}
+#endif
/*
* usrtb_start
@@ -191,6 +199,7 @@ grptb_start(void)
return 0;
}
+#ifndef HAVE_USER_FROM_UID
/*
* user_from_uid()
* caches the name (if any) for the uid. If noname clear, we always
@@ -251,7 +260,9 @@ user_from_uid(uid_t uid, int noname)
}
return ptr->name;
}
+#endif
+#ifndef HAVE_GROUP_FROM_GID
/*
* group_from_gid()
* caches the name (if any) for the gid. If noname clear, we always
@@ -312,6 +323,7 @@ group_from_gid(gid_t gid, int noname)
}
return ptr->name;
}
+#endif
/*
* uid_from_user()
diff --git a/src/readpassphrase.c b/src/readpassphrase.c
index f9f6195..0082c82 100644
--- a/src/readpassphrase.c
+++ b/src/readpassphrase.c
@@ -36,6 +36,15 @@
#define TCSASOFT 0
#endif
+#ifndef _NSIG
+#if defined(NSIG)
+#define _NSIG NSIG
+#else
+/* The SIGRTMAX define might be set to a function such as sysconf(). */
+#define _NSIG (SIGRTMAX + 1)
+#endif
+#endif
+
static volatile sig_atomic_t signo[_NSIG];
static void handler(int);
diff --git a/src/setmode.c b/src/setmode.c
index 48ac2dd..12b5f7e 100644
--- a/src/setmode.c
+++ b/src/setmode.c
@@ -36,6 +36,7 @@
#include <sys/types.h>
#include <sys/stat.h>
+#include <stddef.h>
#include <ctype.h>
#include <errno.h>
#include <signal.h>
@@ -144,12 +145,13 @@ common: if (set->cmd2 & CMD2_CLR) {
#define ADDCMD(a, b, c, d) do { \
if (set >= endset) { \
+ ptrdiff_t setdiff = set - saveset; \
BITCMD *newset; \
setlen += SET_LEN_INCR; \
newset = reallocarray(saveset, setlen, sizeof(BITCMD)); \
if (newset == NULL) \
goto out; \
- set = newset + (set - saveset); \
+ set = newset + setdiff; \
saveset = newset; \
endset = newset + (setlen - 2); \
} \
diff --git a/src/setproctitle.c b/src/setproctitle.c
index ff32aa3..06928e6 100644
--- a/src/setproctitle.c
+++ b/src/setproctitle.c
@@ -33,6 +33,10 @@
#include <string.h>
#include "local-link.h"
+#if !HAVE_DECL_ENVIRON
+extern char **environ;
+#endif
+
static struct {
/* Original value. */
const char *arg0;
@@ -222,6 +226,10 @@ setproctitle_init(int argc, char *argv[], char *envp[])
#define SPT_MAXTITLE 255
#endif
+__printflike(1, 2)
+void
+setproctitle_impl(const char *fmt, ...);
+
void
setproctitle_impl(const char *fmt, ...)
{
@@ -276,24 +284,22 @@ setproctitle_impl(const char *fmt, ...)
if (nul < SPT.nul) {
*SPT.nul = '.';
- } else if (nul == SPT.nul && &nul[1] < SPT.end) {
+ } else if (nul == SPT.nul && (nul + 1) < SPT.end) {
*SPT.nul = ' ';
*++nul = '\0';
}
}
-libbsd_symver_default(setproctitle, setproctitle_impl, LIBBSD_0.5);
+libbsd_symver_default(setproctitle_impl, setproctitle, LIBBSD_0.5);
/* The original function introduced in 0.2 was a stub, it only got implemented
* in 0.5, make the implementation available in the old version as an alias
* for code linking against that version, and change the default to use the
* new version, so that new code depends on the implemented version. */
-#ifdef HAVE_TYPEOF
-extern __typeof__(setproctitle_impl)
-setproctitle_stub
- __attribute__((__alias__("setproctitle_impl")));
+#if defined(libbsd_strong_alias)
+libbsd_strong_alias(setproctitle_impl, setproctitle_stub);
#else
void
setproctitle_stub(const char *fmt, ...)
__attribute__((__alias__("setproctitle_impl")));
#endif
-libbsd_symver_variant(setproctitle, setproctitle_stub, LIBBSD_0.2);
+libbsd_symver_variant(setproctitle_stub, setproctitle, LIBBSD_0.2);
diff --git a/src/setproctitle_ctor.c b/src/setproctitle_ctor.c
index 2c5b6d0..d97de50 100644
--- a/src/setproctitle_ctor.c
+++ b/src/setproctitle_ctor.c
@@ -38,7 +38,7 @@
*
* To avoid any other possible fallout, the constructor is split into a
* new static library that needs to be linked explicitly into programs
- * using setproctitle(). As an additional safety measure the pkg-config
+ * using setproctitle(). As an additional safety measure the pkgconf(1)
* linker flags will mark the program as not allowing to be dlopen()ed
* so that we make sure to avoid the problem described above.
*/
@@ -49,4 +49,4 @@
* move them from .ctors to .init_array.
*/
void (*libbsd_init_func)(int argc, char *argv[], char *envp[])
- __attribute__((__section__(".init_array"))) = setproctitle_init;
+ __attribute__((__section__(".init_array"), __used__)) = setproctitle_init;
diff --git a/src/strtoi.c b/src/strtoi.c
index 9e3771d..7a27ca7 100644
--- a/src/strtoi.c
+++ b/src/strtoi.c
@@ -1,4 +1,4 @@
-/* $NetBSD: _strtoi.h,v 1.2 2015/01/18 17:55:22 christos Exp $ */
+/* $NetBSD: _strtoi.h,v 1.3 2024/01/20 16:13:39 christos Exp $ */
/*-
* Copyright (c) 1990, 1993
@@ -32,7 +32,7 @@
* NetBSD: src/lib/libc/locale/_wcstoul.h,v 1.2 2003/08/07 16:43:03 agc Exp
*
* Created by Kamil Rytarowski, based on ID:
- * NetBSD: src/common/lib/libc/stdlib/_strtoul.h,v 1.7 2013/05/17 12:55:56 joe…
+ * NetBSD: src/common/lib/libc/stdlib/_strtoul.h,v 1.7 2013/05/17 12:55:56 joerg Exp
*/
#include <sys/cdefs.h>
@@ -73,25 +73,25 @@ strtoi(const char *__restrict nptr,
*rstatus = errno;
errno = serrno;
- if (*rstatus == 0) {
- /* No digits were found */
- if (nptr == *endptr)
- *rstatus = ECANCELED;
- /* There are further characters after number */
- else if (**endptr != '\0')
- *rstatus = ENOTSUP;
- }
+ /* No digits were found */
+ if (*rstatus == 0 && nptr == *endptr)
+ *rstatus = ECANCELED;
if (im < lo) {
if (*rstatus == 0)
*rstatus = ERANGE;
return lo;
}
+
if (im > hi) {
if (*rstatus == 0)
*rstatus = ERANGE;
return hi;
}
+ /* There are further characters after number */
+ if (*rstatus == 0 && **endptr != '\0')
+ *rstatus = ENOTSUP;
+
return im;
}
diff --git a/src/strtonum.c b/src/strtonum.c
index 2fa0fcf..f85f741 100644
--- a/src/strtonum.c
+++ b/src/strtonum.c
@@ -1,4 +1,4 @@
-/* $NetBSD: strtonum.c,v 1.5 2018/01/04 20:57:29 kamil Exp $ */
+/* $NetBSD: strtonum.c,v 1.7 2024/01/20 16:13:39 christos Exp $ */
/*-
* Copyright (c) 2014 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -42,21 +42,34 @@ strtonum(const char *nptr, long long minval, long long maxval,
int e;
long long rv;
const char *resp;
+ char *eptr;
if (errstr == NULL)
errstr = &resp;
- rv = (long long)strtoi(nptr, NULL, 10, minval, maxval, &e);
+ if (minval > maxval)
+ goto out;
- if (e == 0) {
+ rv = (long long)strtoi(nptr, &eptr, 10, minval, maxval, &e);
+
+ switch (e) {
+ case 0:
*errstr = NULL;
return rv;
+ case ECANCELED:
+ case ENOTSUP:
+ case EINVAL:
+ goto out;
+ case ERANGE:
+ if (*eptr)
+ goto out;
+ *errstr = rv == maxval ? "too large" : "too small";
+ return 0;
+ default:
+ abort();
}
- if (e == ERANGE)
- *errstr = (rv == maxval ? "too large" : "too small");
- else
- *errstr = "invalid";
-
+out:
+ *errstr = "invalid";
return 0;
}
diff --git a/src/strtou.c b/src/strtou.c
index 0e22a88..a87adcc 100644
--- a/src/strtou.c
+++ b/src/strtou.c
@@ -1,4 +1,4 @@
-/* $NetBSD: _strtoi.h,v 1.2 2015/01/18 17:55:22 christos Exp $ */
+/* $NetBSD: _strtoi.h,v 1.3 2024/01/20 16:13:39 christos Exp $ */
/*-
* Copyright (c) 1990, 1993
@@ -73,25 +73,25 @@ strtou(const char *__restrict nptr,
*rstatus = errno;
errno = serrno;
- if (*rstatus == 0) {
- /* No digits were found */
- if (nptr == *endptr)
- *rstatus = ECANCELED;
- /* There are further characters after number */
- else if (**endptr != '\0')
- *rstatus = ENOTSUP;
- }
+ /* No digits were found */
+ if (*rstatus == 0 && nptr == *endptr)
+ *rstatus = ECANCELED;
if (im < lo) {
if (*rstatus == 0)
*rstatus = ERANGE;
return lo;
}
+
if (im > hi) {
if (*rstatus == 0)
*rstatus = ERANGE;
return hi;
}
+ /* There are further characters after number */
+ if (*rstatus == 0 && **endptr != '\0')
+ *rstatus = ENOTSUP;
+
return im;
}
diff --git a/src/timeconv.c b/src/timeconv.c
index 11f926e..0c122e4 100644
--- a/src/timeconv.c
+++ b/src/timeconv.c
@@ -32,17 +32,161 @@
#include <sys/cdefs.h>
#include <sys/types.h>
-#include <timeconv.h>
+
+#include "local-link.h"
+
+#if LIBBSD_SYS_TIME_BITS == 64
+/*
+ * - enable time64 functions
+ * - symver libbsd<func>_time64 -> <func> 0.7
+ */
+#define time32_symbol(name)
+#define time64_symbol(name) \
+ libbsd_strong_alias(libbsd ## name ## _time64, name)
+#elif LIBBSD_SYS_TIME_BITS == 32 && LIBBSD_SYS_HAS_TIME64
+/*
+ * - enable time32 functions
+ * - enable time64 functions
+ * - symver libbsd<func>_time32 -> <func> 0.7
+ * - map libbsd<func>_time64 <func>_time64 0.12
+ */
+#define time32_symbol(name) \
+ libbsd_strong_alias(libbsd ## name ## _time32, name)
+#define time64_symbol(name) \
+ libbsd_strong_alias(libbsd ## name ## _time64, name ## _time64)
+#elif LIBBSD_SYS_TIME_BITS == 32 && !LIBBSD_SYS_HAS_TIME64
+/*
+ * - enable time32 functions
+ * - symver libbsd<func>_time32 -> <func>
+ */
+#define time32_symbol(name) \
+ libbsd_strong_alias(libbsd ## name ## _time32, name)
+#define time64_symbol(name)
+#else
+#error "Unknown time_t support"
+#endif
+
+#if LIBBSD_SYS_HAS_TIME64
+typedef int64_t libbsd_time64_t;
/*
* Convert a 32 bit representation of time_t into time_t. XXX needs to
* implement the 50-year rule to handle post-2038 conversions.
*/
-time_t
-_time32_to_time(int32_t t32)
+libbsd_time64_t
+libbsd_time32_to_time_time64(int32_t t32);
+libbsd_time64_t
+libbsd_time32_to_time_time64(int32_t t32)
+{
+ return((libbsd_time64_t)t32);
+}
+time64_symbol(_time32_to_time);
+
+/*
+ * Convert time_t to a 32 bit representation. If time_t is 64 bits we can
+ * simply chop it down. The resulting 32 bit representation can be
+ * converted back to a temporally local 64 bit time_t using time32_to_time.
+ */
+int32_t
+libbsd_time_to_time32_time64(libbsd_time64_t t);
+int32_t
+libbsd_time_to_time32_time64(libbsd_time64_t t)
+{
+ return((int32_t)t);
+}
+time64_symbol(_time_to_time32);
+
+/*
+ * Convert a 64 bit representation of time_t into time_t. If time_t is
+ * represented as 32 bits we can simply chop it and not support times
+ * past 2038.
+ */
+libbsd_time64_t
+libbsd_time64_to_time_time64(int64_t t64);
+libbsd_time64_t
+libbsd_time64_to_time_time64(int64_t t64)
+{
+ return((libbsd_time64_t)t64);
+}
+time64_symbol(_time64_to_time);
+
+/*
+ * Convert time_t to a 64 bit representation. If time_t is represented
+ * as 32 bits we simply sign-extend and do not support times past 2038.
+ */
+int64_t
+libbsd_time_to_time64_time64(libbsd_time64_t t);
+int64_t
+libbsd_time_to_time64_time64(libbsd_time64_t t)
+{
+ return((int64_t)t);
+}
+time64_symbol(_time_to_time64);
+
+/*
+ * Convert to/from 'long'. Depending on the sizeof(long) this may or
+ * may not require using the 50-year rule.
+ */
+long
+libbsd_time_to_long_time64(libbsd_time64_t t);
+long
+libbsd_time_to_long_time64(libbsd_time64_t t)
+{
+ if (sizeof(long) == sizeof(int64_t))
+ return(libbsd_time_to_time64_time64(t));
+ return((long)t);
+}
+time64_symbol(_time_to_long);
+
+libbsd_time64_t
+libbsd_long_to_time_time64(long tlong);
+libbsd_time64_t
+libbsd_long_to_time_time64(long tlong)
+{
+ if (sizeof(long) == sizeof(int32_t))
+ return(libbsd_time32_to_time_time64(tlong));
+ return((libbsd_time64_t)tlong);
+}
+time64_symbol(_long_to_time);
+
+/*
+ * Convert to/from 'int'. Depending on the sizeof(int) this may or
+ * may not require using the 50-year rule.
+ */
+int
+libbsd_time_to_int_time64(time_t t);
+int
+libbsd_time_to_int_time64(time_t t)
{
- return((time_t)t32);
+ if (sizeof(int) == sizeof(int64_t))
+ return(libbsd_time_to_time64_time64(t));
+ return((int)t);
}
+time64_symbol(_time_to_int);
+
+libbsd_time64_t
+libbsd_int_to_time_time64(int tint);
+libbsd_time64_t
+libbsd_int_to_time_time64(int tint)
+{
+ if (sizeof(int) == sizeof(int32_t))
+ return(libbsd_time32_to_time_time64(tint));
+ return((libbsd_time64_t)tint);
+}
+time64_symbol(_int_to_time);
+#endif
+
+#if LIBBSD_SYS_TIME_BITS == 32
+typedef int32_t libbsd_time32_t;
+
+libbsd_time32_t
+libbsd_time32_to_time_time32(int32_t t32);
+libbsd_time32_t
+libbsd_time32_to_time_time32(int32_t t32)
+{
+ return((libbsd_time32_t)t32);
+}
+time32_symbol(_time32_to_time);
/*
* Convert time_t to a 32 bit representation. If time_t is 64 bits we can
@@ -50,68 +194,90 @@ _time32_to_time(int32_t t32)
* converted back to a temporally local 64 bit time_t using time32_to_time.
*/
int32_t
-_time_to_time32(time_t t)
+libbsd_time_to_time32_time32(libbsd_time32_t t);
+int32_t
+libbsd_time_to_time32_time32(libbsd_time32_t t)
{
return((int32_t)t);
}
+time32_symbol(_time_to_time32);
/*
* Convert a 64 bit representation of time_t into time_t. If time_t is
* represented as 32 bits we can simply chop it and not support times
* past 2038.
*/
-time_t
-_time64_to_time(int64_t t64)
+libbsd_time32_t
+libbsd_time64_to_time_time32(int64_t t64);
+libbsd_time32_t
+libbsd_time64_to_time_time32(int64_t t64)
{
- return((time_t)t64);
+ return((libbsd_time32_t)t64);
}
+time32_symbol(_time64_to_time);
/*
* Convert time_t to a 64 bit representation. If time_t is represented
* as 32 bits we simply sign-extend and do not support times past 2038.
*/
int64_t
-_time_to_time64(time_t t)
+libbsd_time_to_time64_time32(libbsd_time32_t t);
+int64_t
+libbsd_time_to_time64_time32(libbsd_time32_t t)
{
return((int64_t)t);
}
+time32_symbol(_time_to_time64);
/*
* Convert to/from 'long'. Depending on the sizeof(long) this may or
* may not require using the 50-year rule.
*/
long
-_time_to_long(time_t t)
+libbsd_time_to_long_time32(libbsd_time32_t t);
+long
+libbsd_time_to_long_time32(libbsd_time32_t t)
{
if (sizeof(long) == sizeof(int64_t))
- return(_time_to_time64(t));
+ return(libbsd_time_to_time64_time32(t));
return((long)t);
}
+time32_symbol(_time_to_long);
-time_t
-_long_to_time(long tlong)
+libbsd_time32_t
+libbsd_long_to_time_time32(long tlong);
+libbsd_time32_t
+libbsd_long_to_time_time32(long tlong)
{
if (sizeof(long) == sizeof(int32_t))
- return(_time32_to_time(tlong));
- return((time_t)tlong);
+ return(libbsd_time32_to_time_time32(tlong));
+ return((libbsd_time32_t)tlong);
}
+time32_symbol(_long_to_time);
/*
* Convert to/from 'int'. Depending on the sizeof(int) this may or
* may not require using the 50-year rule.
*/
int
-_time_to_int(time_t t)
+libbsd_time_to_int_time32(libbsd_time32_t t);
+int
+libbsd_time_to_int_time32(libbsd_time32_t t)
{
if (sizeof(int) == sizeof(int64_t))
- return(_time_to_time64(t));
+ return(libbsd_time_to_time64_time32(t));
return((int)t);
}
+time32_symbol(_time_to_int);
-time_t
-_int_to_time(int tint)
+libbsd_time32_t
+libbsd_int_to_time_time32(int tint);
+libbsd_time32_t
+libbsd_int_to_time_time32(int tint)
{
if (sizeof(int) == sizeof(int32_t))
- return(_time32_to_time(tint));
- return((time_t)tint);
+ return(libbsd_time32_to_time_time32(tint));
+ return((libbsd_time32_t)tint);
}
+time32_symbol(_int_to_time);
+#endif
diff --git a/src/unvis.c b/src/unvis.c
index 166421a..378cee6 100644
--- a/src/unvis.c
+++ b/src/unvis.c
@@ -554,7 +554,7 @@ strunvis(char *dst, const char *src)
* existing one in OpenBSD and Freedesktop's libbsd (the former having existed
* for over ten years). Despite this incompatibility being reported during
* development (see http://gnats.netbsd.org/44977) they still shipped it.
- * Even more unfortunately FreeBSD and later MacOS picked up this incompatible
+ * Even more unfortunately FreeBSD and later macOS picked up this incompatible
* implementation.
*
* Provide both implementations and default for now on the historical one to
@@ -564,15 +564,19 @@ strunvis(char *dst, const char *src)
* NetBSD: 2012, strnunvis(char *dst, size_t dlen, const char *src);
*/
ssize_t
+strnunvis_openbsd(char *, const char *, size_t);
+ssize_t
strnunvis_openbsd(char *dst, const char *src, size_t dlen)
{
return strnunvisx(dst, dlen, src, 0);
}
-libbsd_symver_default(strnunvis, strnunvis_openbsd, LIBBSD_0.2);
+libbsd_symver_default(strnunvis_openbsd, strnunvis, LIBBSD_0.2);
int
+strnunvis_netbsd(char *, size_t, const char *);
+int
strnunvis_netbsd(char *dst, size_t dlen, const char *src)
{
return strnunvisx(dst, dlen, src, 0);
}
-libbsd_symver_variant(strnunvis, strnunvis_netbsd, LIBBSD_0.9.1);
+libbsd_symver_variant(strnunvis_netbsd, strnunvis, LIBBSD_0.9.1);
diff --git a/src/vasprintf.c b/src/vasprintf.c
new file mode 100644
index 0000000..d9ae8bb
--- /dev/null
+++ b/src/vasprintf.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright © 2010-2024 Guillem Jover <guillem@hadrons.org>
+ *
+ * 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 author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``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 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 <config.h>
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+vasprintf(char **strp, char const *fmt, va_list args)
+{
+ va_list args_copy;
+ int needed, n;
+ char *str;
+
+ va_copy(args_copy, args);
+ needed = vsnprintf(NULL, 0, fmt, args_copy);
+ va_end(args_copy);
+
+ if (needed < 0) {
+ *strp = NULL;
+ return -1;
+ }
+
+ str = malloc(needed + 1);
+ if (str == NULL) {
+ *strp = NULL;
+ return -1;
+ }
+
+ n = vsnprintf(str, needed + 1, fmt, args);
+ if (n < 0) {
+ free(str);
+ str = NULL;
+ }
+
+ *strp = str;
+
+ return n;
+}
diff --git a/src/vis.c b/src/vis.c
index c8e5ae8..0dafa62 100644
--- a/src/vis.c
+++ b/src/vis.c
@@ -723,7 +723,7 @@ strvis(char *mbdst, const char *mbsrc, int flags)
* existing one in OpenBSD and Freedesktop's libbsd (the former having existed
* for over ten years). Despite this incompatibility being reported during
* development (see http://gnats.netbsd.org/44977) they still shipped it.
- * Even more unfortunately FreeBSD and later MacOS picked up this incompatible
+ * Even more unfortunately FreeBSD and later macOS picked up this incompatible
* implementation.
*
* Provide both implementations and default for now on the historical one to
@@ -733,18 +733,22 @@ strvis(char *mbdst, const char *mbsrc, int flags)
* NetBSD: 2012, strnvis(char *dst, size_t dlen, const char *src, int flag);
*/
int
+strnvis_openbsd(char *, const char *, size_t, int);
+int
strnvis_openbsd(char *mbdst, const char *mbsrc, size_t dlen, int flags)
{
return istrsenvisxl(mbdst, &dlen, mbsrc, flags, "", NULL);
}
-libbsd_symver_default(strnvis, strnvis_openbsd, LIBBSD_0.2);
+libbsd_symver_default(strnvis_openbsd, strnvis, LIBBSD_0.2);
int
+strnvis_netbsd(char *, size_t, const char *, int);
+int
strnvis_netbsd(char *mbdst, size_t dlen, const char *mbsrc, int flags)
{
return istrsenvisxl(mbdst, &dlen, mbsrc, flags, "", NULL);
}
-libbsd_symver_variant(strnvis, strnvis_netbsd, LIBBSD_0.9.1);
+libbsd_symver_variant(strnvis_netbsd, strnvis, LIBBSD_0.9.1);
int
stravis(char **mbdstp, const char *mbsrc, int flags)
diff --git a/test/.gitignore b/test/.gitignore
index 2c39751..bfd5572 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -2,23 +2,27 @@ arc4random
bzero
closefrom
endian
+explicit_bzero
fgetln
-funopen
fparseln
fpurge
+funopen
headers-overlay-gen.c
headers-system-gen.c
humanize
md5
nlist
overlay
-proctitle-init
proctitle
+proctitle-init
progname
pwcache
setmode
strl
strmode
strnstr
+strtonum
+timeconv32
+timeconv64
vis
vis-openbsd
diff --git a/test/Makefile.am b/test/Makefile.am
index 90fe384..13c3309 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -4,75 +4,190 @@ HEADERS_CPPFLAGS = \
-I$(top_builddir) \
-include $(top_builddir)/config.h \
-DLIBBSD_DISABLE_DEPRECATED \
- -D__REENTRANT
+ -D__REENTRANT \
+ # EOL
AM_CPPFLAGS = \
-isystem $(top_srcdir)/include/bsd/ \
$(HEADERS_CPPFLAGS) \
- -DLIBBSD_OVERLAY
+ -DLIBBSD_OVERLAY \
+ # EOL
AM_TESTS_ENVIRONMENT = \
export CC="$(CC)"; \
export CPPFLAGS="$(HEADERS_CPPFLAGS)"; \
export top_srcdir="$(top_srcdir)"; \
- $(nil)
+ # EOL
LDADD = $(top_builddir)/src/libbsd.la
EXTRA_DIST = \
headers-overlay.sh \
headers-system.sh \
- $(nil)
+ # EOL
check_SCRIPTS = \
headers-overlay.sh \
headers-system.sh \
- $(nil)
+ # EOL
check_PROGRAMS = \
overlay \
- bzero \
- closefrom \
endian \
- humanize \
- fgetln \
- funopen \
- fparseln \
- fpurge \
- md5 \
- nlist \
- proctitle-init \
- progname \
- pwcache \
+ # EOL
+
+if ABI_ACCMODE
+check_PROGRAMS += \
setmode \
- strl \
- strmode \
- strnstr \
- vis \
- vis-openbsd \
- $(nil)
+ # EOL
+endif
+if ABI_ARC4RANDOM
if HAVE_LIBTESTU01
+check_PROGRAMS += arc4random
+
arc4random_LDADD = $(LDADD) $(TESTU01_LIBS)
+endif
+endif
-check_PROGRAMS += arc4random
+if ABI_CLOSEFROM
+check_PROGRAMS += \
+ closefrom \
+ # EOL
+endif
+
+if ABI_EXPLICIT_BZERO
+check_PROGRAMS += \
+ bzero \
+ explicit_bzero \
+ # EOL
+endif
+
+if ABI_FGETLN
+check_PROGRAMS += \
+ fgetln \
+ fparseln \
+ # EOL
+
+fgetln_SOURCES = \
+ test-stream.c \
+ test-stream.h \
+ fgetln.c \
+ # EOL
+
+fgetln_CFLAGS = -Wno-deprecated-declarations
+
+fparseln_SOURCES = \
+ test-stream.c \
+ test-stream.h \
+ fparseln.c \
+ # EOL
+endif
+
+if ABI_FPURGE
+check_PROGRAMS += fpurge
+endif
+
+if ABI_FUNOPEN
+check_PROGRAMS += funopen
+endif
+
+if ABI_HUMANIZE_NUMBER
+check_PROGRAMS += \
+ humanize \
+ # EOL
+endif
+
+if ABI_FPURGE
+check_PROGRAMS += fpurge
+endif
+
+if ABI_FUNOPEN
+check_PROGRAMS += funopen
+endif
+
+if ABI_MD5
+check_PROGRAMS += md5
+
+if ABI_TRANSPARENT_LIBMD
+# On the installed system this is handled via the ld script.
+md5_LDADD = $(LDADD) $(MD5_LIBS)
+endif
endif
+if ABI_NLIST
+check_PROGRAMS += nlist
+endif
+
+if ABI_PROGNAME
+check_PROGRAMS += progname
+endif
+
+if ABI_PROCTITLE
+check_PROGRAMS += \
+ proctitle-init \
+ # EOL
+
+proctitle_init_SOURCES = \
+ proctitle.c \
+ # EOL
+
+proctitle_init_CPPFLAGS = $(AM_CPPFLAGS) -DTEST_USE_SETPROCTITLE_INIT=1
+
if BUILD_LIBBSD_CTOR
+check_PROGRAMS += proctitle
+
proctitle_LDFLAGS = \
-Wl,-u,libbsd_init_func \
$(top_builddir)/src/libbsd-ctor.a \
$(top_builddir)/src/libbsd.la \
- $(nil)
+ # EOL
+endif
+endif
-check_PROGRAMS += proctitle
+if ABI_PWCACHE
+check_PROGRAMS += \
+ pwcache \
+ # EOL
endif
-fgetln_SOURCES = test-stream.c test-stream.h fgetln.c
-fgetln_CFLAGS = -Wno-deprecated-declarations
-fparseln_SOURCES = test-stream.c test-stream.h fparseln.c
+if ABI_PROGNAME
+check_PROGRAMS += progname
+endif
-proctitle_init_SOURCES = proctitle.c
-proctitle_init_CPPFLAGS = $(AM_CPPFLAGS) -DTEST_USE_SETPROCTITLE_INIT=1
+if ABI_STRL
+check_PROGRAMS += strl
+endif
+
+if ABI_STRMODE
+check_PROGRAMS += strmode
+endif
+
+if ABI_STRNSTR
+check_PROGRAMS += \
+ strnstr \
+ # EOL
+endif
+
+if ABI_STRTONUM
+check_PROGRAMS += \
+ strtonum \
+ # EOL
+endif
+
+if ABI_VIS
+check_PROGRAMS += \
+ vis \
+ vis-openbsd \
+ # EOL
+endif
+
+if LIBBSD_SYS_IS_TIME32
+check_PROGRAMS += timeconv32
+endif
+
+if LIBBSD_SYS_HAS_TIME64
+check_PROGRAMS += timeconv64
+endif
TESTS = $(check_SCRIPTS) $(check_PROGRAMS)
diff --git a/test/closefrom.c b/test/closefrom.c
index 160e6b1..f9d74cc 100644
--- a/test/closefrom.c
+++ b/test/closefrom.c
@@ -35,18 +35,46 @@ main(int argc, char *argv[])
{
int i;
int fd;
+ int fd_max;
fd = open("/dev/null", O_RDONLY);
- for (i = 4; i < 1024; i *= 2)
- assert(dup2(fd, i) == i);
+ fd_max = 1024;
+
+ /* First make sure we have a clean fd list. */
+ for (i = 4; i < fd_max; i++)
+ close(i);
+
+ /* Then initialize each even fd. */
+ for (i = 4; i < fd_max; i *= 2) {
+ int fd_new = dup2(fd, i);
+
+ if (fd_new < 0 && (errno == EMFILE || errno == EBADF)) {
+ fd_max = i - 1;
+ break;
+ }
+ assert(fd_new == i);
+ }
if (fd < 4)
close(fd);
closefrom(4);
- for (i = 4; i < 1024; i++)
- assert(fcntl(i, F_GETFL) == -1 && errno == EBADF);
+ for (i = 4; i < fd_max; i++) {
+ int rc;
+
+ errno = 0;
+ rc = fcntl(i, F_GETFD);
+#ifdef __APPLE__
+ /* On macOS we only set close-on-exec. */
+ if ((i & (i - 1)) == 0)
+ assert(rc == FD_CLOEXEC);
+ else
+ assert(rc == -1 && errno == EBADF);
+#else
+ assert(rc == -1 && errno == EBADF);
+#endif
+ }
assert(fcntl(fd, F_GETFL) == -1 && errno == EBADF);
return 0;
diff --git a/test/explicit_bzero.c b/test/explicit_bzero.c
new file mode 100644
index 0000000..031aa42
--- /dev/null
+++ b/test/explicit_bzero.c
@@ -0,0 +1,242 @@
+/* $OpenBSD: explicit_bzero.c,v 1.7 2021/03/27 11:17:58 bcook Exp $ */
+/*
+ * Copyright (c) 2014 Google Inc.
+ * Copyright (c) 2022 Guillem Jover <guillem@hadrons.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define ASSERT_EQ(a, b) assert((a) == (b))
+#define ASSERT_NE(a, b) assert((a) != (b))
+#define ASSERT_GE(a, b) assert((a) >= (b))
+
+#if defined(__has_feature)
+#if __has_feature(address_sanitizer)
+#define __SANITIZE_ADDRESS__
+#endif
+#endif
+#ifdef __SANITIZE_ADDRESS__
+#define ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address))
+#else
+#define ATTRIBUTE_NO_SANITIZE_ADDRESS
+#endif
+
+/* 128 bits of random data. */
+static const char secret[16] = {
+ 0xa0, 0x6c, 0x0c, 0x81, 0xba, 0xd8, 0x5b, 0x0c,
+ 0xb0, 0xd6, 0xd4, 0xe3, 0xeb, 0x52, 0x5f, 0x96,
+};
+
+enum {
+ SECRETCOUNT = 64,
+ SECRETBYTES = SECRETCOUNT * sizeof(secret)
+};
+
+/*
+ * As of glibc 2.34, when _GNU_SOURCE is defined, SIGSTKSZ is no longer
+ * constant on Linux. SIGSTKSZ is redefined to sysconf (_SC_SIGSTKSZ).
+ */
+static char *altstack;
+#define ALTSTACK_SIZE (SIGSTKSZ + SECRETBYTES)
+
+static void
+setup_stack(void)
+{
+ const stack_t sigstk = {
+ .ss_sp = altstack = calloc(1, ALTSTACK_SIZE),
+ .ss_size = ALTSTACK_SIZE
+ };
+
+ ASSERT_NE(NULL, altstack);
+ ASSERT_EQ(0, sigaltstack(&sigstk, NULL));
+}
+
+static void
+cleanup_stack(void)
+{
+ free(altstack);
+}
+
+static void
+assert_on_stack(void)
+{
+ stack_t cursigstk;
+ ASSERT_EQ(0, sigaltstack(NULL, &cursigstk));
+ ASSERT_EQ(SS_ONSTACK, cursigstk.ss_flags & (SS_DISABLE|SS_ONSTACK));
+}
+
+static void
+call_on_stack(void (*fn)(int))
+{
+ /*
+ * This is a bit more complicated than strictly necessary, but
+ * it ensures we don't have any flaky test failures due to
+ * inherited signal masks/actions/etc.
+ *
+ * On systems where SA_ONSTACK is not supported, this could
+ * alternatively be implemented using makecontext() or
+ * pthread_attr_setstack().
+ */
+
+ const struct sigaction sigact = {
+ .sa_handler = fn,
+ .sa_flags = SA_ONSTACK,
+ };
+ struct sigaction oldsigact;
+ sigset_t sigset, oldsigset;
+
+ /* First, block all signals. */
+ ASSERT_EQ(0, sigemptyset(&sigset));
+ ASSERT_EQ(0, sigfillset(&sigset));
+ ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &sigset, &oldsigset));
+
+ /* Next setup the signal handler for SIGUSR1. */
+ ASSERT_EQ(0, sigaction(SIGUSR1, &sigact, &oldsigact));
+
+ /* Raise SIGUSR1 and momentarily unblock it to run the handler. */
+ ASSERT_EQ(0, raise(SIGUSR1));
+ ASSERT_EQ(0, sigdelset(&sigset, SIGUSR1));
+ ASSERT_EQ(-1, sigsuspend(&sigset));
+ ASSERT_EQ(EINTR, errno);
+
+ /* Restore the original signal action, stack, and mask. */
+ ASSERT_EQ(0, sigaction(SIGUSR1, &oldsigact, NULL));
+ ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &oldsigset, NULL));
+}
+
+static void
+populate_secret(char *buf, ssize_t len)
+{
+ int i, fds[2];
+ ASSERT_EQ(0, pipe(fds));
+
+ for (i = 0; i < SECRETCOUNT; i++)
+ ASSERT_EQ(sizeof(secret), write(fds[1], secret, sizeof(secret)));
+ ASSERT_EQ(0, close(fds[1]));
+
+ ASSERT_EQ(len, read(fds[0], buf, len));
+ ASSERT_EQ(0, close(fds[0]));
+}
+
+static void __attribute__((__noinline__))
+blank_stack_side_effects(char *buf, size_t len)
+{
+#if defined(__GNU__) && !defined(__SANITIZE_ADDRESS__)
+ char scratch[SECRETBYTES * 4];
+
+ /* If the read(3) in populate_secret() wrote into the stack, as it
+ * might happen on the Hurd for small data, then we might incorrectly
+ * detect the wrong secret on the stack. */
+ memset(scratch, 0xFF, sizeof(scratch));
+ ASSERT_EQ(NULL, memmem(scratch, sizeof(scratch), buf, len));
+#endif
+}
+
+static int
+count_secrets(const char *buf)
+{
+ int res = 0;
+ size_t i;
+ for (i = 0; i < SECRETCOUNT; i++) {
+ if (memcmp(buf + i * sizeof(secret), secret,
+ sizeof(secret)) == 0)
+ res += 1;
+ }
+ return (res);
+}
+
+ATTRIBUTE_NO_SANITIZE_ADDRESS static char *
+test_without_bzero(void)
+{
+ char buf[SECRETBYTES];
+ char *res;
+ assert_on_stack();
+ populate_secret(buf, sizeof(buf));
+ blank_stack_side_effects(buf, sizeof(buf));
+ res = memmem(altstack, ALTSTACK_SIZE, buf, sizeof(buf));
+ ASSERT_NE(NULL, res);
+ return (res);
+}
+
+ATTRIBUTE_NO_SANITIZE_ADDRESS static char *
+test_with_bzero(void)
+{
+ char buf[SECRETBYTES];
+ char *res;
+ assert_on_stack();
+ populate_secret(buf, sizeof(buf));
+ blank_stack_side_effects(buf, sizeof(buf));
+ res = memmem(altstack, ALTSTACK_SIZE, buf, sizeof(buf));
+ ASSERT_NE(NULL, res);
+ explicit_bzero(buf, sizeof(buf));
+ return (res);
+}
+
+static void
+do_test_without_bzero(int signo)
+{
+ char *buf = test_without_bzero();
+ ASSERT_GE(count_secrets(buf), 1);
+}
+
+static void
+do_test_with_bzero(int signo)
+{
+ char *buf = test_with_bzero();
+ ASSERT_EQ(count_secrets(buf), 0);
+}
+
+int
+main(int argc, char **argv)
+{
+ setup_stack();
+
+ /*
+ * Solaris and OS X clobber the signal stack after returning to the
+ * normal stack, so we need to inspect altstack while we're still
+ * running on it. Unfortunately, this means we risk clobbering the
+ * buffer ourselves.
+ *
+ * To minimize this risk, test_with{,out}_bzero() are responsible for
+ * locating the offset of their buf variable within altstack, and
+ * and returning that address. Then we can simply memcmp() repeatedly
+ * to count how many instances of secret we found.
+ */
+
+ /*
+ * First, test that if we *don't* call explicit_bzero, that we
+ * *are* able to find at least one instance of the secret data still
+ * on the stack. This sanity checks that call_on_stack() and
+ * populate_secret() work as intended.
+ */
+ memset(altstack, 0, ALTSTACK_SIZE);
+ call_on_stack(do_test_without_bzero);
+
+ /*
+ * Now test with a call to explicit_bzero() and check that we
+ * *don't* find any instances of the secret data.
+ */
+ memset(altstack, 0, ALTSTACK_SIZE);
+ call_on_stack(do_test_with_bzero);
+
+ cleanup_stack();
+
+ return (0);
+}
diff --git a/test/fgetln.c b/test/fgetln.c
index d08fb3b..e137fe7 100644
--- a/test/fgetln.c
+++ b/test/fgetln.c
@@ -75,7 +75,7 @@ test_fgetln_single(void)
size_t len;
int i;
- fp = pipe_feed("%s", (const void **)data_ascii, DATA_LINES);
+ fp = pipe_feed(PIPE_DATA_ASCII, (const void **)data_ascii, DATA_LINES);
for (i = 0; i < DATA_LINES; i++) {
char *str = fgetln(fp, &len);
@@ -96,13 +96,14 @@ test_fgetln_multi(void)
char *str;
str = strdup("A\n");
+ assert(str);
str[0] += i;
files[i].line_alloc = str;
files[i].lines = reallocarray(NULL, LINE_COUNT, sizeof(char *));
files[i].lines[0] = str;
files[i].lines[1] = str;
- files[i].fp = pipe_feed("%s", files[i].lines, LINE_COUNT);
+ files[i].fp = pipe_feed(PIPE_DATA_ASCII, files[i].lines, LINE_COUNT);
}
for (l = 0; l < LINE_COUNT; l++) {
@@ -139,7 +140,7 @@ test_fgetwln_single(void)
size_t len;
int i;
- fp = pipe_feed("%ls", (const void **)data_wide, DATA_LINES);
+ fp = pipe_feed(PIPE_DATA_WIDE, (const void **)data_wide, DATA_LINES);
for (i = 0; i < DATA_LINES; i++) {
wchar_t *wstr;
@@ -168,7 +169,7 @@ test_fgetwln_multi(void)
files[i].lines = reallocarray(NULL, LINE_COUNT, sizeof(char *));
files[i].lines[0] = wstr;
files[i].lines[1] = wstr;
- files[i].fp = pipe_feed("%ls", files[i].lines, LINE_COUNT);
+ files[i].fp = pipe_feed(PIPE_DATA_WIDE, files[i].lines, LINE_COUNT);
}
for (l = 0; l < LINE_COUNT; l++) {
diff --git a/test/fparseln.c b/test/fparseln.c
index daff6bd..5d7898d 100644
--- a/test/fparseln.c
+++ b/test/fparseln.c
@@ -68,7 +68,7 @@ test_fparseln(const char **data_expect, int flags)
FILE *fp;
size_t i, len, lineno = 0;
- fp = pipe_feed("%s", (const void **)data_test, TEST_LINES);
+ fp = pipe_feed(PIPE_DATA_ASCII, (const void **)data_test, TEST_LINES);
for (i = 0; i < EXPECT_LINES; i++) {
char *str = fparseln(fp, &len, &lineno, NULL, flags);
diff --git a/test/fpurge.c b/test/fpurge.c
index a99cff7..784f32e 100644
--- a/test/fpurge.c
+++ b/test/fpurge.c
@@ -25,24 +25,51 @@
*/
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static int
+test_memstream(void)
+{
+ int rc = 0;
+#if HAVE_OPEN_MEMSTREAM
+ FILE *fp;
+ char *buf = NULL;
+ size_t bufsz = 0;
+
+ fp = open_memstream(&buf, &bufsz);
+ if (fp == NULL)
+ return 1;
+
+ fputs("World", fp);
+ if (fpurge(fp) < 0)
+ rc = 1;
+ fflush(fp);
+ if (bufsz != 0)
+ rc = 1;
+
+ fclose(fp);
+ free(buf);
+#endif
+
+ return rc;
+}
int
main(int argc, char *argv[])
{
- static FILE fp_bad;
FILE *fp;
+ int rc;
if (fpurge(NULL) == 0)
return 1;
- if (fpurge(&fp_bad) == 0)
- return 1;
-
fp = fopen("/dev/zero", "r");
if (fpurge(fp) < 0)
return 1;
-
fclose(fp);
- return 0;
+ rc = test_memstream();
+
+ return rc;
}
diff --git a/test/funopen.c b/test/funopen.c
index 2b34f7e..65c493e 100644
--- a/test/funopen.c
+++ b/test/funopen.c
@@ -114,7 +114,7 @@ main(int argc, char **argv)
size_t i;
/* Test invalid hooks. */
- fp = funopen(&tc, NULL, NULL, NULL, NULL);
+ fp = funopen(NULL, NULL, NULL, NULL, NULL);
assert(fp == NULL);
assert(errno == EINVAL);
diff --git a/test/headers-overlay.sh b/test/headers-overlay.sh
index be92eff..176623e 100755
--- a/test/headers-overlay.sh
+++ b/test/headers-overlay.sh
@@ -18,8 +18,9 @@ int main() { return 0; }
SOURCE
echo "testing header $inc"
- run $CC -isystem "$incdir" $CPPFLAGS headers-overlay-gen.c -o /dev/null
+ run $CC -isystem "$incdir" $CPPFLAGS headers-overlay-gen.c -o headers-overlay
echo
+ rm -f headers-overlay
rm -f headers-overlay-gen*
done
diff --git a/test/headers-system.sh b/test/headers-system.sh
index 5ff0517..458fbbb 100755
--- a/test/headers-system.sh
+++ b/test/headers-system.sh
@@ -17,8 +17,9 @@ int main() { return 0; }
SOURCE
echo "testing header $inc"
- run $CC -isystem "$incdir" $CPPFLAGS headers-system-gen.c -o /dev/null
+ run $CC -isystem "$incdir" $CPPFLAGS headers-system-gen.c -o headers-system
echo
+ rm -f headers-system
rm -f headers-system-gen.*
done
diff --git a/test/nlist.c b/test/nlist.c
index 82e24e9..0031a4d 100644
--- a/test/nlist.c
+++ b/test/nlist.c
@@ -33,17 +33,29 @@
#include <fcntl.h>
#include <nlist.h>
+#if defined(__has_attribute)
+#if __has_attribute(__retain__)
+#define ATTRIBUTE_RETAIN __attribute__((__retain__))
+#else
+#define ATTRIBUTE_RETAIN
+#endif
+#endif
+
static int data_prv_init = 50;
extern int data_pub_init;
extern int data_pub_uninit[2048];
extern int *data_pub_ptr;
+/* GCC's __has_attribute has odd behavior for retain: https://gcc.gnu.org/PR99587 */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wattributes"
int *data_pub_ptr = &data_prv_init;
-int data_pub_init = 10;
-int data_pub_uninit[2048];
+int data_pub_init ATTRIBUTE_RETAIN __attribute__((__used__)) = 10;
+int data_pub_uninit[2048] ATTRIBUTE_RETAIN __attribute__((__used__));
extern int
-func_pub(void);
+func_pub(void) ATTRIBUTE_RETAIN __attribute__((__used__));
+#pragma GCC diagnostic pop
int
func_pub(void)
@@ -55,11 +67,11 @@ int
main(int argc, char **argv)
{
struct nlist nl[] = {
- { .n_un.n_name = "main" },
- { .n_un.n_name = "func_pub" },
- { .n_un.n_name = "data_pub_uninit" },
- { .n_un.n_name = "data_pub_init" },
- { .n_un.n_name = "data_prv_init" },
+ { .n_un.n_name = (char *)"main" },
+ { .n_un.n_name = (char *)"func_pub" },
+ { .n_un.n_name = (char *)"data_pub_uninit" },
+ { .n_un.n_name = (char *)"data_pub_init" },
+ { .n_un.n_name = (char *)"data_prv_init" },
{ .n_un.n_name = NULL },
};
int rc;
diff --git a/test/overlay.c b/test/overlay.c
index d82f14e..af83232 100644
--- a/test/overlay.c
+++ b/test/overlay.c
@@ -28,12 +28,14 @@
* other headers through magic macros, to check that the overlay is working
* properly. */
#include <errno.h>
+#ifndef __APPLE__
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
#ifdef HAVE_GRP_H
#include <grp.h>
#endif
+#endif
#include <stdint.h>
/* Include libbsd overlayed headers that might get partially included. */
diff --git a/test/pwcache.c b/test/pwcache.c
index d68ea4c..458903f 100644
--- a/test/pwcache.c
+++ b/test/pwcache.c
@@ -1,5 +1,5 @@
/*
- * Copyright © 2021 Guillem Jover <guillem@hadrons.org>
+ * Copyright © 2021, 2023 Guillem Jover <guillem@hadrons.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -26,24 +26,50 @@
#include <assert.h>
#include <string.h>
+#include <stdlib.h>
#include <pwd.h>
#include <grp.h>
+#define TEST_SKIP 77
+
int
main(int argc, char **argv)
{
+ struct group *gr;
+ struct passwd *pw;
+ char *uname;
+ char *gname;
uid_t uid;
gid_t gid;
- assert(uid_from_user("root", &uid) == 0);
+ /* Do not hardcode user or group names. */
+ pw = getpwuid(0);
+ if (pw == NULL)
+ return TEST_SKIP;
+ uname = strdup(pw->pw_name);
+ assert(uname != NULL);
+
+ gr = getgrgid(0);
+ if (gr == NULL) {
+ free(uname);
+ return TEST_SKIP;
+ }
+ gname = strdup(gr->gr_name);
+ assert(gname != NULL);
+
+ /* Test the functions. */
+ assert(uid_from_user(uname, &uid) == 0);
assert(uid == 0);
- assert(strcmp(user_from_uid(0, 0), "root") == 0);
+ assert(strcmp(user_from_uid(0, 0), uname) == 0);
- assert(gid_from_group("root", &gid) == 0);
+ assert(gid_from_group(gname, &gid) == 0);
assert(gid == 0);
- assert(strcmp(group_from_gid(0, 0), "root") == 0);
+ assert(strcmp(group_from_gid(0, 0), gname) == 0);
+
+ free(uname);
+ free(gname);
return 0;
}
diff --git a/test/strtonum.c b/test/strtonum.c
new file mode 100644
index 0000000..6dee3da
--- /dev/null
+++ b/test/strtonum.c
@@ -0,0 +1,64 @@
+/* $OpenBSD: strtonumtest.c,v 1.1 2004/08/03 20:38:36 otto Exp $ */
+/*
+ * Copyright (c) 2004 Otto Moerbeek <otto@drijf.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static int fail;
+
+static void
+test(const char *p, long long lb, long long ub, int ok)
+{
+ long long val;
+ const char *q;
+
+ val = strtonum(p, lb, ub, &q);
+ if (ok && q != NULL) {
+ fprintf(stderr, "%s [%lld-%lld] ", p, lb, ub);
+ fprintf(stderr, "NUMBER NOT ACCEPTED %s\n", q);
+ fail = 1;
+ } else if (!ok && q == NULL) {
+ fprintf(stderr, "%s [%lld-%lld] %lld ", p, lb, ub, val);
+ fprintf(stderr, "NUMBER ACCEPTED\n");
+ fail = 1;
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ test("1", 0, 10, 1);
+ test("0", -2, 5, 1);
+ test("0", 2, 5, 0);
+ test("0", 2, LLONG_MAX, 0);
+ test("-2", 0, LLONG_MAX, 0);
+ test("0", -5, LLONG_MAX, 1);
+ test("-3", -3, LLONG_MAX, 1);
+ test("-9223372036854775808", LLONG_MIN, LLONG_MAX, 1);
+ test("9223372036854775807", LLONG_MIN, LLONG_MAX, 1);
+ test("-9223372036854775809", LLONG_MIN, LLONG_MAX, 0);
+ test("9223372036854775808", LLONG_MIN, LLONG_MAX, 0);
+ test("1000000000000000000000000", LLONG_MIN, LLONG_MAX, 0);
+ test("-1000000000000000000000000", LLONG_MIN, LLONG_MAX, 0);
+ test("-2", 10, -1, 0);
+ test("-2", -10, -1, 1);
+ test("-20", -10, -1, 0);
+ test("20", -10, -1, 0);
+
+ return (fail);
+}
+
diff --git a/test/test-stream.c b/test/test-stream.c
index 849f419..0bbb641 100644
--- a/test/test-stream.c
+++ b/test/test-stream.c
@@ -27,12 +27,13 @@
#include <sys/wait.h>
#include <assert.h>
#include <unistd.h>
+#include <wchar.h>
#include <stdio.h>
#include "test-stream.h"
FILE *
-pipe_feed(const char *fmt, const void **buf, int buf_nmemb)
+pipe_feed(enum pipe_data_mode mode, const void **buf, int buf_nmemb)
{
FILE *fp;
int rc;
@@ -56,7 +57,10 @@ pipe_feed(const char *fmt, const void **buf, int buf_nmemb)
assert(fp);
for (line = 0; line < buf_nmemb; line++) {
- rc = fprintf(fp, fmt, buf[line]);
+ if (mode == PIPE_DATA_ASCII)
+ rc = fprintf(fp, "%s", (const char *)buf[line]);
+ else
+ rc = fprintf(fp, "%ls", (const wchar_t *)buf[line]);
assert(rc >= 0);
}
diff --git a/test/test-stream.h b/test/test-stream.h
index cee4e60..8caf3fc 100644
--- a/test/test-stream.h
+++ b/test/test-stream.h
@@ -29,8 +29,13 @@
#include <stdio.h>
+enum pipe_data_mode {
+ PIPE_DATA_ASCII,
+ PIPE_DATA_WIDE,
+};
+
FILE *
-pipe_feed(const char *fmt, const void **buf, int buf_nmemb);
+pipe_feed(enum pipe_data_mode mode, const void **buf, int buf_nmemb);
void
pipe_close(FILE *fp);
diff --git a/test/timeconv32.c b/test/timeconv32.c
new file mode 100644
index 0000000..549e612
--- /dev/null
+++ b/test/timeconv32.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright © 2024 Guillem Jover <guillem@hadrons.org>
+ *
+ * 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 author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``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 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.
+ */
+
+#undef _TIME_BITS
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <timeconv.h>
+
+int
+main(int argc, char **argv)
+{
+ time_t t;
+
+ t = _time64_to_time(INT64_MAX);
+ assert(t < INT64_MAX);
+
+ return 0;
+}
diff --git a/test/timeconv64.c b/test/timeconv64.c
new file mode 100644
index 0000000..d175ed2
--- /dev/null
+++ b/test/timeconv64.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright © 2024 Guillem Jover <guillem@hadrons.org>
+ *
+ * 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 author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``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 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 <assert.h>
+#include <stdint.h>
+#include <timeconv.h>
+
+int
+main(int argc, char **argv)
+{
+ time_t t;
+
+ t = _time64_to_time(INT64_MAX);
+ assert(t == INT64_MAX);
+
+ return 0;
+}