[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#1032977: marked as done (unblock: apache2/2.4.56-1)



Your message dated Sat, 18 Mar 2023 15:03:09 +0000
with message-id <E1pdY5N-000Mip-54@respighi.debian.org>
and subject line unblock apache2
has caused the Debian Bug report #1032977,
regarding unblock: apache2/2.4.56-1
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact owner@bugs.debian.org
immediately.)


-- 
1032977: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1032977
Debian Bug Tracking System
Contact owner@bugs.debian.org with problems
--- Begin Message ---
Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: unblock
X-Debbugs-Cc: apache2@packages.debian.org
Control: affects -1 + src:apache2

Please unblock package apache2

[ Reason ]
Apache2 < 2.4.56 is vulnerable to 2 CVE, the major is CVE-2023-25690
(bypass access control using HTTP Request Smuggling attack)

[ Impact ]
Major security issue

[ Tests ]
Test updated, passed

[ Risks ]
Low risk, patch is not so big (attached debdiff ignores doc changes)

[ Checklist ]
  [X] all changes are documented in the d/changelog
  [X] I reviewed all changes and I approve them
  [X] attach debdiff against the package in testing

unblock apache2/2.4.56-1
diff --git a/CHANGES b/CHANGES
index c58c6fef..16f8f55d 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,64 @@
                                                          -*- coding: utf-8 -*-
+Changes with Apache 2.4.56
+
+  *) rotatelogs: Add -T flag to allow subsequent rotated logfiles to be
+     truncated without the initial logfile being truncated.  [Eric Covener]
+
+  *) mod_ldap: LDAPConnectionPoolTTL should accept negative values in order to
+     allow connections of any age to be reused. Up to now, a negative value
+     was handled as an error when parsing the configuration file.  PR 66421.
+     [nailyk <bzapache nailyk.fr>, Christophe Jaillet]
+
+  *) mod_proxy_ajp: Report an error if the AJP backend sends an invalid number
+     of headers. [Ruediger Pluem]
+
+  *) mod_md:
+     - Enabling ED25519 support and certificate transparency information when
+       building with libressl v3.5.0 and newer. Thanks to Giovanni Bechis.
+     - MDChallengeDns01 can now be configured for individual domains.
+       Thanks to Jérôme Billiras (@bilhackmac) for the initial PR.
+     - Fixed a bug found by Jérôme Billiras (@bilhackmac) that caused the challenge
+       teardown not being invoked as it should.
+     [Stefan Eissing]
+
+  *) mod_http2: client resets of HTTP/2 streams led to unwanted 500 errors
+     reported in access logs and error documents. The processing of the
+     reset was correct, only unneccesary reporting was caused.
+     [Stefan Eissing]
+
+  *) mod_proxy_uwsgi: Stricter backend HTTP response parsing/validation.
+     [Yann Ylavic]
+
 Changes with Apache 2.4.55
 
+  *) SECURITY: CVE-2022-37436: Apache HTTP Server: mod_proxy prior to
+     2.4.55 allows a backend to trigger HTTP response splitting
+     (cve.mitre.org)
+     Prior to Apache HTTP Server 2.4.55, a malicious backend can
+     cause the response headers to be truncated early, resulting in
+     some headers being incorporated into the response body. If the
+     later headers have any security purpose, they will not be
+     interpreted by the client.
+     Credits: Dimas Fariski Setyawan Putra (@nyxsorcerer)
+
+  *) SECURITY: CVE-2022-36760: Apache HTTP Server: mod_proxy_ajp
+     Possible request smuggling (cve.mitre.org)
+     Inconsistent Interpretation of HTTP Requests ('HTTP Request
+     Smuggling') vulnerability in mod_proxy_ajp of Apache HTTP Server
+     allows an attacker to smuggle requests to the AJP server it
+     forwards requests to.  This issue affects Apache HTTP Server
+     Apache HTTP Server 2.4 version 2.4.54 and prior versions.
+     Credits: ZeddYu_Lu from Qi'anxin Research Institute of Legendsec
+     at Qi'anxin Group
+
+  *) SECURITY: CVE-2006-20001: mod_dav out of  bounds read, or write
+     of zero byte (cve.mitre.org)
+     A carefully crafted If: request header can cause a memory read,
+     or write of a single zero byte, in a pool (heap) memory location
+     beyond the header value sent. This could cause the process to
+     crash.
+     This issue affects Apache HTTP Server 2.4.54 and earlier.
+
   *) mod_dav: Open the lock database read-only when possible.
      PR 36636 [Wilson Felipe <wfelipe gmail.com>, manu]
 
@@ -15,7 +73,7 @@ Changes with Apache 2.4.55
 
   *) mod_proxy_hcheck: Honor worker timeout settings.  [Yann Ylavic]
 
-  *) mod_http2: version 2.0.10 of the module, synchronizing changes
+  *) mod_http2: version 2.0.11 of the module, synchronizing changes
      with the gitgub version. This is a partial rewrite of how connections
      and streams are handled.
      - an APR pollset and pipes (where supported) are used to monitor
diff --git a/README b/README
index 60337442..f1f6d78c 100644
--- a/README
+++ b/README
@@ -16,7 +16,7 @@
   ------------------
 
   Details of the latest version can be found on the Apache HTTP
-  server project page under http://httpd.apache.org/.
+  server project page under https://httpd.apache.org/.
 
   Documentation
   -------------
@@ -24,7 +24,7 @@
   The documentation available as of the date of this release is
   included in HTML format in the docs/manual/ directory.  The most
   up-to-date documentation can be found at
-  http://httpd.apache.org/docs/2.4/.
+  https://httpd.apache.org/docs/2.4/.
 
   Installation
   ------------
@@ -46,7 +46,7 @@
   to another country, of encryption software.  BEFORE using any encryption
   software, please check your country's laws, regulations and policies
   concerning the import, possession, or use, and re-export of encryption
-  software, to see if this is permitted.  See <http://www.wassenaar.org/>
+  software, to see if this is permitted.  See <https://www.wassenaar.org/>
   for more information.
 
   The U.S. Government Department of Commerce, Bureau of Industry and
@@ -82,7 +82,7 @@
     Some object code distributions of Apache httpd, indicated with the
     word "crypto" in the package name, may include object code for the
     OpenSSL encryption library as distributed in open source form from
-    <http://www.openssl.org/source/>.
+    <https://www.openssl.org/source/>.
 
   The above files are optional and may be removed if the cryptographic
   functionality is not desired or needs to be excluded from redistribution.
@@ -96,15 +96,15 @@
      o If you want to be informed about new code releases, bug fixes,
        security fixes, general news and information about the Apache server
        subscribe to the apache-announce mailing list as described under
-       <http://httpd.apache.org/lists.html#http-announce>
+       <https://httpd.apache.org/lists.html#http-announce>
 
      o If you want freely available support for running Apache please see the
-       resources at <http://httpd.apache.org/support.html>
+       resources at <https://httpd.apache.org/support.html>
 
      o If you have a concrete bug report for Apache please see the instructions
-       for bug reporting at <http://httpd.apache.org/bug_report.html>
+       for bug reporting at <https://httpd.apache.org/bug_report.html>
 
      o If you want to participate in actively developing Apache please
        subscribe to the `dev@httpd.apache.org' mailing list as described at
-       <http://httpd.apache.org/lists.html#http-dev>
+       <https://httpd.apache.org/lists.html#http-dev>
 
diff --git a/build/apr_common.m4 b/build/apr_common.m4
index f4e2dfd0..ac2312c6 100644
--- a/build/apr_common.m4
+++ b/build/apr_common.m4
@@ -451,43 +451,6 @@ fi
 ])
 
 
-dnl
-dnl APR_CHECK_SIZEOF_EXTENDED(INCLUDES, TYPE [, CROSS_SIZE])
-dnl
-dnl A variant of AC_CHECK_SIZEOF which allows the checking of
-dnl sizes of non-builtin types
-dnl
-AC_DEFUN([APR_CHECK_SIZEOF_EXTENDED],
-[changequote(<<, >>)dnl
-dnl The name to #define.
-define(<<AC_TYPE_NAME>>, translit(sizeof_$2, [a-z *], [A-Z_P]))dnl
-dnl The cache variable name.
-define(<<AC_CV_NAME>>, translit(ac_cv_sizeof_$2, [ *], [_p]))dnl
-changequote([, ])dnl
-AC_MSG_CHECKING(size of $2)
-AC_CACHE_VAL(AC_CV_NAME,
-[AC_TRY_RUN([#include <stdio.h>
-$1
-#ifdef WIN32
-#define binmode "b"
-#else
-#define binmode
-#endif
-main()
-{
-  FILE *f=fopen("conftestval", "w" binmode);
-  if (!f) exit(1);
-  fprintf(f, "%d\n", sizeof($2));
-  exit(0);
-}], AC_CV_NAME=`cat conftestval`, AC_CV_NAME=0, ifelse([$3],,,
-AC_CV_NAME=$3))])dnl
-AC_MSG_RESULT($AC_CV_NAME)
-AC_DEFINE_UNQUOTED(AC_TYPE_NAME, $AC_CV_NAME, [The size of ]$2)
-undefine([AC_TYPE_NAME])dnl
-undefine([AC_CV_NAME])dnl
-])
-
-
 dnl
 dnl APR_TRY_COMPILE_NO_WARNING(INCLUDES, FUNCTION-BODY,
 dnl             [ACTIONS-IF-NO-WARNINGS], [ACTIONS-IF-WARNINGS])
@@ -505,7 +468,10 @@ AC_DEFUN([APR_TRY_COMPILE_NO_WARNING],
  fi
  AC_COMPILE_IFELSE(
   [AC_LANG_SOURCE(
-   [#include "confdefs.h"
+   [
+#ifndef PACKAGE_NAME
+#include "confdefs.h"
+#endif
    ]
    [[$1]]
    [int main(int argc, const char *const *argv) {]
@@ -526,12 +492,14 @@ dnl  string.
 dnl
 dnl
 AC_DEFUN([APR_CHECK_STRERROR_R_RC], [
-AC_MSG_CHECKING(for type of return code from strerror_r)
-AC_TRY_RUN([
+AC_CACHE_CHECK([whether return code from strerror_r has type int],
+[ac_cv_strerror_r_rc_int],
+[AC_TRY_RUN([
 #include <errno.h>
 #include <string.h>
 #include <stdio.h>
-main()
+#include <stdlib.h>
+int main(void)
 {
   char buf[1024];
   if (strerror_r(ERANGE, buf, sizeof buf) < 1) {
@@ -543,14 +511,10 @@ main()
 }], [
     ac_cv_strerror_r_rc_int=yes ], [
     ac_cv_strerror_r_rc_int=no ], [
-    ac_cv_strerror_r_rc_int=no ] )
+    ac_cv_strerror_r_rc_int=no ] ) ] )
 if test "x$ac_cv_strerror_r_rc_int" = xyes; then
   AC_DEFINE(STRERROR_R_RC_INT, 1, [Define if strerror returns int])
-  msg="int"
-else
-  msg="pointer"
 fi
-AC_MSG_RESULT([$msg])
 ] )
 
 dnl
diff --git a/build/config.guess b/build/config.guess
index 0f9b29c8..e81d3ae7 100755
--- a/build/config.guess
+++ b/build/config.guess
@@ -1,8 +1,10 @@
 #! /bin/sh
 # Attempt to guess a canonical system name.
-#   Copyright 1992-2019 Free Software Foundation, Inc.
+#   Copyright 1992-2021 Free Software Foundation, Inc.
 
-timestamp='2019-01-01'
+# shellcheck disable=SC2006,SC2268 # see below for rationale
+
+timestamp='2021-06-03'
 
 # This file is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
@@ -27,11 +29,19 @@ timestamp='2019-01-01'
 # Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
 #
 # You can get the latest version of this script from:
-# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
+# https://git.savannah.gnu.org/cgit/config.git/plain/config.guess
 #
 # Please send patches to <config-patches@gnu.org>.
 
 
+# The "shellcheck disable" line above the timestamp inhibits complaints
+# about features and limitations of the classic Bourne shell that were
+# superseded or lifted in POSIX.  However, this script identifies a wide
+# variety of pre-POSIX systems that do not have POSIX shells at all, and
+# even some reasonably current systems (Solaris 10 as case-in-point) still
+# have a pre-POSIX /bin/sh.
+
+
 me=`echo "$0" | sed -e 's,.*/,,'`
 
 usage="\
@@ -50,7 +60,7 @@ version="\
 GNU config.guess ($timestamp)
 
 Originally written by Per Bothner.
-Copyright 1992-2019 Free Software Foundation, Inc.
+Copyright 1992-2021 Free Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -84,6 +94,9 @@ if test $# != 0; then
   exit 1
 fi
 
+# Just in case it came from the environment.
+GUESS=
+
 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a
 # compiler to aid in system detection is discouraged as it requires
 # temporary files to be created and, as you can see below, it is a
@@ -99,8 +112,10 @@ tmp=
 trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15
 
 set_cc_for_build() {
+    # prevent multiple calls if $tmp is already set
+    test "$tmp" && return 0
     : "${TMPDIR=/tmp}"
-    # shellcheck disable=SC2039
+    # shellcheck disable=SC2039,SC3028
     { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
 	{ test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } ||
 	{ tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } ||
@@ -110,7 +125,7 @@ set_cc_for_build() {
 	,,)    echo "int x;" > "$dummy.c"
 	       for driver in cc gcc c89 c99 ; do
 		   if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then
-		       CC_FOR_BUILD="$driver"
+		       CC_FOR_BUILD=$driver
 		       break
 		   fi
 	       done
@@ -131,14 +146,12 @@ fi
 
 UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
 UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
-UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
 UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
 
-case "$UNAME_SYSTEM" in
+case $UNAME_SYSTEM in
 Linux|GNU|GNU/*)
-	# If the system lacks a compiler, then just pick glibc.
-	# We could probably try harder.
-	LIBC=gnu
+	LIBC=unknown
 
 	set_cc_for_build
 	cat <<-EOF > "$dummy.c"
@@ -147,24 +160,37 @@ Linux|GNU|GNU/*)
 	LIBC=uclibc
 	#elif defined(__dietlibc__)
 	LIBC=dietlibc
-	#else
+	#elif defined(__GLIBC__)
 	LIBC=gnu
+	#else
+	#include <stdarg.h>
+	/* First heuristic to detect musl libc.  */
+	#ifdef __DEFINED_va_list
+	LIBC=musl
+	#endif
 	#endif
 	EOF
-	eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`"
+	cc_set_libc=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
+	eval "$cc_set_libc"
 
-	# If ldd exists, use it to detect musl libc.
-	if command -v ldd >/dev/null && \
-		ldd --version 2>&1 | grep -q ^musl
-	then
-	    LIBC=musl
+	# Second heuristic to detect musl libc.
+	if [ "$LIBC" = unknown ] &&
+	   command -v ldd >/dev/null &&
+	   ldd --version 2>&1 | grep -q ^musl; then
+		LIBC=musl
+	fi
+
+	# If the system lacks a compiler, then just pick glibc.
+	# We could probably try harder.
+	if [ "$LIBC" = unknown ]; then
+		LIBC=gnu
 	fi
 	;;
 esac
 
 # Note: order is significant - the case branches are not exclusive.
 
-case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
+case $UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION in
     *:NetBSD:*:*)
 	# NetBSD (nbsd) targets should (where applicable) match one or
 	# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
@@ -176,12 +202,12 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
 	#
 	# Note: NetBSD doesn't particularly care about the vendor
 	# portion of the name.  We always set it to "unknown".
-	sysctl="sysctl -n hw.machine_arch"
 	UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
-	    "/sbin/$sysctl" 2>/dev/null || \
-	    "/usr/sbin/$sysctl" 2>/dev/null || \
+	    /sbin/sysctl -n hw.machine_arch 2>/dev/null || \
+	    /usr/sbin/sysctl -n hw.machine_arch 2>/dev/null || \
 	    echo unknown)`
-	case "$UNAME_MACHINE_ARCH" in
+	case $UNAME_MACHINE_ARCH in
+	    aarch64eb) machine=aarch64_be-unknown ;;
 	    armeb) machine=armeb-unknown ;;
 	    arm*) machine=arm-unknown ;;
 	    sh3el) machine=shl-unknown ;;
@@ -190,13 +216,13 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
 	    earmv*)
 		arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
 		endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'`
-		machine="${arch}${endian}"-unknown
+		machine=${arch}${endian}-unknown
 		;;
-	    *) machine="$UNAME_MACHINE_ARCH"-unknown ;;
+	    *) machine=$UNAME_MACHINE_ARCH-unknown ;;
 	esac
 	# The Operating System including object format, if it has switched
 	# to ELF recently (or will in the future) and ABI.
-	case "$UNAME_MACHINE_ARCH" in
+	case $UNAME_MACHINE_ARCH in
 	    earm*)
 		os=netbsdelf
 		;;
@@ -217,7 +243,7 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
 		;;
 	esac
 	# Determine ABI tags.
-	case "$UNAME_MACHINE_ARCH" in
+	case $UNAME_MACHINE_ARCH in
 	    earm*)
 		expr='s/^earmv[0-9]/-eabi/;s/eb$//'
 		abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"`
@@ -228,7 +254,7 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
 	# thus, need a distinct triplet. However, they do not need
 	# kernel version information, so it can be replaced with a
 	# suitable tag, in the style of linux-gnu.
-	case "$UNAME_VERSION" in
+	case $UNAME_VERSION in
 	    Debian*)
 		release='-gnu'
 		;;
@@ -239,45 +265,57 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
 	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
 	# contains redundant information, the shorter form:
 	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
-	echo "$machine-${os}${release}${abi-}"
-	exit ;;
+	GUESS=$machine-${os}${release}${abi-}
+	;;
     *:Bitrig:*:*)
 	UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
-	echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE"
-	exit ;;
+	GUESS=$UNAME_MACHINE_ARCH-unknown-bitrig$UNAME_RELEASE
+	;;
     *:OpenBSD:*:*)
 	UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
-	echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE"
-	exit ;;
+	GUESS=$UNAME_MACHINE_ARCH-unknown-openbsd$UNAME_RELEASE
+	;;
+    *:SecBSD:*:*)
+	UNAME_MACHINE_ARCH=`arch | sed 's/SecBSD.//'`
+	GUESS=$UNAME_MACHINE_ARCH-unknown-secbsd$UNAME_RELEASE
+	;;
     *:LibertyBSD:*:*)
 	UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
-	echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE"
-	exit ;;
+	GUESS=$UNAME_MACHINE_ARCH-unknown-libertybsd$UNAME_RELEASE
+	;;
     *:MidnightBSD:*:*)
-	echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE"
-	exit ;;
+	GUESS=$UNAME_MACHINE-unknown-midnightbsd$UNAME_RELEASE
+	;;
     *:ekkoBSD:*:*)
-	echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE"
-	exit ;;
+	GUESS=$UNAME_MACHINE-unknown-ekkobsd$UNAME_RELEASE
+	;;
     *:SolidBSD:*:*)
-	echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE"
-	exit ;;
+	GUESS=$UNAME_MACHINE-unknown-solidbsd$UNAME_RELEASE
+	;;
+    *:OS108:*:*)
+	GUESS=$UNAME_MACHINE-unknown-os108_$UNAME_RELEASE
+	;;
     macppc:MirBSD:*:*)
-	echo powerpc-unknown-mirbsd"$UNAME_RELEASE"
-	exit ;;
+	GUESS=powerpc-unknown-mirbsd$UNAME_RELEASE
+	;;
     *:MirBSD:*:*)
-	echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE"
-	exit ;;
+	GUESS=$UNAME_MACHINE-unknown-mirbsd$UNAME_RELEASE
+	;;
     *:Sortix:*:*)
-	echo "$UNAME_MACHINE"-unknown-sortix
-	exit ;;
+	GUESS=$UNAME_MACHINE-unknown-sortix
+	;;
+    *:Twizzler:*:*)
+	GUESS=$UNAME_MACHINE-unknown-twizzler
+	;;
     *:Redox:*:*)
-	echo "$UNAME_MACHINE"-unknown-redox
-	exit ;;
+	GUESS=$UNAME_MACHINE-unknown-redox
+	;;
     mips:OSF1:*.*)
-        echo mips-dec-osf1
-        exit ;;
+	GUESS=mips-dec-osf1
+	;;
     alpha:OSF1:*:*)
+	# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
+	trap '' 0
 	case $UNAME_RELEASE in
 	*4.0)
 		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
@@ -291,7 +329,7 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
 	# covers most systems running today.  This code pipes the CPU
 	# types through head -n 1, so we only detect the type of CPU 0.
 	ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
-	case "$ALPHA_CPU_TYPE" in
+	case $ALPHA_CPU_TYPE in
 	    "EV4 (21064)")
 		UNAME_MACHINE=alpha ;;
 	    "EV4.5 (21064)")
@@ -328,75 +366,76 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
 	# A Tn.n version is a released field test version.
 	# A Xn.n version is an unreleased experimental baselevel.
 	# 1.2 uses "1.2" for uname -r.
-	echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`"
-	# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
-	exitcode=$?
-	trap '' 0
-	exit $exitcode ;;
+	OSF_REL=`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+	GUESS=$UNAME_MACHINE-dec-osf$OSF_REL
+	;;
     Amiga*:UNIX_System_V:4.0:*)
-	echo m68k-unknown-sysv4
-	exit ;;
+	GUESS=m68k-unknown-sysv4
+	;;
     *:[Aa]miga[Oo][Ss]:*:*)
-	echo "$UNAME_MACHINE"-unknown-amigaos
-	exit ;;
+	GUESS=$UNAME_MACHINE-unknown-amigaos
+	;;
     *:[Mm]orph[Oo][Ss]:*:*)
-	echo "$UNAME_MACHINE"-unknown-morphos
-	exit ;;
+	GUESS=$UNAME_MACHINE-unknown-morphos
+	;;
     *:OS/390:*:*)
-	echo i370-ibm-openedition
-	exit ;;
+	GUESS=i370-ibm-openedition
+	;;
     *:z/VM:*:*)
-	echo s390-ibm-zvmoe
-	exit ;;
+	GUESS=s390-ibm-zvmoe
+	;;
     *:OS400:*:*)
-	echo powerpc-ibm-os400
-	exit ;;
+	GUESS=powerpc-ibm-os400
+	;;
     arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
-	echo arm-acorn-riscix"$UNAME_RELEASE"
-	exit ;;
+	GUESS=arm-acorn-riscix$UNAME_RELEASE
+	;;
     arm*:riscos:*:*|arm*:RISCOS:*:*)
-	echo arm-unknown-riscos
-	exit ;;
+	GUESS=arm-unknown-riscos
+	;;
     SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
-	echo hppa1.1-hitachi-hiuxmpp
-	exit ;;
+	GUESS=hppa1.1-hitachi-hiuxmpp
+	;;
     Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
 	# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
-	if test "`(/bin/universe) 2>/dev/null`" = att ; then
-		echo pyramid-pyramid-sysv3
-	else
-		echo pyramid-pyramid-bsd
-	fi
-	exit ;;
+	case `(/bin/universe) 2>/dev/null` in
+	    att) GUESS=pyramid-pyramid-sysv3 ;;
+	    *)   GUESS=pyramid-pyramid-bsd   ;;
+	esac
+	;;
     NILE*:*:*:dcosx)
-	echo pyramid-pyramid-svr4
-	exit ;;
+	GUESS=pyramid-pyramid-svr4
+	;;
     DRS?6000:unix:4.0:6*)
-	echo sparc-icl-nx6
-	exit ;;
+	GUESS=sparc-icl-nx6
+	;;
     DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
 	case `/usr/bin/uname -p` in
-	    sparc) echo sparc-icl-nx7; exit ;;
-	esac ;;
+	    sparc) GUESS=sparc-icl-nx7 ;;
+	esac
+	;;
     s390x:SunOS:*:*)
-	echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`"
-	exit ;;
+	SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+	GUESS=$UNAME_MACHINE-ibm-solaris2$SUN_REL
+	;;
     sun4H:SunOS:5.*:*)
-	echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
-	exit ;;
+	SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+	GUESS=sparc-hal-solaris2$SUN_REL
+	;;
     sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
-	echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`"
-	exit ;;
+	SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+	GUESS=sparc-sun-solaris2$SUN_REL
+	;;
     i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
-	echo i386-pc-auroraux"$UNAME_RELEASE"
-	exit ;;
+	GUESS=i386-pc-auroraux$UNAME_RELEASE
+	;;
     i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
 	set_cc_for_build
 	SUN_ARCH=i386
 	# If there is a compiler, see if it is configured for 64-bit objects.
 	# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
 	# This test works for both compilers.
-	if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
+	if test "$CC_FOR_BUILD" != no_compiler_found; then
 	    if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
 		(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
 		grep IS_64BIT_ARCH >/dev/null
@@ -404,41 +443,44 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
 		SUN_ARCH=x86_64
 	    fi
 	fi
-	echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
-	exit ;;
+	SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+	GUESS=$SUN_ARCH-pc-solaris2$SUN_REL
+	;;
     sun4*:SunOS:6*:*)
 	# According to config.sub, this is the proper way to canonicalize
 	# SunOS6.  Hard to guess exactly what SunOS6 will be like, but
 	# it's likely to be more like Solaris than SunOS4.
-	echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
-	exit ;;
+	SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+	GUESS=sparc-sun-solaris3$SUN_REL
+	;;
     sun4*:SunOS:*:*)
-	case "`/usr/bin/arch -k`" in
+	case `/usr/bin/arch -k` in
 	    Series*|S4*)
 		UNAME_RELEASE=`uname -v`
 		;;
 	esac
 	# Japanese Language versions have a version number like `4.1.3-JL'.
-	echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`"
-	exit ;;
+	SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/'`
+	GUESS=sparc-sun-sunos$SUN_REL
+	;;
     sun3*:SunOS:*:*)
-	echo m68k-sun-sunos"$UNAME_RELEASE"
-	exit ;;
+	GUESS=m68k-sun-sunos$UNAME_RELEASE
+	;;
     sun*:*:4.2BSD:*)
 	UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
 	test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3
-	case "`/bin/arch`" in
+	case `/bin/arch` in
 	    sun3)
-		echo m68k-sun-sunos"$UNAME_RELEASE"
+		GUESS=m68k-sun-sunos$UNAME_RELEASE
 		;;
 	    sun4)
-		echo sparc-sun-sunos"$UNAME_RELEASE"
+		GUESS=sparc-sun-sunos$UNAME_RELEASE
 		;;
 	esac
-	exit ;;
+	;;
     aushp:SunOS:*:*)
-	echo sparc-auspex-sunos"$UNAME_RELEASE"
-	exit ;;
+	GUESS=sparc-auspex-sunos$UNAME_RELEASE
+	;;
     # The situation for MiNT is a little confusing.  The machine name
     # can be virtually everything (everything which is not
     # "atarist" or "atariste" at least should have a processor
@@ -448,41 +490,41 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
     # MiNT.  But MiNT is downward compatible to TOS, so this should
     # be no problem.
     atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
-	echo m68k-atari-mint"$UNAME_RELEASE"
-	exit ;;
+	GUESS=m68k-atari-mint$UNAME_RELEASE
+	;;
     atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
-	echo m68k-atari-mint"$UNAME_RELEASE"
-	exit ;;
+	GUESS=m68k-atari-mint$UNAME_RELEASE
+	;;
     *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
-	echo m68k-atari-mint"$UNAME_RELEASE"
-	exit ;;
+	GUESS=m68k-atari-mint$UNAME_RELEASE
+	;;
     milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
-	echo m68k-milan-mint"$UNAME_RELEASE"
-	exit ;;
+	GUESS=m68k-milan-mint$UNAME_RELEASE
+	;;
     hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
-	echo m68k-hades-mint"$UNAME_RELEASE"
-	exit ;;
+	GUESS=m68k-hades-mint$UNAME_RELEASE
+	;;
     *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
-	echo m68k-unknown-mint"$UNAME_RELEASE"
-	exit ;;
+	GUESS=m68k-unknown-mint$UNAME_RELEASE
+	;;
     m68k:machten:*:*)
-	echo m68k-apple-machten"$UNAME_RELEASE"
-	exit ;;
+	GUESS=m68k-apple-machten$UNAME_RELEASE
+	;;
     powerpc:machten:*:*)
-	echo powerpc-apple-machten"$UNAME_RELEASE"
-	exit ;;
+	GUESS=powerpc-apple-machten$UNAME_RELEASE
+	;;
     RISC*:Mach:*:*)
-	echo mips-dec-mach_bsd4.3
-	exit ;;
+	GUESS=mips-dec-mach_bsd4.3
+	;;
     RISC*:ULTRIX:*:*)
-	echo mips-dec-ultrix"$UNAME_RELEASE"
-	exit ;;
+	GUESS=mips-dec-ultrix$UNAME_RELEASE
+	;;
     VAX*:ULTRIX*:*:*)
-	echo vax-dec-ultrix"$UNAME_RELEASE"
-	exit ;;
+	GUESS=vax-dec-ultrix$UNAME_RELEASE
+	;;
     2020:CLIX:*:* | 2430:CLIX:*:*)
-	echo clipper-intergraph-clix"$UNAME_RELEASE"
-	exit ;;
+	GUESS=clipper-intergraph-clix$UNAME_RELEASE
+	;;
     mips:*:*:UMIPS | mips:*:*:RISCos)
 	set_cc_for_build
 	sed 's/^	//' << EOF > "$dummy.c"
@@ -510,75 +552,76 @@ EOF
 	  dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` &&
 	  SYSTEM_NAME=`"$dummy" "$dummyarg"` &&
 	    { echo "$SYSTEM_NAME"; exit; }
-	echo mips-mips-riscos"$UNAME_RELEASE"
-	exit ;;
+	GUESS=mips-mips-riscos$UNAME_RELEASE
+	;;
     Motorola:PowerMAX_OS:*:*)
-	echo powerpc-motorola-powermax
-	exit ;;
+	GUESS=powerpc-motorola-powermax
+	;;
     Motorola:*:4.3:PL8-*)
-	echo powerpc-harris-powermax
-	exit ;;
+	GUESS=powerpc-harris-powermax
+	;;
     Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
-	echo powerpc-harris-powermax
-	exit ;;
+	GUESS=powerpc-harris-powermax
+	;;
     Night_Hawk:Power_UNIX:*:*)
-	echo powerpc-harris-powerunix
-	exit ;;
+	GUESS=powerpc-harris-powerunix
+	;;
     m88k:CX/UX:7*:*)
-	echo m88k-harris-cxux7
-	exit ;;
+	GUESS=m88k-harris-cxux7
+	;;
     m88k:*:4*:R4*)
-	echo m88k-motorola-sysv4
-	exit ;;
+	GUESS=m88k-motorola-sysv4
+	;;
     m88k:*:3*:R3*)
-	echo m88k-motorola-sysv3
-	exit ;;
+	GUESS=m88k-motorola-sysv3
+	;;
     AViiON:dgux:*:*)
 	# DG/UX returns AViiON for all architectures
 	UNAME_PROCESSOR=`/usr/bin/uname -p`
-	if [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ]
+	if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110
 	then
-	    if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \
-	       [ "$TARGET_BINARY_INTERFACE"x = x ]
+	    if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \
+	       test "$TARGET_BINARY_INTERFACE"x = x
 	    then
-		echo m88k-dg-dgux"$UNAME_RELEASE"
+		GUESS=m88k-dg-dgux$UNAME_RELEASE
 	    else
-		echo m88k-dg-dguxbcs"$UNAME_RELEASE"
+		GUESS=m88k-dg-dguxbcs$UNAME_RELEASE
 	    fi
 	else
-	    echo i586-dg-dgux"$UNAME_RELEASE"
+	    GUESS=i586-dg-dgux$UNAME_RELEASE
 	fi
-	exit ;;
+	;;
     M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
-	echo m88k-dolphin-sysv3
-	exit ;;
+	GUESS=m88k-dolphin-sysv3
+	;;
     M88*:*:R3*:*)
 	# Delta 88k system running SVR3
-	echo m88k-motorola-sysv3
-	exit ;;
+	GUESS=m88k-motorola-sysv3
+	;;
     XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
-	echo m88k-tektronix-sysv3
-	exit ;;
+	GUESS=m88k-tektronix-sysv3
+	;;
     Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
-	echo m68k-tektronix-bsd
-	exit ;;
+	GUESS=m68k-tektronix-bsd
+	;;
     *:IRIX*:*:*)
-	echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`"
-	exit ;;
+	IRIX_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/g'`
+	GUESS=mips-sgi-irix$IRIX_REL
+	;;
     ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
-	echo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id
-	exit ;;               # Note that: echo "'`uname -s`'" gives 'AIX '
+	GUESS=romp-ibm-aix    # uname -m gives an 8 hex-code CPU id
+	;;                    # Note that: echo "'`uname -s`'" gives 'AIX '
     i*86:AIX:*:*)
-	echo i386-ibm-aix
-	exit ;;
+	GUESS=i386-ibm-aix
+	;;
     ia64:AIX:*:*)
-	if [ -x /usr/bin/oslevel ] ; then
+	if test -x /usr/bin/oslevel ; then
 		IBM_REV=`/usr/bin/oslevel`
 	else
-		IBM_REV="$UNAME_VERSION.$UNAME_RELEASE"
+		IBM_REV=$UNAME_VERSION.$UNAME_RELEASE
 	fi
-	echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV"
-	exit ;;
+	GUESS=$UNAME_MACHINE-ibm-aix$IBM_REV
+	;;
     *:AIX:2:3)
 	if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
 		set_cc_for_build
@@ -595,16 +638,16 @@ EOF
 EOF
 		if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"`
 		then
-			echo "$SYSTEM_NAME"
+			GUESS=$SYSTEM_NAME
 		else
-			echo rs6000-ibm-aix3.2.5
+			GUESS=rs6000-ibm-aix3.2.5
 		fi
 	elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
-		echo rs6000-ibm-aix3.2.4
+		GUESS=rs6000-ibm-aix3.2.4
 	else
-		echo rs6000-ibm-aix3.2
+		GUESS=rs6000-ibm-aix3.2
 	fi
-	exit ;;
+	;;
     *:AIX:*:[4567])
 	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
 	if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then
@@ -612,56 +655,56 @@ EOF
 	else
 		IBM_ARCH=powerpc
 	fi
-	if [ -x /usr/bin/lslpp ] ; then
-		IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
+	if test -x /usr/bin/lslpp ; then
+		IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | \
 			   awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
 	else
-		IBM_REV="$UNAME_VERSION.$UNAME_RELEASE"
+		IBM_REV=$UNAME_VERSION.$UNAME_RELEASE
 	fi
-	echo "$IBM_ARCH"-ibm-aix"$IBM_REV"
-	exit ;;
+	GUESS=$IBM_ARCH-ibm-aix$IBM_REV
+	;;
     *:AIX:*:*)
-	echo rs6000-ibm-aix
-	exit ;;
+	GUESS=rs6000-ibm-aix
+	;;
     ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*)
-	echo romp-ibm-bsd4.4
-	exit ;;
+	GUESS=romp-ibm-bsd4.4
+	;;
     ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
-	echo romp-ibm-bsd"$UNAME_RELEASE"   # 4.3 with uname added to
-	exit ;;                             # report: romp-ibm BSD 4.3
+	GUESS=romp-ibm-bsd$UNAME_RELEASE    # 4.3 with uname added to
+	;;                                  # report: romp-ibm BSD 4.3
     *:BOSX:*:*)
-	echo rs6000-bull-bosx
-	exit ;;
+	GUESS=rs6000-bull-bosx
+	;;
     DPX/2?00:B.O.S.:*:*)
-	echo m68k-bull-sysv3
-	exit ;;
+	GUESS=m68k-bull-sysv3
+	;;
     9000/[34]??:4.3bsd:1.*:*)
-	echo m68k-hp-bsd
-	exit ;;
+	GUESS=m68k-hp-bsd
+	;;
     hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
-	echo m68k-hp-bsd4.4
-	exit ;;
+	GUESS=m68k-hp-bsd4.4
+	;;
     9000/[34678]??:HP-UX:*:*)
-	HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'`
-	case "$UNAME_MACHINE" in
+	HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'`
+	case $UNAME_MACHINE in
 	    9000/31?)            HP_ARCH=m68000 ;;
 	    9000/[34]??)         HP_ARCH=m68k ;;
 	    9000/[678][0-9][0-9])
-		if [ -x /usr/bin/getconf ]; then
+		if test -x /usr/bin/getconf; then
 		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
 		    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
-		    case "$sc_cpu_version" in
+		    case $sc_cpu_version in
 		      523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
 		      528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
 		      532)                      # CPU_PA_RISC2_0
-			case "$sc_kernel_bits" in
+			case $sc_kernel_bits in
 			  32) HP_ARCH=hppa2.0n ;;
 			  64) HP_ARCH=hppa2.0w ;;
 			  '') HP_ARCH=hppa2.0 ;;   # HP-UX 10.20
 			esac ;;
 		    esac
 		fi
-		if [ "$HP_ARCH" = "" ]; then
+		if test "$HP_ARCH" = ""; then
 		    set_cc_for_build
 		    sed 's/^		//' << EOF > "$dummy.c"
 
@@ -700,7 +743,7 @@ EOF
 		    test -z "$HP_ARCH" && HP_ARCH=hppa
 		fi ;;
 	esac
-	if [ "$HP_ARCH" = hppa2.0w ]
+	if test "$HP_ARCH" = hppa2.0w
 	then
 	    set_cc_for_build
 
@@ -721,12 +764,12 @@ EOF
 		HP_ARCH=hppa64
 	    fi
 	fi
-	echo "$HP_ARCH"-hp-hpux"$HPUX_REV"
-	exit ;;
+	GUESS=$HP_ARCH-hp-hpux$HPUX_REV
+	;;
     ia64:HP-UX:*:*)
-	HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'`
-	echo ia64-hp-hpux"$HPUX_REV"
-	exit ;;
+	HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'`
+	GUESS=ia64-hp-hpux$HPUX_REV
+	;;
     3050*:HI-UX:*:*)
 	set_cc_for_build
 	sed 's/^	//' << EOF > "$dummy.c"
@@ -756,36 +799,36 @@ EOF
 EOF
 	$CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` &&
 		{ echo "$SYSTEM_NAME"; exit; }
-	echo unknown-hitachi-hiuxwe2
-	exit ;;
+	GUESS=unknown-hitachi-hiuxwe2
+	;;
     9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*)
-	echo hppa1.1-hp-bsd
-	exit ;;
+	GUESS=hppa1.1-hp-bsd
+	;;
     9000/8??:4.3bsd:*:*)
-	echo hppa1.0-hp-bsd
-	exit ;;
+	GUESS=hppa1.0-hp-bsd
+	;;
     *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
-	echo hppa1.0-hp-mpeix
-	exit ;;
+	GUESS=hppa1.0-hp-mpeix
+	;;
     hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*)
-	echo hppa1.1-hp-osf
-	exit ;;
+	GUESS=hppa1.1-hp-osf
+	;;
     hp8??:OSF1:*:*)
-	echo hppa1.0-hp-osf
-	exit ;;
+	GUESS=hppa1.0-hp-osf
+	;;
     i*86:OSF1:*:*)
-	if [ -x /usr/sbin/sysversion ] ; then
-	    echo "$UNAME_MACHINE"-unknown-osf1mk
+	if test -x /usr/sbin/sysversion ; then
+	    GUESS=$UNAME_MACHINE-unknown-osf1mk
 	else
-	    echo "$UNAME_MACHINE"-unknown-osf1
+	    GUESS=$UNAME_MACHINE-unknown-osf1
 	fi
-	exit ;;
+	;;
     parisc*:Lites*:*:*)
-	echo hppa1.1-hp-lites
-	exit ;;
+	GUESS=hppa1.1-hp-lites
+	;;
     C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
-	echo c1-convex-bsd
-	exit ;;
+	GUESS=c1-convex-bsd
+	;;
     C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
 	if getsysinfo -f scalar_acc
 	then echo c32-convex-bsd
@@ -793,17 +836,18 @@ EOF
 	fi
 	exit ;;
     C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
-	echo c34-convex-bsd
-	exit ;;
+	GUESS=c34-convex-bsd
+	;;
     C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
-	echo c38-convex-bsd
-	exit ;;
+	GUESS=c38-convex-bsd
+	;;
     C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
-	echo c4-convex-bsd
-	exit ;;
+	GUESS=c4-convex-bsd
+	;;
     CRAY*Y-MP:*:*:*)
-	echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
-	exit ;;
+	CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+	GUESS=ymp-cray-unicos$CRAY_REL
+	;;
     CRAY*[A-Z]90:*:*:*)
 	echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \
 	| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
@@ -811,114 +855,126 @@ EOF
 	      -e 's/\.[^.]*$/.X/'
 	exit ;;
     CRAY*TS:*:*:*)
-	echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
-	exit ;;
+	CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+	GUESS=t90-cray-unicos$CRAY_REL
+	;;
     CRAY*T3E:*:*:*)
-	echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
-	exit ;;
+	CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+	GUESS=alphaev5-cray-unicosmk$CRAY_REL
+	;;
     CRAY*SV1:*:*:*)
-	echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
-	exit ;;
+	CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+	GUESS=sv1-cray-unicos$CRAY_REL
+	;;
     *:UNICOS/mp:*:*)
-	echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
-	exit ;;
+	CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+	GUESS=craynv-cray-unicosmp$CRAY_REL
+	;;
     F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
 	FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
 	FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
 	FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'`
-	echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
-	exit ;;
+	GUESS=${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}
+	;;
     5000:UNIX_System_V:4.*:*)
 	FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
 	FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
-	echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
-	exit ;;
+	GUESS=sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}
+	;;
     i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
-	echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE"
-	exit ;;
+	GUESS=$UNAME_MACHINE-pc-bsdi$UNAME_RELEASE
+	;;
     sparc*:BSD/OS:*:*)
-	echo sparc-unknown-bsdi"$UNAME_RELEASE"
-	exit ;;
+	GUESS=sparc-unknown-bsdi$UNAME_RELEASE
+	;;
     *:BSD/OS:*:*)
-	echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE"
-	exit ;;
+	GUESS=$UNAME_MACHINE-unknown-bsdi$UNAME_RELEASE
+	;;
     arm:FreeBSD:*:*)
 	UNAME_PROCESSOR=`uname -p`
 	set_cc_for_build
 	if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
 	    | grep -q __ARM_PCS_VFP
 	then
-	    echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabi
+	    FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+	    GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabi
 	else
-	    echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabihf
+	    FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+	    GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabihf
 	fi
-	exit ;;
+	;;
     *:FreeBSD:*:*)
 	UNAME_PROCESSOR=`/usr/bin/uname -p`
-	case "$UNAME_PROCESSOR" in
+	case $UNAME_PROCESSOR in
 	    amd64)
 		UNAME_PROCESSOR=x86_64 ;;
 	    i386)
 		UNAME_PROCESSOR=i586 ;;
 	esac
-	echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`"
-	exit ;;
+	FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+	GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL
+	;;
     i*:CYGWIN*:*)
-	echo "$UNAME_MACHINE"-pc-cygwin
-	exit ;;
+	GUESS=$UNAME_MACHINE-pc-cygwin
+	;;
     *:MINGW64*:*)
-	echo "$UNAME_MACHINE"-pc-mingw64
-	exit ;;
+	GUESS=$UNAME_MACHINE-pc-mingw64
+	;;
     *:MINGW*:*)
-	echo "$UNAME_MACHINE"-pc-mingw32
-	exit ;;
+	GUESS=$UNAME_MACHINE-pc-mingw32
+	;;
     *:MSYS*:*)
-	echo "$UNAME_MACHINE"-pc-msys
-	exit ;;
+	GUESS=$UNAME_MACHINE-pc-msys
+	;;
     i*:PW*:*)
-	echo "$UNAME_MACHINE"-pc-pw32
-	exit ;;
+	GUESS=$UNAME_MACHINE-pc-pw32
+	;;
     *:Interix*:*)
-	case "$UNAME_MACHINE" in
+	case $UNAME_MACHINE in
 	    x86)
-		echo i586-pc-interix"$UNAME_RELEASE"
-		exit ;;
+		GUESS=i586-pc-interix$UNAME_RELEASE
+		;;
 	    authenticamd | genuineintel | EM64T)
-		echo x86_64-unknown-interix"$UNAME_RELEASE"
-		exit ;;
+		GUESS=x86_64-unknown-interix$UNAME_RELEASE
+		;;
 	    IA64)
-		echo ia64-unknown-interix"$UNAME_RELEASE"
-		exit ;;
+		GUESS=ia64-unknown-interix$UNAME_RELEASE
+		;;
 	esac ;;
     i*:UWIN*:*)
-	echo "$UNAME_MACHINE"-pc-uwin
-	exit ;;
+	GUESS=$UNAME_MACHINE-pc-uwin
+	;;
     amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
-	echo x86_64-pc-cygwin
-	exit ;;
+	GUESS=x86_64-pc-cygwin
+	;;
     prep*:SunOS:5.*:*)
-	echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
-	exit ;;
+	SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+	GUESS=powerpcle-unknown-solaris2$SUN_REL
+	;;
     *:GNU:*:*)
 	# the GNU system
-	echo "`echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,'`-unknown-$LIBC`echo "$UNAME_RELEASE"|sed -e 's,/.*$,,'`"
-	exit ;;
+	GNU_ARCH=`echo "$UNAME_MACHINE" | sed -e 's,[-/].*$,,'`
+	GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's,/.*$,,'`
+	GUESS=$GNU_ARCH-unknown-$LIBC$GNU_REL
+	;;
     *:GNU/*:*:*)
 	# other systems with GNU libc and userland
-	echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC"
-	exit ;;
+	GNU_SYS=`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"`
+	GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+	GUESS=$UNAME_MACHINE-unknown-$GNU_SYS$GNU_REL-$LIBC
+	;;
     *:Minix:*:*)
-	echo "$UNAME_MACHINE"-unknown-minix
-	exit ;;
+	GUESS=$UNAME_MACHINE-unknown-minix
+	;;
     aarch64:Linux:*:*)
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
     aarch64_be:Linux:*:*)
 	UNAME_MACHINE=aarch64_be
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
     alpha:Linux:*:*)
-	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in
 	  EV5)   UNAME_MACHINE=alphaev5 ;;
 	  EV56)  UNAME_MACHINE=alphaev56 ;;
 	  PCA56) UNAME_MACHINE=alphapca56 ;;
@@ -929,183 +985,225 @@ EOF
 	esac
 	objdump --private-headers /bin/sh | grep -q ld.so.1
 	if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
-    arc:Linux:*:* | arceb:Linux:*:*)
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
+    arc:Linux:*:* | arceb:Linux:*:* | arc32:Linux:*:* | arc64:Linux:*:*)
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
     arm*:Linux:*:*)
 	set_cc_for_build
 	if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
 	    | grep -q __ARM_EABI__
 	then
-	    echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+	    GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
 	else
 	    if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
 		| grep -q __ARM_PCS_VFP
 	    then
-		echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi
+		GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabi
 	    else
-		echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf
+		GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabihf
 	    fi
 	fi
-	exit ;;
+	;;
     avr32*:Linux:*:*)
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
     cris:Linux:*:*)
-	echo "$UNAME_MACHINE"-axis-linux-"$LIBC"
-	exit ;;
+	GUESS=$UNAME_MACHINE-axis-linux-$LIBC
+	;;
     crisv32:Linux:*:*)
-	echo "$UNAME_MACHINE"-axis-linux-"$LIBC"
-	exit ;;
+	GUESS=$UNAME_MACHINE-axis-linux-$LIBC
+	;;
     e2k:Linux:*:*)
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
     frv:Linux:*:*)
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
     hexagon:Linux:*:*)
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
     i*86:Linux:*:*)
-	echo "$UNAME_MACHINE"-pc-linux-"$LIBC"
-	exit ;;
+	GUESS=$UNAME_MACHINE-pc-linux-$LIBC
+	;;
     ia64:Linux:*:*)
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
     k1om:Linux:*:*)
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
+    loongarch32:Linux:*:* | loongarch64:Linux:*:* | loongarchx32:Linux:*:*)
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
     m32r*:Linux:*:*)
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
     m68*:Linux:*:*)
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
     mips:Linux:*:* | mips64:Linux:*:*)
 	set_cc_for_build
+	IS_GLIBC=0
+	test x"${LIBC}" = xgnu && IS_GLIBC=1
 	sed 's/^	//' << EOF > "$dummy.c"
 	#undef CPU
-	#undef ${UNAME_MACHINE}
-	#undef ${UNAME_MACHINE}el
+	#undef mips
+	#undef mipsel
+	#undef mips64
+	#undef mips64el
+	#if ${IS_GLIBC} && defined(_ABI64)
+	LIBCABI=gnuabi64
+	#else
+	#if ${IS_GLIBC} && defined(_ABIN32)
+	LIBCABI=gnuabin32
+	#else
+	LIBCABI=${LIBC}
+	#endif
+	#endif
+
+	#if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6
+	CPU=mipsisa64r6
+	#else
+	#if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6
+	CPU=mipsisa32r6
+	#else
+	#if defined(__mips64)
+	CPU=mips64
+	#else
+	CPU=mips
+	#endif
+	#endif
+	#endif
+
 	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
-	CPU=${UNAME_MACHINE}el
+	MIPS_ENDIAN=el
 	#else
 	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
-	CPU=${UNAME_MACHINE}
+	MIPS_ENDIAN=
 	#else
-	CPU=
+	MIPS_ENDIAN=
 	#endif
 	#endif
 EOF
-	eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU'`"
-	test "x$CPU" != x && { echo "$CPU-unknown-linux-$LIBC"; exit; }
+	cc_set_vars=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'`
+	eval "$cc_set_vars"
+	test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; }
 	;;
     mips64el:Linux:*:*)
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
     openrisc*:Linux:*:*)
-	echo or1k-unknown-linux-"$LIBC"
-	exit ;;
+	GUESS=or1k-unknown-linux-$LIBC
+	;;
     or32:Linux:*:* | or1k*:Linux:*:*)
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
     padre:Linux:*:*)
-	echo sparc-unknown-linux-"$LIBC"
-	exit ;;
+	GUESS=sparc-unknown-linux-$LIBC
+	;;
     parisc64:Linux:*:* | hppa64:Linux:*:*)
-	echo hppa64-unknown-linux-"$LIBC"
-	exit ;;
+	GUESS=hppa64-unknown-linux-$LIBC
+	;;
     parisc:Linux:*:* | hppa:Linux:*:*)
 	# Look for CPU level
 	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
-	  PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;;
-	  PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;;
-	  *)    echo hppa-unknown-linux-"$LIBC" ;;
+	  PA7*) GUESS=hppa1.1-unknown-linux-$LIBC ;;
+	  PA8*) GUESS=hppa2.0-unknown-linux-$LIBC ;;
+	  *)    GUESS=hppa-unknown-linux-$LIBC ;;
 	esac
-	exit ;;
+	;;
     ppc64:Linux:*:*)
-	echo powerpc64-unknown-linux-"$LIBC"
-	exit ;;
+	GUESS=powerpc64-unknown-linux-$LIBC
+	;;
     ppc:Linux:*:*)
-	echo powerpc-unknown-linux-"$LIBC"
-	exit ;;
+	GUESS=powerpc-unknown-linux-$LIBC
+	;;
     ppc64le:Linux:*:*)
-	echo powerpc64le-unknown-linux-"$LIBC"
-	exit ;;
+	GUESS=powerpc64le-unknown-linux-$LIBC
+	;;
     ppcle:Linux:*:*)
-	echo powerpcle-unknown-linux-"$LIBC"
-	exit ;;
-    riscv32:Linux:*:* | riscv64:Linux:*:*)
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
+	GUESS=powerpcle-unknown-linux-$LIBC
+	;;
+    riscv32:Linux:*:* | riscv32be:Linux:*:* | riscv64:Linux:*:* | riscv64be:Linux:*:*)
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
     s390:Linux:*:* | s390x:Linux:*:*)
-	echo "$UNAME_MACHINE"-ibm-linux-"$LIBC"
-	exit ;;
+	GUESS=$UNAME_MACHINE-ibm-linux-$LIBC
+	;;
     sh64*:Linux:*:*)
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
     sh*:Linux:*:*)
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
     sparc:Linux:*:* | sparc64:Linux:*:*)
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
     tile*:Linux:*:*)
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
     vax:Linux:*:*)
-	echo "$UNAME_MACHINE"-dec-linux-"$LIBC"
-	exit ;;
+	GUESS=$UNAME_MACHINE-dec-linux-$LIBC
+	;;
     x86_64:Linux:*:*)
-	echo "$UNAME_MACHINE"-pc-linux-"$LIBC"
-	exit ;;
+	set_cc_for_build
+	LIBCABI=$LIBC
+	if test "$CC_FOR_BUILD" != no_compiler_found; then
+	    if (echo '#ifdef __ILP32__'; echo IS_X32; echo '#endif') | \
+		(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+		grep IS_X32 >/dev/null
+	    then
+		LIBCABI=${LIBC}x32
+	    fi
+	fi
+	GUESS=$UNAME_MACHINE-pc-linux-$LIBCABI
+	;;
     xtensa*:Linux:*:*)
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
     i*86:DYNIX/ptx:4*:*)
 	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
 	# earlier versions are messed up and put the nodename in both
 	# sysname and nodename.
-	echo i386-sequent-sysv4
-	exit ;;
+	GUESS=i386-sequent-sysv4
+	;;
     i*86:UNIX_SV:4.2MP:2.*)
 	# Unixware is an offshoot of SVR4, but it has its own version
 	# number series starting with 2...
 	# I am not positive that other SVR4 systems won't match this,
 	# I just have to hope.  -- rms.
 	# Use sysv4.2uw... so that sysv4* matches it.
-	echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION"
-	exit ;;
+	GUESS=$UNAME_MACHINE-pc-sysv4.2uw$UNAME_VERSION
+	;;
     i*86:OS/2:*:*)
 	# If we were able to find `uname', then EMX Unix compatibility
 	# is probably installed.
-	echo "$UNAME_MACHINE"-pc-os2-emx
-	exit ;;
+	GUESS=$UNAME_MACHINE-pc-os2-emx
+	;;
     i*86:XTS-300:*:STOP)
-	echo "$UNAME_MACHINE"-unknown-stop
-	exit ;;
+	GUESS=$UNAME_MACHINE-unknown-stop
+	;;
     i*86:atheos:*:*)
-	echo "$UNAME_MACHINE"-unknown-atheos
-	exit ;;
+	GUESS=$UNAME_MACHINE-unknown-atheos
+	;;
     i*86:syllable:*:*)
-	echo "$UNAME_MACHINE"-pc-syllable
-	exit ;;
+	GUESS=$UNAME_MACHINE-pc-syllable
+	;;
     i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
-	echo i386-unknown-lynxos"$UNAME_RELEASE"
-	exit ;;
+	GUESS=i386-unknown-lynxos$UNAME_RELEASE
+	;;
     i*86:*DOS:*:*)
-	echo "$UNAME_MACHINE"-pc-msdosdjgpp
-	exit ;;
+	GUESS=$UNAME_MACHINE-pc-msdosdjgpp
+	;;
     i*86:*:4.*:*)
 	UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'`
 	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
-		echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL"
+		GUESS=$UNAME_MACHINE-univel-sysv$UNAME_REL
 	else
-		echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL"
+		GUESS=$UNAME_MACHINE-pc-sysv$UNAME_REL
 	fi
-	exit ;;
+	;;
     i*86:*:5:[678]*)
 	# UnixWare 7.x, OpenUNIX and OpenServer 6.
 	case `/bin/uname -X | grep "^Machine"` in
@@ -1113,12 +1211,12 @@ EOF
 	    *Pentium)	     UNAME_MACHINE=i586 ;;
 	    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
 	esac
-	echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}{$UNAME_VERSION}"
-	exit ;;
+	GUESS=$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+	;;
     i*86:*:3.2:*)
 	if test -f /usr/options/cb.name; then
 		UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
-		echo "$UNAME_MACHINE"-pc-isc"$UNAME_REL"
+		GUESS=$UNAME_MACHINE-pc-isc$UNAME_REL
 	elif /bin/uname -X 2>/dev/null >/dev/null ; then
 		UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
 		(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
@@ -1128,11 +1226,11 @@ EOF
 			&& UNAME_MACHINE=i686
 		(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
 			&& UNAME_MACHINE=i686
-		echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL"
+		GUESS=$UNAME_MACHINE-pc-sco$UNAME_REL
 	else
-		echo "$UNAME_MACHINE"-pc-sysv32
+		GUESS=$UNAME_MACHINE-pc-sysv32
 	fi
-	exit ;;
+	;;
     pc:*:*:*)
 	# Left here for compatibility:
 	# uname -m prints for DJGPP always 'pc', but it prints nothing about
@@ -1140,31 +1238,31 @@ EOF
 	# Note: whatever this is, it MUST be the same as what config.sub
 	# prints for the "djgpp" host, or else GDB configure will decide that
 	# this is a cross-build.
-	echo i586-pc-msdosdjgpp
-	exit ;;
+	GUESS=i586-pc-msdosdjgpp
+	;;
     Intel:Mach:3*:*)
-	echo i386-pc-mach3
-	exit ;;
+	GUESS=i386-pc-mach3
+	;;
     paragon:*:*:*)
-	echo i860-intel-osf1
-	exit ;;
+	GUESS=i860-intel-osf1
+	;;
     i860:*:4.*:*) # i860-SVR4
 	if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
-	  echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4
+	  GUESS=i860-stardent-sysv$UNAME_RELEASE    # Stardent Vistra i860-SVR4
 	else # Add other i860-SVR4 vendors below as they are discovered.
-	  echo i860-unknown-sysv"$UNAME_RELEASE"  # Unknown i860-SVR4
+	  GUESS=i860-unknown-sysv$UNAME_RELEASE     # Unknown i860-SVR4
 	fi
-	exit ;;
+	;;
     mini*:CTIX:SYS*5:*)
 	# "miniframe"
-	echo m68010-convergent-sysv
-	exit ;;
+	GUESS=m68010-convergent-sysv
+	;;
     mc68k:UNIX:SYSTEM5:3.51m)
-	echo m68k-convergent-sysv
-	exit ;;
+	GUESS=m68k-convergent-sysv
+	;;
     M680?0:D-NIX:5.3:*)
-	echo m68k-diab-dnix
-	exit ;;
+	GUESS=m68k-diab-dnix
+	;;
     M68*:*:R3V[5678]*:*)
 	test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
     3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
@@ -1189,253 +1287,401 @@ EOF
 	/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
 	    && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
     m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
-	echo m68k-unknown-lynxos"$UNAME_RELEASE"
-	exit ;;
+	GUESS=m68k-unknown-lynxos$UNAME_RELEASE
+	;;
     mc68030:UNIX_System_V:4.*:*)
-	echo m68k-atari-sysv4
-	exit ;;
+	GUESS=m68k-atari-sysv4
+	;;
     TSUNAMI:LynxOS:2.*:*)
-	echo sparc-unknown-lynxos"$UNAME_RELEASE"
-	exit ;;
+	GUESS=sparc-unknown-lynxos$UNAME_RELEASE
+	;;
     rs6000:LynxOS:2.*:*)
-	echo rs6000-unknown-lynxos"$UNAME_RELEASE"
-	exit ;;
+	GUESS=rs6000-unknown-lynxos$UNAME_RELEASE
+	;;
     PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
-	echo powerpc-unknown-lynxos"$UNAME_RELEASE"
-	exit ;;
+	GUESS=powerpc-unknown-lynxos$UNAME_RELEASE
+	;;
     SM[BE]S:UNIX_SV:*:*)
-	echo mips-dde-sysv"$UNAME_RELEASE"
-	exit ;;
+	GUESS=mips-dde-sysv$UNAME_RELEASE
+	;;
     RM*:ReliantUNIX-*:*:*)
-	echo mips-sni-sysv4
-	exit ;;
+	GUESS=mips-sni-sysv4
+	;;
     RM*:SINIX-*:*:*)
-	echo mips-sni-sysv4
-	exit ;;
+	GUESS=mips-sni-sysv4
+	;;
     *:SINIX-*:*:*)
 	if uname -p 2>/dev/null >/dev/null ; then
 		UNAME_MACHINE=`(uname -p) 2>/dev/null`
-		echo "$UNAME_MACHINE"-sni-sysv4
+		GUESS=$UNAME_MACHINE-sni-sysv4
 	else
-		echo ns32k-sni-sysv
+		GUESS=ns32k-sni-sysv
 	fi
-	exit ;;
+	;;
     PENTIUM:*:4.0*:*)	# Unisys `ClearPath HMP IX 4000' SVR4/MP effort
 			# says <Richard.M.Bartel@ccMail.Census.GOV>
-	echo i586-unisys-sysv4
-	exit ;;
+	GUESS=i586-unisys-sysv4
+	;;
     *:UNIX_System_V:4*:FTX*)
 	# From Gerald Hewes <hewes@openmarket.com>.
 	# How about differentiating between stratus architectures? -djm
-	echo hppa1.1-stratus-sysv4
-	exit ;;
+	GUESS=hppa1.1-stratus-sysv4
+	;;
     *:*:*:FTX*)
 	# From seanf@swdc.stratus.com.
-	echo i860-stratus-sysv4
-	exit ;;
+	GUESS=i860-stratus-sysv4
+	;;
     i*86:VOS:*:*)
 	# From Paul.Green@stratus.com.
-	echo "$UNAME_MACHINE"-stratus-vos
-	exit ;;
+	GUESS=$UNAME_MACHINE-stratus-vos
+	;;
     *:VOS:*:*)
 	# From Paul.Green@stratus.com.
-	echo hppa1.1-stratus-vos
-	exit ;;
+	GUESS=hppa1.1-stratus-vos
+	;;
     mc68*:A/UX:*:*)
-	echo m68k-apple-aux"$UNAME_RELEASE"
-	exit ;;
+	GUESS=m68k-apple-aux$UNAME_RELEASE
+	;;
     news*:NEWS-OS:6*:*)
-	echo mips-sony-newsos6
-	exit ;;
+	GUESS=mips-sony-newsos6
+	;;
     R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
-	if [ -d /usr/nec ]; then
-		echo mips-nec-sysv"$UNAME_RELEASE"
+	if test -d /usr/nec; then
+		GUESS=mips-nec-sysv$UNAME_RELEASE
 	else
-		echo mips-unknown-sysv"$UNAME_RELEASE"
+		GUESS=mips-unknown-sysv$UNAME_RELEASE
 	fi
-	exit ;;
+	;;
     BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
-	echo powerpc-be-beos
-	exit ;;
+	GUESS=powerpc-be-beos
+	;;
     BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only.
-	echo powerpc-apple-beos
-	exit ;;
+	GUESS=powerpc-apple-beos
+	;;
     BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
-	echo i586-pc-beos
-	exit ;;
+	GUESS=i586-pc-beos
+	;;
     BePC:Haiku:*:*)	# Haiku running on Intel PC compatible.
-	echo i586-pc-haiku
-	exit ;;
+	GUESS=i586-pc-haiku
+	;;
     x86_64:Haiku:*:*)
-	echo x86_64-unknown-haiku
-	exit ;;
+	GUESS=x86_64-unknown-haiku
+	;;
     SX-4:SUPER-UX:*:*)
-	echo sx4-nec-superux"$UNAME_RELEASE"
-	exit ;;
+	GUESS=sx4-nec-superux$UNAME_RELEASE
+	;;
     SX-5:SUPER-UX:*:*)
-	echo sx5-nec-superux"$UNAME_RELEASE"
-	exit ;;
+	GUESS=sx5-nec-superux$UNAME_RELEASE
+	;;
     SX-6:SUPER-UX:*:*)
-	echo sx6-nec-superux"$UNAME_RELEASE"
-	exit ;;
+	GUESS=sx6-nec-superux$UNAME_RELEASE
+	;;
     SX-7:SUPER-UX:*:*)
-	echo sx7-nec-superux"$UNAME_RELEASE"
-	exit ;;
+	GUESS=sx7-nec-superux$UNAME_RELEASE
+	;;
     SX-8:SUPER-UX:*:*)
-	echo sx8-nec-superux"$UNAME_RELEASE"
-	exit ;;
+	GUESS=sx8-nec-superux$UNAME_RELEASE
+	;;
     SX-8R:SUPER-UX:*:*)
-	echo sx8r-nec-superux"$UNAME_RELEASE"
-	exit ;;
+	GUESS=sx8r-nec-superux$UNAME_RELEASE
+	;;
     SX-ACE:SUPER-UX:*:*)
-	echo sxace-nec-superux"$UNAME_RELEASE"
-	exit ;;
+	GUESS=sxace-nec-superux$UNAME_RELEASE
+	;;
     Power*:Rhapsody:*:*)
-	echo powerpc-apple-rhapsody"$UNAME_RELEASE"
-	exit ;;
+	GUESS=powerpc-apple-rhapsody$UNAME_RELEASE
+	;;
     *:Rhapsody:*:*)
-	echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE"
-	exit ;;
+	GUESS=$UNAME_MACHINE-apple-rhapsody$UNAME_RELEASE
+	;;
+    arm64:Darwin:*:*)
+	GUESS=aarch64-apple-darwin$UNAME_RELEASE
+	;;
     *:Darwin:*:*)
-	UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
-	set_cc_for_build
-	if test "$UNAME_PROCESSOR" = unknown ; then
-	    UNAME_PROCESSOR=powerpc
+	UNAME_PROCESSOR=`uname -p`
+	case $UNAME_PROCESSOR in
+	    unknown) UNAME_PROCESSOR=powerpc ;;
+	esac
+	if command -v xcode-select > /dev/null 2> /dev/null && \
+		! xcode-select --print-path > /dev/null 2> /dev/null ; then
+	    # Avoid executing cc if there is no toolchain installed as
+	    # cc will be a stub that puts up a graphical alert
+	    # prompting the user to install developer tools.
+	    CC_FOR_BUILD=no_compiler_found
+	else
+	    set_cc_for_build
 	fi
-	if test "`echo "$UNAME_RELEASE" | sed -e 's/\..*//'`" -le 10 ; then
-	    if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
-		if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
-		       (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
-		       grep IS_64BIT_ARCH >/dev/null
-		then
-		    case $UNAME_PROCESSOR in
-			i386) UNAME_PROCESSOR=x86_64 ;;
-			powerpc) UNAME_PROCESSOR=powerpc64 ;;
-		    esac
-		fi
-		# On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc
-		if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \
-		       (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
-		       grep IS_PPC >/dev/null
-		then
-		    UNAME_PROCESSOR=powerpc
-		fi
+	if test "$CC_FOR_BUILD" != no_compiler_found; then
+	    if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+		   (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+		   grep IS_64BIT_ARCH >/dev/null
+	    then
+		case $UNAME_PROCESSOR in
+		    i386) UNAME_PROCESSOR=x86_64 ;;
+		    powerpc) UNAME_PROCESSOR=powerpc64 ;;
+		esac
+	    fi
+	    # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc
+	    if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \
+		   (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+		   grep IS_PPC >/dev/null
+	    then
+		UNAME_PROCESSOR=powerpc
 	    fi
 	elif test "$UNAME_PROCESSOR" = i386 ; then
-	    # Avoid executing cc on OS X 10.9, as it ships with a stub
-	    # that puts up a graphical alert prompting to install
-	    # developer tools.  Any system running Mac OS X 10.7 or
-	    # later (Darwin 11 and later) is required to have a 64-bit
-	    # processor. This is not true of the ARM version of Darwin
-	    # that Apple uses in portable devices.
-	    UNAME_PROCESSOR=x86_64
+	    # uname -m returns i386 or x86_64
+	    UNAME_PROCESSOR=$UNAME_MACHINE
 	fi
-	echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE"
-	exit ;;
+	GUESS=$UNAME_PROCESSOR-apple-darwin$UNAME_RELEASE
+	;;
     *:procnto*:*:* | *:QNX:[0123456789]*:*)
 	UNAME_PROCESSOR=`uname -p`
 	if test "$UNAME_PROCESSOR" = x86; then
 		UNAME_PROCESSOR=i386
 		UNAME_MACHINE=pc
 	fi
-	echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE"
-	exit ;;
+	GUESS=$UNAME_PROCESSOR-$UNAME_MACHINE-nto-qnx$UNAME_RELEASE
+	;;
     *:QNX:*:4*)
-	echo i386-pc-qnx
-	exit ;;
+	GUESS=i386-pc-qnx
+	;;
     NEO-*:NONSTOP_KERNEL:*:*)
-	echo neo-tandem-nsk"$UNAME_RELEASE"
-	exit ;;
+	GUESS=neo-tandem-nsk$UNAME_RELEASE
+	;;
     NSE-*:NONSTOP_KERNEL:*:*)
-	echo nse-tandem-nsk"$UNAME_RELEASE"
-	exit ;;
+	GUESS=nse-tandem-nsk$UNAME_RELEASE
+	;;
     NSR-*:NONSTOP_KERNEL:*:*)
-	echo nsr-tandem-nsk"$UNAME_RELEASE"
-	exit ;;
+	GUESS=nsr-tandem-nsk$UNAME_RELEASE
+	;;
     NSV-*:NONSTOP_KERNEL:*:*)
-	echo nsv-tandem-nsk"$UNAME_RELEASE"
-	exit ;;
+	GUESS=nsv-tandem-nsk$UNAME_RELEASE
+	;;
     NSX-*:NONSTOP_KERNEL:*:*)
-	echo nsx-tandem-nsk"$UNAME_RELEASE"
-	exit ;;
+	GUESS=nsx-tandem-nsk$UNAME_RELEASE
+	;;
     *:NonStop-UX:*:*)
-	echo mips-compaq-nonstopux
-	exit ;;
+	GUESS=mips-compaq-nonstopux
+	;;
     BS2000:POSIX*:*:*)
-	echo bs2000-siemens-sysv
-	exit ;;
+	GUESS=bs2000-siemens-sysv
+	;;
     DS/*:UNIX_System_V:*:*)
-	echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE"
-	exit ;;
+	GUESS=$UNAME_MACHINE-$UNAME_SYSTEM-$UNAME_RELEASE
+	;;
     *:Plan9:*:*)
 	# "uname -m" is not consistent, so use $cputype instead. 386
 	# is converted to i386 for consistency with other x86
 	# operating systems.
-	# shellcheck disable=SC2154
-	if test "$cputype" = 386; then
+	if test "${cputype-}" = 386; then
 	    UNAME_MACHINE=i386
-	else
-	    UNAME_MACHINE="$cputype"
+	elif test "x${cputype-}" != x; then
+	    UNAME_MACHINE=$cputype
 	fi
-	echo "$UNAME_MACHINE"-unknown-plan9
-	exit ;;
+	GUESS=$UNAME_MACHINE-unknown-plan9
+	;;
     *:TOPS-10:*:*)
-	echo pdp10-unknown-tops10
-	exit ;;
+	GUESS=pdp10-unknown-tops10
+	;;
     *:TENEX:*:*)
-	echo pdp10-unknown-tenex
-	exit ;;
+	GUESS=pdp10-unknown-tenex
+	;;
     KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
-	echo pdp10-dec-tops20
-	exit ;;
+	GUESS=pdp10-dec-tops20
+	;;
     XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
-	echo pdp10-xkl-tops20
-	exit ;;
+	GUESS=pdp10-xkl-tops20
+	;;
     *:TOPS-20:*:*)
-	echo pdp10-unknown-tops20
-	exit ;;
+	GUESS=pdp10-unknown-tops20
+	;;
     *:ITS:*:*)
-	echo pdp10-unknown-its
-	exit ;;
+	GUESS=pdp10-unknown-its
+	;;
     SEI:*:*:SEIUX)
-	echo mips-sei-seiux"$UNAME_RELEASE"
-	exit ;;
+	GUESS=mips-sei-seiux$UNAME_RELEASE
+	;;
     *:DragonFly:*:*)
-	echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`"
-	exit ;;
+	DRAGONFLY_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+	GUESS=$UNAME_MACHINE-unknown-dragonfly$DRAGONFLY_REL
+	;;
     *:*VMS:*:*)
 	UNAME_MACHINE=`(uname -p) 2>/dev/null`
-	case "$UNAME_MACHINE" in
-	    A*) echo alpha-dec-vms ; exit ;;
-	    I*) echo ia64-dec-vms ; exit ;;
-	    V*) echo vax-dec-vms ; exit ;;
+	case $UNAME_MACHINE in
+	    A*) GUESS=alpha-dec-vms ;;
+	    I*) GUESS=ia64-dec-vms ;;
+	    V*) GUESS=vax-dec-vms ;;
 	esac ;;
     *:XENIX:*:SysV)
-	echo i386-pc-xenix
-	exit ;;
+	GUESS=i386-pc-xenix
+	;;
     i*86:skyos:*:*)
-	echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`"
-	exit ;;
+	SKYOS_REL=`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`
+	GUESS=$UNAME_MACHINE-pc-skyos$SKYOS_REL
+	;;
     i*86:rdos:*:*)
-	echo "$UNAME_MACHINE"-pc-rdos
-	exit ;;
-    i*86:AROS:*:*)
-	echo "$UNAME_MACHINE"-pc-aros
-	exit ;;
+	GUESS=$UNAME_MACHINE-pc-rdos
+	;;
+    *:AROS:*:*)
+	GUESS=$UNAME_MACHINE-unknown-aros
+	;;
     x86_64:VMkernel:*:*)
-	echo "$UNAME_MACHINE"-unknown-esx
-	exit ;;
+	GUESS=$UNAME_MACHINE-unknown-esx
+	;;
     amd64:Isilon\ OneFS:*:*)
-	echo x86_64-unknown-onefs
-	exit ;;
+	GUESS=x86_64-unknown-onefs
+	;;
     *:Unleashed:*:*)
-	echo "$UNAME_MACHINE"-unknown-unleashed"$UNAME_RELEASE"
-	exit ;;
+	GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE
+	;;
 esac
 
+# Do we have a guess based on uname results?
+if test "x$GUESS" != x; then
+    echo "$GUESS"
+    exit
+fi
+
+# No uname command or uname output not recognized.
+set_cc_for_build
+cat > "$dummy.c" <<EOF
+#ifdef _SEQUENT_
+#include <sys/types.h>
+#include <sys/utsname.h>
+#endif
+#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
+#if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
+#include <signal.h>
+#if defined(_SIZE_T_) || defined(SIGLOST)
+#include <sys/utsname.h>
+#endif
+#endif
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
+     I don't know....  */
+  printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+  printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+  "4"
+#else
+  ""
+#endif
+  ); exit (0);
+#endif
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+  int version;
+  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+  if (version < 4)
+    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+  else
+    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+  exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+  printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+  printf ("ns32k-encore-mach\n"); exit (0);
+#else
+  printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+  printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+  printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+  printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+  struct utsname un;
+
+  uname(&un);
+  if (strncmp(un.version, "V2", 2) == 0) {
+    printf ("i386-sequent-ptx2\n"); exit (0);
+  }
+  if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+    printf ("i386-sequent-ptx1\n"); exit (0);
+  }
+  printf ("i386-sequent-ptx\n"); exit (0);
+#endif
+
+#if defined (vax)
+#if !defined (ultrix)
+#include <sys/param.h>
+#if defined (BSD)
+#if BSD == 43
+  printf ("vax-dec-bsd4.3\n"); exit (0);
+#else
+#if BSD == 199006
+  printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#else
+  printf ("vax-dec-bsd\n"); exit (0);
+#endif
+#endif
+#else
+  printf ("vax-dec-bsd\n"); exit (0);
+#endif
+#else
+#if defined(_SIZE_T_) || defined(SIGLOST)
+  struct utsname un;
+  uname (&un);
+  printf ("vax-dec-ultrix%s\n", un.release); exit (0);
+#else
+  printf ("vax-dec-ultrix\n"); exit (0);
+#endif
+#endif
+#endif
+#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
+#if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
+#if defined(_SIZE_T_) || defined(SIGLOST)
+  struct utsname *un;
+  uname (&un);
+  printf ("mips-dec-ultrix%s\n", un.release); exit (0);
+#else
+  printf ("mips-dec-ultrix\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (alliant) && defined (i860)
+  printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+  exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`"$dummy"` &&
+	{ echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; }
+
 echo "$0: unable to guess system type" >&2
 
-case "$UNAME_MACHINE:$UNAME_SYSTEM" in
+case $UNAME_MACHINE:$UNAME_SYSTEM in
     mips:Linux | mips64:Linux)
 	# If we got here on MIPS GNU/Linux, output extra information.
 	cat >&2 <<EOF
@@ -1452,9 +1698,17 @@ This script (version $timestamp), has failed to recognize the
 operating system you are using. If your script is old, overwrite *all*
 copies of config.guess and config.sub with the latest versions from:
 
-  https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
+  https://git.savannah.gnu.org/cgit/config.git/plain/config.guess
 and
-  https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
+  https://git.savannah.gnu.org/cgit/config.git/plain/config.sub
+EOF
+
+our_year=`echo $timestamp | sed 's,-.*,,'`
+thisyear=`date +%Y`
+# shellcheck disable=SC2003
+script_age=`expr "$thisyear" - "$our_year"`
+if test "$script_age" -lt 3 ; then
+   cat >&2 <<EOF
 
 If $0 has already been updated, send the following data and any
 information you think might be pertinent to config-patches@gnu.org to
@@ -1482,6 +1736,7 @@ UNAME_RELEASE = "$UNAME_RELEASE"
 UNAME_SYSTEM  = "$UNAME_SYSTEM"
 UNAME_VERSION = "$UNAME_VERSION"
 EOF
+fi
 
 exit 1
 
diff --git a/build/config.sub b/build/config.sub
index a8f3f7e7..d74fb6de 100755
--- a/build/config.sub
+++ b/build/config.sub
@@ -1,8 +1,10 @@
 #! /bin/sh
 # Configuration validation subroutine script.
-#   Copyright 1992-2019 Free Software Foundation, Inc.
+#   Copyright 1992-2021 Free Software Foundation, Inc.
 
-timestamp='2019-01-01'
+# shellcheck disable=SC2006,SC2268 # see below for rationale
+
+timestamp='2021-08-14'
 
 # This file is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
@@ -33,7 +35,7 @@ timestamp='2019-01-01'
 # Otherwise, we print the canonical config type on stdout and succeed.
 
 # You can get the latest version of this script from:
-# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
+# https://git.savannah.gnu.org/cgit/config.git/plain/config.sub
 
 # This file is supposed to be the same for all GNU packages
 # and recognize all the CPU types, system types and aliases
@@ -50,6 +52,13 @@ timestamp='2019-01-01'
 #	CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
 # It is wrong to echo any other type of specification.
 
+# The "shellcheck disable" line above the timestamp inhibits complaints
+# about features and limitations of the classic Bourne shell that were
+# superseded or lifted in POSIX.  However, this script identifies a wide
+# variety of pre-POSIX systems that do not have POSIX shells at all, and
+# even some reasonably current systems (Solaris 10 as case-in-point) still
+# have a pre-POSIX /bin/sh.
+
 me=`echo "$0" | sed -e 's,.*/,,'`
 
 usage="\
@@ -67,7 +76,7 @@ Report bugs and patches to <config-patches@gnu.org>."
 version="\
 GNU config.sub ($timestamp)
 
-Copyright 1992-2019 Free Software Foundation, Inc.
+Copyright 1992-2021 Free Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -111,9 +120,12 @@ case $# in
 esac
 
 # Split fields of configuration type
+# shellcheck disable=SC2162
+saved_IFS=$IFS
 IFS="-" read field1 field2 field3 field4 <<EOF
 $1
 EOF
+IFS=$saved_IFS
 
 # Separate into logical components for further validation
 case $1 in
@@ -123,28 +135,27 @@ case $1 in
 		;;
 	*-*-*-*)
 		basic_machine=$field1-$field2
-		os=$field3-$field4
+		basic_os=$field3-$field4
 		;;
 	*-*-*)
 		# Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two
 		# parts
 		maybe_os=$field2-$field3
 		case $maybe_os in
-			nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc \
-			| linux-newlib* | linux-musl* | linux-uclibc* | uclinux-uclibc* \
+			nto-qnx* | linux-* | uclinux-uclibc* \
 			| uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \
 			| netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \
 			| storm-chaos* | os2-emx* | rtmk-nova*)
 				basic_machine=$field1
-				os=$maybe_os
+				basic_os=$maybe_os
 				;;
 			android-linux)
 				basic_machine=$field1-unknown
-				os=linux-android
+				basic_os=linux-android
 				;;
 			*)
 				basic_machine=$field1-$field2
-				os=$field3
+				basic_os=$field3
 				;;
 		esac
 		;;
@@ -153,7 +164,7 @@ case $1 in
 		case $field1-$field2 in
 			decstation-3100)
 				basic_machine=mips-dec
-				os=
+				basic_os=
 				;;
 			*-*)
 				# Second component is usually, but not always the OS
@@ -161,7 +172,11 @@ case $1 in
 					# Prevent following clause from handling this valid os
 					sun*os*)
 						basic_machine=$field1
-						os=$field2
+						basic_os=$field2
+						;;
+					zephyr*)
+						basic_machine=$field1-unknown
+						basic_os=$field2
 						;;
 					# Manufacturers
 					dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \
@@ -174,11 +189,11 @@ case $1 in
 					| microblaze* | sim | cisco \
 					| oki | wec | wrs | winbond)
 						basic_machine=$field1-$field2
-						os=
+						basic_os=
 						;;
 					*)
 						basic_machine=$field1
-						os=$field2
+						basic_os=$field2
 						;;
 				esac
 			;;
@@ -190,450 +205,451 @@ case $1 in
 		case $field1 in
 			386bsd)
 				basic_machine=i386-pc
-				os=bsd
+				basic_os=bsd
 				;;
 			a29khif)
 				basic_machine=a29k-amd
-				os=udi
+				basic_os=udi
 				;;
 			adobe68k)
 				basic_machine=m68010-adobe
-				os=scout
+				basic_os=scout
 				;;
 			alliant)
 				basic_machine=fx80-alliant
-				os=
+				basic_os=
 				;;
 			altos | altos3068)
 				basic_machine=m68k-altos
-				os=
+				basic_os=
 				;;
 			am29k)
 				basic_machine=a29k-none
-				os=bsd
+				basic_os=bsd
 				;;
 			amdahl)
 				basic_machine=580-amdahl
-				os=sysv
+				basic_os=sysv
 				;;
 			amiga)
 				basic_machine=m68k-unknown
-				os=
+				basic_os=
 				;;
 			amigaos | amigados)
 				basic_machine=m68k-unknown
-				os=amigaos
+				basic_os=amigaos
 				;;
 			amigaunix | amix)
 				basic_machine=m68k-unknown
-				os=sysv4
+				basic_os=sysv4
 				;;
 			apollo68)
 				basic_machine=m68k-apollo
-				os=sysv
+				basic_os=sysv
 				;;
 			apollo68bsd)
 				basic_machine=m68k-apollo
-				os=bsd
+				basic_os=bsd
 				;;
 			aros)
 				basic_machine=i386-pc
-				os=aros
+				basic_os=aros
 				;;
 			aux)
 				basic_machine=m68k-apple
-				os=aux
+				basic_os=aux
 				;;
 			balance)
 				basic_machine=ns32k-sequent
-				os=dynix
+				basic_os=dynix
 				;;
 			blackfin)
 				basic_machine=bfin-unknown
-				os=linux
+				basic_os=linux
 				;;
 			cegcc)
 				basic_machine=arm-unknown
-				os=cegcc
+				basic_os=cegcc
 				;;
 			convex-c1)
 				basic_machine=c1-convex
-				os=bsd
+				basic_os=bsd
 				;;
 			convex-c2)
 				basic_machine=c2-convex
-				os=bsd
+				basic_os=bsd
 				;;
 			convex-c32)
 				basic_machine=c32-convex
-				os=bsd
+				basic_os=bsd
 				;;
 			convex-c34)
 				basic_machine=c34-convex
-				os=bsd
+				basic_os=bsd
 				;;
 			convex-c38)
 				basic_machine=c38-convex
-				os=bsd
+				basic_os=bsd
 				;;
 			cray)
 				basic_machine=j90-cray
-				os=unicos
+				basic_os=unicos
 				;;
 			crds | unos)
 				basic_machine=m68k-crds
-				os=
+				basic_os=
 				;;
 			da30)
 				basic_machine=m68k-da30
-				os=
+				basic_os=
 				;;
 			decstation | pmax | pmin | dec3100 | decstatn)
 				basic_machine=mips-dec
-				os=
+				basic_os=
 				;;
 			delta88)
 				basic_machine=m88k-motorola
-				os=sysv3
+				basic_os=sysv3
 				;;
 			dicos)
 				basic_machine=i686-pc
-				os=dicos
+				basic_os=dicos
 				;;
 			djgpp)
 				basic_machine=i586-pc
-				os=msdosdjgpp
+				basic_os=msdosdjgpp
 				;;
 			ebmon29k)
 				basic_machine=a29k-amd
-				os=ebmon
+				basic_os=ebmon
 				;;
 			es1800 | OSE68k | ose68k | ose | OSE)
 				basic_machine=m68k-ericsson
-				os=ose
+				basic_os=ose
 				;;
 			gmicro)
 				basic_machine=tron-gmicro
-				os=sysv
+				basic_os=sysv
 				;;
 			go32)
 				basic_machine=i386-pc
-				os=go32
+				basic_os=go32
 				;;
 			h8300hms)
 				basic_machine=h8300-hitachi
-				os=hms
+				basic_os=hms
 				;;
 			h8300xray)
 				basic_machine=h8300-hitachi
-				os=xray
+				basic_os=xray
 				;;
 			h8500hms)
 				basic_machine=h8500-hitachi
-				os=hms
+				basic_os=hms
 				;;
 			harris)
 				basic_machine=m88k-harris
-				os=sysv3
+				basic_os=sysv3
 				;;
-			hp300)
+			hp300 | hp300hpux)
 				basic_machine=m68k-hp
+				basic_os=hpux
 				;;
 			hp300bsd)
 				basic_machine=m68k-hp
-				os=bsd
-				;;
-			hp300hpux)
-				basic_machine=m68k-hp
-				os=hpux
+				basic_os=bsd
 				;;
 			hppaosf)
 				basic_machine=hppa1.1-hp
-				os=osf
+				basic_os=osf
 				;;
 			hppro)
 				basic_machine=hppa1.1-hp
-				os=proelf
+				basic_os=proelf
 				;;
 			i386mach)
 				basic_machine=i386-mach
-				os=mach
-				;;
-			vsta)
-				basic_machine=i386-pc
-				os=vsta
+				basic_os=mach
 				;;
 			isi68 | isi)
 				basic_machine=m68k-isi
-				os=sysv
+				basic_os=sysv
 				;;
 			m68knommu)
 				basic_machine=m68k-unknown
-				os=linux
+				basic_os=linux
 				;;
 			magnum | m3230)
 				basic_machine=mips-mips
-				os=sysv
+				basic_os=sysv
 				;;
 			merlin)
 				basic_machine=ns32k-utek
-				os=sysv
+				basic_os=sysv
 				;;
 			mingw64)
 				basic_machine=x86_64-pc
-				os=mingw64
+				basic_os=mingw64
 				;;
 			mingw32)
 				basic_machine=i686-pc
-				os=mingw32
+				basic_os=mingw32
 				;;
 			mingw32ce)
 				basic_machine=arm-unknown
-				os=mingw32ce
+				basic_os=mingw32ce
 				;;
 			monitor)
 				basic_machine=m68k-rom68k
-				os=coff
+				basic_os=coff
 				;;
 			morphos)
 				basic_machine=powerpc-unknown
-				os=morphos
+				basic_os=morphos
 				;;
 			moxiebox)
 				basic_machine=moxie-unknown
-				os=moxiebox
+				basic_os=moxiebox
 				;;
 			msdos)
 				basic_machine=i386-pc
-				os=msdos
+				basic_os=msdos
 				;;
 			msys)
 				basic_machine=i686-pc
-				os=msys
+				basic_os=msys
 				;;
 			mvs)
 				basic_machine=i370-ibm
-				os=mvs
+				basic_os=mvs
 				;;
 			nacl)
 				basic_machine=le32-unknown
-				os=nacl
+				basic_os=nacl
 				;;
 			ncr3000)
 				basic_machine=i486-ncr
-				os=sysv4
+				basic_os=sysv4
 				;;
 			netbsd386)
 				basic_machine=i386-pc
-				os=netbsd
+				basic_os=netbsd
 				;;
 			netwinder)
 				basic_machine=armv4l-rebel
-				os=linux
+				basic_os=linux
 				;;
 			news | news700 | news800 | news900)
 				basic_machine=m68k-sony
-				os=newsos
+				basic_os=newsos
 				;;
 			news1000)
 				basic_machine=m68030-sony
-				os=newsos
+				basic_os=newsos
 				;;
 			necv70)
 				basic_machine=v70-nec
-				os=sysv
+				basic_os=sysv
 				;;
 			nh3000)
 				basic_machine=m68k-harris
-				os=cxux
+				basic_os=cxux
 				;;
 			nh[45]000)
 				basic_machine=m88k-harris
-				os=cxux
+				basic_os=cxux
 				;;
 			nindy960)
 				basic_machine=i960-intel
-				os=nindy
+				basic_os=nindy
 				;;
 			mon960)
 				basic_machine=i960-intel
-				os=mon960
+				basic_os=mon960
 				;;
 			nonstopux)
 				basic_machine=mips-compaq
-				os=nonstopux
+				basic_os=nonstopux
 				;;
 			os400)
 				basic_machine=powerpc-ibm
-				os=os400
+				basic_os=os400
 				;;
 			OSE68000 | ose68000)
 				basic_machine=m68000-ericsson
-				os=ose
+				basic_os=ose
 				;;
 			os68k)
 				basic_machine=m68k-none
-				os=os68k
+				basic_os=os68k
 				;;
 			paragon)
 				basic_machine=i860-intel
-				os=osf
+				basic_os=osf
 				;;
 			parisc)
 				basic_machine=hppa-unknown
-				os=linux
+				basic_os=linux
+				;;
+			psp)
+				basic_machine=mipsallegrexel-sony
+				basic_os=psp
 				;;
 			pw32)
 				basic_machine=i586-unknown
-				os=pw32
+				basic_os=pw32
 				;;
 			rdos | rdos64)
 				basic_machine=x86_64-pc
-				os=rdos
+				basic_os=rdos
 				;;
 			rdos32)
 				basic_machine=i386-pc
-				os=rdos
+				basic_os=rdos
 				;;
 			rom68k)
 				basic_machine=m68k-rom68k
-				os=coff
+				basic_os=coff
 				;;
 			sa29200)
 				basic_machine=a29k-amd
-				os=udi
+				basic_os=udi
 				;;
 			sei)
 				basic_machine=mips-sei
-				os=seiux
+				basic_os=seiux
 				;;
 			sequent)
 				basic_machine=i386-sequent
-				os=
+				basic_os=
 				;;
 			sps7)
 				basic_machine=m68k-bull
-				os=sysv2
+				basic_os=sysv2
 				;;
 			st2000)
 				basic_machine=m68k-tandem
-				os=
+				basic_os=
 				;;
 			stratus)
 				basic_machine=i860-stratus
-				os=sysv4
+				basic_os=sysv4
 				;;
 			sun2)
 				basic_machine=m68000-sun
-				os=
+				basic_os=
 				;;
 			sun2os3)
 				basic_machine=m68000-sun
-				os=sunos3
+				basic_os=sunos3
 				;;
 			sun2os4)
 				basic_machine=m68000-sun
-				os=sunos4
+				basic_os=sunos4
 				;;
 			sun3)
 				basic_machine=m68k-sun
-				os=
+				basic_os=
 				;;
 			sun3os3)
 				basic_machine=m68k-sun
-				os=sunos3
+				basic_os=sunos3
 				;;
 			sun3os4)
 				basic_machine=m68k-sun
-				os=sunos4
+				basic_os=sunos4
 				;;
 			sun4)
 				basic_machine=sparc-sun
-				os=
+				basic_os=
 				;;
 			sun4os3)
 				basic_machine=sparc-sun
-				os=sunos3
+				basic_os=sunos3
 				;;
 			sun4os4)
 				basic_machine=sparc-sun
-				os=sunos4
+				basic_os=sunos4
 				;;
 			sun4sol2)
 				basic_machine=sparc-sun
-				os=solaris2
+				basic_os=solaris2
 				;;
 			sun386 | sun386i | roadrunner)
 				basic_machine=i386-sun
-				os=
+				basic_os=
 				;;
 			sv1)
 				basic_machine=sv1-cray
-				os=unicos
+				basic_os=unicos
 				;;
 			symmetry)
 				basic_machine=i386-sequent
-				os=dynix
+				basic_os=dynix
 				;;
 			t3e)
 				basic_machine=alphaev5-cray
-				os=unicos
+				basic_os=unicos
 				;;
 			t90)
 				basic_machine=t90-cray
-				os=unicos
+				basic_os=unicos
 				;;
 			toad1)
 				basic_machine=pdp10-xkl
-				os=tops20
+				basic_os=tops20
 				;;
 			tpf)
 				basic_machine=s390x-ibm
-				os=tpf
+				basic_os=tpf
 				;;
 			udi29k)
 				basic_machine=a29k-amd
-				os=udi
+				basic_os=udi
 				;;
 			ultra3)
 				basic_machine=a29k-nyu
-				os=sym1
+				basic_os=sym1
 				;;
 			v810 | necv810)
 				basic_machine=v810-nec
-				os=none
+				basic_os=none
 				;;
 			vaxv)
 				basic_machine=vax-dec
-				os=sysv
+				basic_os=sysv
 				;;
 			vms)
 				basic_machine=vax-dec
-				os=vms
+				basic_os=vms
+				;;
+			vsta)
+				basic_machine=i386-pc
+				basic_os=vsta
 				;;
 			vxworks960)
 				basic_machine=i960-wrs
-				os=vxworks
+				basic_os=vxworks
 				;;
 			vxworks68)
 				basic_machine=m68k-wrs
-				os=vxworks
+				basic_os=vxworks
 				;;
 			vxworks29k)
 				basic_machine=a29k-wrs
-				os=vxworks
+				basic_os=vxworks
 				;;
 			xbox)
 				basic_machine=i686-pc
-				os=mingw32
+				basic_os=mingw32
 				;;
 			ymp)
 				basic_machine=ymp-cray
-				os=unicos
+				basic_os=unicos
 				;;
 			*)
 				basic_machine=$1
-				os=
+				basic_os=
 				;;
 		esac
 		;;
@@ -685,17 +701,17 @@ case $basic_machine in
 	bluegene*)
 		cpu=powerpc
 		vendor=ibm
-		os=cnk
+		basic_os=cnk
 		;;
 	decsystem10* | dec10*)
 		cpu=pdp10
 		vendor=dec
-		os=tops10
+		basic_os=tops10
 		;;
 	decsystem20* | dec20*)
 		cpu=pdp10
 		vendor=dec
-		os=tops20
+		basic_os=tops20
 		;;
 	delta | 3300 | motorola-3300 | motorola-delta \
 	      | 3300-motorola | delta-motorola)
@@ -705,7 +721,7 @@ case $basic_machine in
 	dpx2*)
 		cpu=m68k
 		vendor=bull
-		os=sysv3
+		basic_os=sysv3
 		;;
 	encore | umax | mmax)
 		cpu=ns32k
@@ -714,7 +730,7 @@ case $basic_machine in
 	elxsi)
 		cpu=elxsi
 		vendor=elxsi
-		os=${os:-bsd}
+		basic_os=${basic_os:-bsd}
 		;;
 	fx2800)
 		cpu=i860
@@ -727,7 +743,7 @@ case $basic_machine in
 	h3050r* | hiux*)
 		cpu=hppa1.1
 		vendor=hitachi
-		os=hiuxwe2
+		basic_os=hiuxwe2
 		;;
 	hp3k9[0-9][0-9] | hp9[0-9][0-9])
 		cpu=hppa1.0
@@ -770,36 +786,36 @@ case $basic_machine in
 	i*86v32)
 		cpu=`echo "$1" | sed -e 's/86.*/86/'`
 		vendor=pc
-		os=sysv32
+		basic_os=sysv32
 		;;
 	i*86v4*)
 		cpu=`echo "$1" | sed -e 's/86.*/86/'`
 		vendor=pc
-		os=sysv4
+		basic_os=sysv4
 		;;
 	i*86v)
 		cpu=`echo "$1" | sed -e 's/86.*/86/'`
 		vendor=pc
-		os=sysv
+		basic_os=sysv
 		;;
 	i*86sol2)
 		cpu=`echo "$1" | sed -e 's/86.*/86/'`
 		vendor=pc
-		os=solaris2
+		basic_os=solaris2
 		;;
 	j90 | j90-cray)
 		cpu=j90
 		vendor=cray
-		os=${os:-unicos}
+		basic_os=${basic_os:-unicos}
 		;;
 	iris | iris4d)
 		cpu=mips
 		vendor=sgi
-		case $os in
+		case $basic_os in
 		    irix*)
 			;;
 		    *)
-			os=irix4
+			basic_os=irix4
 			;;
 		esac
 		;;
@@ -810,24 +826,26 @@ case $basic_machine in
 	*mint | mint[0-9]* | *MiNT | *MiNT[0-9]*)
 		cpu=m68k
 		vendor=atari
-		os=mint
+		basic_os=mint
 		;;
 	news-3600 | risc-news)
 		cpu=mips
 		vendor=sony
-		os=newsos
+		basic_os=newsos
 		;;
 	next | m*-next)
 		cpu=m68k
 		vendor=next
-		case $os in
-		    nextstep* )
+		case $basic_os in
+		    openstep*)
+		        ;;
+		    nextstep*)
 			;;
 		    ns2*)
-		      os=nextstep2
+		      basic_os=nextstep2
 			;;
 		    *)
-		      os=nextstep3
+		      basic_os=nextstep3
 			;;
 		esac
 		;;
@@ -838,12 +856,12 @@ case $basic_machine in
 	op50n-* | op60c-*)
 		cpu=hppa1.1
 		vendor=oki
-		os=proelf
+		basic_os=proelf
 		;;
 	pa-hitachi)
 		cpu=hppa1.1
 		vendor=hitachi
-		os=hiuxwe2
+		basic_os=hiuxwe2
 		;;
 	pbd)
 		cpu=sparc
@@ -880,12 +898,12 @@ case $basic_machine in
 	sde)
 		cpu=mipsisa32
 		vendor=sde
-		os=${os:-elf}
+		basic_os=${basic_os:-elf}
 		;;
 	simso-wrs)
 		cpu=sparclite
 		vendor=wrs
-		os=vxworks
+		basic_os=vxworks
 		;;
 	tower | tower-32)
 		cpu=m68k
@@ -902,7 +920,7 @@ case $basic_machine in
 	w89k-*)
 		cpu=hppa1.1
 		vendor=winbond
-		os=proelf
+		basic_os=proelf
 		;;
 	none)
 		cpu=none
@@ -918,9 +936,12 @@ case $basic_machine in
 		;;
 
 	*-*)
+		# shellcheck disable=SC2162
+		saved_IFS=$IFS
 		IFS="-" read cpu vendor <<EOF
 $basic_machine
 EOF
+		IFS=$saved_IFS
 		;;
 	# We use `pc' rather than `unknown'
 	# because (1) that's what they normally are, and
@@ -954,11 +975,11 @@ case $cpu-$vendor in
 	# some cases the only manufacturer, in others, it is the most popular.
 	craynv-unknown)
 		vendor=cray
-		os=${os:-unicosmp}
+		basic_os=${basic_os:-unicosmp}
 		;;
 	c90-unknown | c90-cray)
 		vendor=cray
-		os=${os:-unicos}
+		basic_os=${Basic_os:-unicos}
 		;;
 	fx80-unknown)
 		vendor=alliant
@@ -1002,7 +1023,7 @@ case $cpu-$vendor in
 	dpx20-unknown | dpx20-bull)
 		cpu=rs6000
 		vendor=bull
-		os=${os:-bosx}
+		basic_os=${basic_os:-bosx}
 		;;
 
 	# Here we normalize CPU types irrespective of the vendor
@@ -1011,7 +1032,7 @@ case $cpu-$vendor in
 		;;
 	blackfin-*)
 		cpu=bfin
-		os=linux
+		basic_os=linux
 		;;
 	c54x-*)
 		cpu=tic54x
@@ -1024,7 +1045,7 @@ case $cpu-$vendor in
 		;;
 	e500v[12]-*)
 		cpu=powerpc
-		os=$os"spe"
+		basic_os=${basic_os}"spe"
 		;;
 	mips3*-*)
 		cpu=mips64
@@ -1034,7 +1055,7 @@ case $cpu-$vendor in
 		;;
 	m68knommu-*)
 		cpu=m68k
-		os=linux
+		basic_os=linux
 		;;
 	m9s12z-* | m68hcs12z-* | hcs12z-* | s12z-*)
 		cpu=s12z
@@ -1044,7 +1065,7 @@ case $cpu-$vendor in
 		;;
 	parisc-*)
 		cpu=hppa
-		os=linux
+		basic_os=linux
 		;;
 	pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
 		cpu=i586
@@ -1100,11 +1121,14 @@ case $cpu-$vendor in
 	xscale-* | xscalee[bl]-*)
 		cpu=`echo "$cpu" | sed 's/^xscale/arm/'`
 		;;
+	arm64-*)
+		cpu=aarch64
+		;;
 
 	# Recognize the canonical CPU Types that limit and/or modify the
 	# company names they are paired with.
 	cr16-*)
-		os=${os:-elf}
+		basic_os=${basic_os:-elf}
 		;;
 	crisv32-* | etraxfs*-*)
 		cpu=crisv32
@@ -1115,7 +1139,7 @@ case $cpu-$vendor in
 		vendor=axis
 		;;
 	crx-*)
-		os=${os:-elf}
+		basic_os=${basic_os:-elf}
 		;;
 	neo-tandem)
 		cpu=neo
@@ -1137,16 +1161,12 @@ case $cpu-$vendor in
 		cpu=nsx
 		vendor=tandem
 		;;
-	s390-*)
-		cpu=s390
-		vendor=ibm
-		;;
-	s390x-*)
-		cpu=s390x
-		vendor=ibm
+	mipsallegrexel-sony)
+		cpu=mipsallegrexel
+		vendor=sony
 		;;
 	tile*-*)
-		os=${os:-linux-gnu}
+		basic_os=${basic_os:-linux-gnu}
 		;;
 
 	*)
@@ -1162,13 +1182,13 @@ case $cpu-$vendor in
 			| alphapca5[67] | alpha64pca5[67] \
 			| am33_2.0 \
 			| amdgcn \
-			| arc | arceb \
-			| arm  | arm[lb]e | arme[lb] | armv* \
+			| arc | arceb | arc32 | arc64 \
+			| arm | arm[lb]e | arme[lb] | armv* \
 			| avr | avr32 \
 			| asmjs \
 			| ba \
 			| be32 | be64 \
-			| bfin | bs2000 \
+			| bfin | bpf | bs2000 \
 			| c[123]* | c30 | [cjt]90 | c4x \
 			| c8051 | clipper | craynv | csky | cydra \
 			| d10v | d30v | dlx | dsp16xx \
@@ -1182,14 +1202,15 @@ case $cpu-$vendor in
 			| k1om \
 			| le32 | le64 \
 			| lm32 \
+			| loongarch32 | loongarch64 | loongarchx32 \
 			| m32c | m32r | m32rle \
-			| m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k | v70 | w65 \
-			| m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip \
+			| m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \
+			| m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \
 			| m88110 | m88k | maxq | mb | mcore | mep | metag \
 			| microblaze | microblazeel \
 			| mips | mipsbe | mipseb | mipsel | mipsle \
 			| mips16 \
-			| mips64 | mips64el \
+			| mips64 | mips64eb | mips64el \
 			| mips64octeon | mips64octeonel \
 			| mips64orion | mips64orionel \
 			| mips64r5900 | mips64r5900el \
@@ -1200,9 +1221,13 @@ case $cpu-$vendor in
 			| mips64vr5900 | mips64vr5900el \
 			| mipsisa32 | mipsisa32el \
 			| mipsisa32r2 | mipsisa32r2el \
+			| mipsisa32r3 | mipsisa32r3el \
+			| mipsisa32r5 | mipsisa32r5el \
 			| mipsisa32r6 | mipsisa32r6el \
 			| mipsisa64 | mipsisa64el \
 			| mipsisa64r2 | mipsisa64r2el \
+			| mipsisa64r3 | mipsisa64r3el \
+			| mipsisa64r5 | mipsisa64r5el \
 			| mipsisa64r6 | mipsisa64r6el \
 			| mipsisa64sb1 | mipsisa64sb1el \
 			| mipsisa64sr71k | mipsisa64sr71kel \
@@ -1216,32 +1241,37 @@ case $cpu-$vendor in
 			| nds32 | nds32le | nds32be \
 			| nfp \
 			| nios | nios2 | nios2eb | nios2el \
-			| none | np1 | ns16k | ns32k \
+			| none | np1 | ns16k | ns32k | nvptx \
 			| open8 \
 			| or1k* \
 			| or32 \
 			| orion \
+			| picochip \
 			| pdp10 | pdp11 | pj | pjl | pn | power \
 			| powerpc | powerpc64 | powerpc64le | powerpcle | powerpcspe \
 			| pru \
 			| pyramid \
-			| riscv | riscv32 | riscv64 \
+			| riscv | riscv32 | riscv32be | riscv64 | riscv64be \
 			| rl78 | romp | rs6000 | rx \
+			| s390 | s390x \
 			| score \
-			| sh | sh[1234] | sh[24]a | sh[24]ae[lb] | sh[23]e | she[lb] | sh[lb]e \
+			| sh | shl \
+			| sh[1234] | sh[24]a | sh[24]ae[lb] | sh[23]e | she[lb] | sh[lb]e \
 			| sh[1234]e[lb] |  sh[12345][lb]e | sh[23]ele | sh64 | sh64le \
 			| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet \
 			| sparclite \
 			| sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \
 			| spu \
 			| tahoe \
+			| thumbv7* \
 			| tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \
 			| tron \
 			| ubicom32 \
-			| v850 | v850e | v850e1 | v850es | v850e2 | v850e2v3 \
+			| v70 | v850 | v850e | v850e1 | v850es | v850e2 | v850e2v3 \
 			| vax \
 			| visium \
-			| wasm32 \
+			| w65 \
+			| wasm32 | wasm64 \
 			| we32k \
 			| x86 | x86_64 | xc16x | xgate | xps100 \
 			| xstormy16 | xtensa* \
@@ -1271,8 +1301,49 @@ esac
 
 # Decode manufacturer-specific aliases for certain operating systems.
 
-if [ x$os != x ]
+if test x$basic_os != x
 then
+
+# First recognize some ad-hoc caes, or perhaps split kernel-os, or else just
+# set os.
+case $basic_os in
+	gnu/linux*)
+		kernel=linux
+		os=`echo "$basic_os" | sed -e 's|gnu/linux|gnu|'`
+		;;
+	os2-emx)
+		kernel=os2
+		os=`echo "$basic_os" | sed -e 's|os2-emx|emx|'`
+		;;
+	nto-qnx*)
+		kernel=nto
+		os=`echo "$basic_os" | sed -e 's|nto-qnx|qnx|'`
+		;;
+	*-*)
+		# shellcheck disable=SC2162
+		saved_IFS=$IFS
+		IFS="-" read kernel os <<EOF
+$basic_os
+EOF
+		IFS=$saved_IFS
+		;;
+	# Default OS when just kernel was specified
+	nto*)
+		kernel=nto
+		os=`echo "$basic_os" | sed -e 's|nto|qnx|'`
+		;;
+	linux*)
+		kernel=linux
+		os=`echo "$basic_os" | sed -e 's|linux|gnu|'`
+		;;
+	*)
+		kernel=
+		os=$basic_os
+		;;
+esac
+
+# Now, normalize the OS (knowing we just have one component, it's not a kernel,
+# etc.)
 case $os in
 	# First match some system type aliases that might get confused
 	# with valid system types.
@@ -1284,7 +1355,7 @@ case $os in
 		os=cnk
 		;;
 	solaris1 | solaris1.*)
-		os=`echo $os | sed -e 's|solaris1|sunos4|'`
+		os=`echo "$os" | sed -e 's|solaris1|sunos4|'`
 		;;
 	solaris)
 		os=solaris2
@@ -1292,9 +1363,6 @@ case $os in
 	unixware*)
 		os=sysv4.2uw
 		;;
-	gnu/linux*)
-		os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
-		;;
 	# es1800 is here to avoid being matched by es* (a different OS)
 	es1800*)
 		os=ose
@@ -1316,12 +1384,9 @@ case $os in
 		os=sco3.2v4
 		;;
 	sco3.2.[4-9]*)
-		os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+		os=`echo "$os" | sed -e 's/sco3.2./sco3.2v/'`
 		;;
-	sco3.2v[4-9]* | sco5v6*)
-		# Don't forget version if it is 3.2v4 or newer.
-		;;
-	scout)
+	sco*v* | scout)
 		# Don't match below
 		;;
 	sco*)
@@ -1330,77 +1395,25 @@ case $os in
 	psos*)
 		os=psos
 		;;
-	# Now accept the basic system types.
-	# The portable systems comes first.
-	# Each alternative MUST end in a * to match a version number.
-	# sysv* is not here because it comes later, after sysvr4.
-	gnu* | bsd* | mach* | minix* | genix* | ultrix* | irix* \
-	     | *vms* | esix* | aix* | cnk* | sunos | sunos[34]*\
-	     | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \
-	     | sym* | kopensolaris* | plan9* \
-	     | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \
-	     | aos* | aros* | cloudabi* | sortix* \
-	     | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \
-	     | clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \
-	     | knetbsd* | mirbsd* | netbsd* \
-	     | bitrig* | openbsd* | solidbsd* | libertybsd* \
-	     | ekkobsd* | kfreebsd* | freebsd* | riscix* | lynxos* \
-	     | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \
-	     | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \
-	     | udi* | eabi* | lites* | ieee* | go32* | aux* | hcos* \
-	     | chorusrdb* | cegcc* | glidix* \
-	     | cygwin* | msys* | pe* | moss* | proelf* | rtems* \
-	     | midipix* | mingw32* | mingw64* | linux-gnu* | linux-android* \
-	     | linux-newlib* | linux-musl* | linux-uclibc* \
-	     | uxpv* | beos* | mpeix* | udk* | moxiebox* \
-	     | interix* | uwin* | mks* | rhapsody* | darwin* \
-	     | openstep* | oskit* | conix* | pw32* | nonstopux* \
-	     | storm-chaos* | tops10* | tenex* | tops20* | its* \
-	     | os2* | vos* | palmos* | uclinux* | nucleus* \
-	     | morphos* | superux* | rtmk* | windiss* \
-	     | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \
-	     | skyos* | haiku* | rdos* | toppers* | drops* | es* \
-	     | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
-	     | midnightbsd* | amdhsa* | unleashed* | emscripten*)
-	# Remember, each alternative MUST END IN *, to match a version number.
-		;;
 	qnx*)
-		case $cpu in
-		    x86 | i*86)
-			;;
-		    *)
-			os=nto-$os
-			;;
-		esac
+		os=qnx
 		;;
 	hiux*)
 		os=hiuxwe2
 		;;
-	nto-qnx*)
-		;;
-	nto*)
-		os=`echo $os | sed -e 's|nto|nto-qnx|'`
-		;;
-	sim | xray | os68k* | v88r* \
-	    | windows* | osx | abug | netware* | os9* \
-	    | macos* | mpw* | magic* | mmixware* | mon960* | lnews*)
-		;;
-	linux-dietlibc)
-		os=linux-dietlibc
-		;;
-	linux*)
-		os=`echo $os | sed -e 's|linux|linux-gnu|'`
-		;;
 	lynx*178)
 		os=lynxos178
 		;;
 	lynx*5)
 		os=lynxos5
 		;;
+	lynxos*)
+		# don't get caught up in next wildcard
+		;;
 	lynx*)
 		os=lynxos
 		;;
-	mac*)
+	mac[0-9]*)
 		os=`echo "$os" | sed -e 's|mac|macos|'`
 		;;
 	opened*)
@@ -1445,12 +1458,9 @@ case $os in
 	ns2)
 		os=nextstep2
 		;;
-	nsk*)
-		os=nsk
-		;;
 	# Preserve the version number of sinix5.
 	sinix5.*)
-		os=`echo $os | sed -e 's|sinix|sysv|'`
+		os=`echo "$os" | sed -e 's|sinix|sysv|'`
 		;;
 	sinix*)
 		os=sysv4
@@ -1473,18 +1483,12 @@ case $os in
 	sysvr4)
 		os=sysv4
 		;;
-	# This must come after sysvr4.
-	sysv*)
-		;;
 	ose*)
 		os=ose
 		;;
 	*mint | mint[0-9]* | *MiNT | MiNT[0-9]*)
 		os=mint
 		;;
-	zvmoe)
-		os=zvmoe
-		;;
 	dicos*)
 		os=dicos
 		;;
@@ -1501,19 +1505,11 @@ case $os in
 			;;
 		esac
 		;;
-	nacl*)
-		;;
-	ios)
-		;;
-	none)
-		;;
-	*-eabi)
-		;;
 	*)
-		echo Invalid configuration \`"$1"\': system \`"$os"\' not recognized 1>&2
-		exit 1
+		# No normalization, but not necessarily accepted, that comes below.
 		;;
 esac
+
 else
 
 # Here we handle the default operating systems that come with various machines.
@@ -1526,6 +1522,7 @@ else
 # will signal an error saying that MANUFACTURER isn't an operating
 # system, and we'll never get to this point.
 
+kernel=
 case $cpu-$vendor in
 	score-*)
 		os=elf
@@ -1537,7 +1534,8 @@ case $cpu-$vendor in
 		os=riscix1.2
 		;;
 	arm*-rebel)
-		os=linux
+		kernel=linux
+		os=gnu
 		;;
 	arm*-semi)
 		os=aout
@@ -1703,84 +1701,179 @@ case $cpu-$vendor in
 		os=none
 		;;
 esac
+
 fi
 
+# Now, validate our (potentially fixed-up) OS.
+case $os in
+	# Sometimes we do "kernel-libc", so those need to count as OSes.
+	musl* | newlib* | relibc* | uclibc*)
+		;;
+	# Likewise for "kernel-abi"
+	eabi* | gnueabi*)
+		;;
+	# VxWorks passes extra cpu info in the 4th filed.
+	simlinux | simwindows | spe)
+		;;
+	# Now accept the basic system types.
+	# The portable systems comes first.
+	# Each alternative MUST end in a * to match a version number.
+	gnu* | android* | bsd* | mach* | minix* | genix* | ultrix* | irix* \
+	     | *vms* | esix* | aix* | cnk* | sunos | sunos[34]* \
+	     | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \
+	     | sym* |  plan9* | psp* | sim* | xray* | os68k* | v88r* \
+	     | hiux* | abug | nacl* | netware* | windows* \
+	     | os9* | macos* | osx* | ios* \
+	     | mpw* | magic* | mmixware* | mon960* | lnews* \
+	     | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \
+	     | aos* | aros* | cloudabi* | sortix* | twizzler* \
+	     | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \
+	     | clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \
+	     | mirbsd* | netbsd* | dicos* | openedition* | ose* \
+	     | bitrig* | openbsd* | secbsd* | solidbsd* | libertybsd* | os108* \
+	     | ekkobsd* | freebsd* | riscix* | lynxos* | os400* \
+	     | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \
+	     | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \
+	     | udi* | lites* | ieee* | go32* | aux* | hcos* \
+	     | chorusrdb* | cegcc* | glidix* | serenity* \
+	     | cygwin* | msys* | pe* | moss* | proelf* | rtems* \
+	     | midipix* | mingw32* | mingw64* | mint* \
+	     | uxpv* | beos* | mpeix* | udk* | moxiebox* \
+	     | interix* | uwin* | mks* | rhapsody* | darwin* \
+	     | openstep* | oskit* | conix* | pw32* | nonstopux* \
+	     | storm-chaos* | tops10* | tenex* | tops20* | its* \
+	     | os2* | vos* | palmos* | uclinux* | nucleus* | morphos* \
+	     | scout* | superux* | sysv* | rtmk* | tpf* | windiss* \
+	     | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \
+	     | skyos* | haiku* | rdos* | toppers* | drops* | es* \
+	     | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
+	     | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
+	     | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr*)
+		;;
+	# This one is extra strict with allowed versions
+	sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
+		# Don't forget version if it is 3.2v4 or newer.
+		;;
+	none)
+		;;
+	*)
+		echo Invalid configuration \`"$1"\': OS \`"$os"\' not recognized 1>&2
+		exit 1
+		;;
+esac
+
+# As a final step for OS-related things, validate the OS-kernel combination
+# (given a valid OS), if there is a kernel.
+case $kernel-$os in
+	linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* \
+		   | linux-musl* | linux-relibc* | linux-uclibc* )
+		;;
+	uclinux-uclibc* )
+		;;
+	-dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* )
+		# These are just libc implementations, not actual OSes, and thus
+		# require a kernel.
+		echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2
+		exit 1
+		;;
+	kfreebsd*-gnu* | kopensolaris*-gnu*)
+		;;
+	vxworks-simlinux | vxworks-simwindows | vxworks-spe)
+		;;
+	nto-qnx*)
+		;;
+	os2-emx)
+		;;
+	*-eabi* | *-gnueabi*)
+		;;
+	-*)
+		# Blank kernel with real OS is always fine.
+		;;
+	*-*)
+		echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2
+		exit 1
+		;;
+esac
+
 # Here we handle the case where we know the os, and the CPU type, but not the
 # manufacturer.  We pick the logical manufacturer.
 case $vendor in
 	unknown)
-		case $os in
-			riscix*)
+		case $cpu-$os in
+			*-riscix*)
 				vendor=acorn
 				;;
-			sunos*)
+			*-sunos*)
 				vendor=sun
 				;;
-			cnk*|-aix*)
+			*-cnk* | *-aix*)
 				vendor=ibm
 				;;
-			beos*)
+			*-beos*)
 				vendor=be
 				;;
-			hpux*)
+			*-hpux*)
 				vendor=hp
 				;;
-			mpeix*)
+			*-mpeix*)
 				vendor=hp
 				;;
-			hiux*)
+			*-hiux*)
 				vendor=hitachi
 				;;
-			unos*)
+			*-unos*)
 				vendor=crds
 				;;
-			dgux*)
+			*-dgux*)
 				vendor=dg
 				;;
-			luna*)
+			*-luna*)
 				vendor=omron
 				;;
-			genix*)
+			*-genix*)
 				vendor=ns
 				;;
-			clix*)
+			*-clix*)
 				vendor=intergraph
 				;;
-			mvs* | opened*)
+			*-mvs* | *-opened*)
+				vendor=ibm
+				;;
+			*-os400*)
 				vendor=ibm
 				;;
-			os400*)
+			s390-* | s390x-*)
 				vendor=ibm
 				;;
-			ptx*)
+			*-ptx*)
 				vendor=sequent
 				;;
-			tpf*)
+			*-tpf*)
 				vendor=ibm
 				;;
-			vxsim* | vxworks* | windiss*)
+			*-vxsim* | *-vxworks* | *-windiss*)
 				vendor=wrs
 				;;
-			aux*)
+			*-aux*)
 				vendor=apple
 				;;
-			hms*)
+			*-hms*)
 				vendor=hitachi
 				;;
-			mpw* | macos*)
+			*-mpw* | *-macos*)
 				vendor=apple
 				;;
-			*mint | mint[0-9]* | *MiNT | MiNT[0-9]*)
+			*-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*)
 				vendor=atari
 				;;
-			vos*)
+			*-vos*)
 				vendor=stratus
 				;;
 		esac
 		;;
 esac
 
-echo "$cpu-$vendor-$os"
+echo "$cpu-$vendor-${kernel:+$kernel-}$os"
 exit
 
 # Local variables:
diff --git a/configure b/configure
index 988e3509..c5700a1a 100755
--- a/configure
+++ b/configure
@@ -3430,9 +3430,6 @@ HTTPD_MMN=`$abs_srcdir/build/get-version.sh mmn $abs_srcdir/include/ap_mmn.h MOD
 
 
 
-
-
-
 
 
 
diff --git a/debian/changelog b/debian/changelog
index 7399ed6b..4ae13cf0 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+apache2 (2.4.56-1) unstable; urgency=medium
+
+  * New upstream version (Closes: #1032476, CVE-2023-27522, CVE-2023-25690)
+
+ -- Yadd <yadd@debian.org>  Wed, 08 Mar 2023 06:44:05 +0400
+
 apache2 (2.4.55-1) unstable; urgency=medium
 
   [ Hendrik Jäger ]
@@ -17,7 +23,8 @@ apache2 (2.4.55-1) unstable; urgency=medium
   * Update standards version to 4.6.2, no changes needed.
 
   [ Yadd ]
-  * New upstream version (Closes: CVE-2006-20001, CVE-2022-36760, CVE-2022-37436)
+  * New upstream version (Closes: CVE-2006-20001, CVE-2022-36760,
+    CVE-2022-37436)
 
  -- Yadd <yadd@debian.org>  Wed, 18 Jan 2023 07:41:55 +0400
 
diff --git a/debian/patches/fhs_compliance.patch b/debian/patches/fhs_compliance.patch
index 21de2ebd..e6522c1c 100644
--- a/debian/patches/fhs_compliance.patch
+++ b/debian/patches/fhs_compliance.patch
@@ -6,7 +6,7 @@ Last-Update: 2023-01-18
 
 --- a/configure
 +++ b/configure
-@@ -42078,13 +42078,13 @@
+@@ -42075,13 +42075,13 @@
  ap_prefix="${ap_cur}"
  
  
diff --git a/docs/man/rotatelogs.8 b/docs/man/rotatelogs.8
index f67ee021..29c35da3 100644
--- a/docs/man/rotatelogs.8
+++ b/docs/man/rotatelogs.8
@@ -19,7 +19,7 @@
 .el .ne 3
 .IP "\\$1" \\$2
 ..
-.TH "ROTATELOGS" 8 "2023-01-10" "Apache HTTP Server" "rotatelogs"
+.TH "ROTATELOGS" 8 "2023-03-05" "Apache HTTP Server" "rotatelogs"
 
 .SH NAME
 rotatelogs \- Piped logging program to rotate Apache logs
@@ -58,6 +58,9 @@ Creates the parent directories of the path that the log file will be placed in i
 \fB-t\fR
 Causes the logfile to be truncated instead of rotated\&. This is useful when a log is processed in real time by a command like tail, and there is no need for archived data\&. No suffix will be added to the filename, however format strings containing '%' characters will be respected\&.  
 .TP
+\fB-T\fR
+Causes all but the initial logfile to be truncated when opened\&. This is useful when the format string contains something that will loop around, such as the day of the month\&. Available in 2\&.4\&.56 and later\&.  
+.TP
 \fB-v\fR
 Produce verbose output on STDERR\&. The output contains the result of the configuration parsing, and all file open and close actions\&.  
 .TP
@@ -129,6 +132,15 @@ This configuration will rotate the error logfile whenever it reaches a size of 5
 .PP
 This creates the file \fB/var/log/logfile\fR, truncating the file at startup and then truncating the file once per day\&. It is expected in this scenario that a separate process (such as tail) would process the file in real time\&.
  
+.nf
+ 
+     CustomLog "|bin/rotatelogs -T /var/log/logfile\&.%d 86400" common
+ 
+.fi
+ 
+.PP
+If the server is started (or restarted) on the first of the month, this appends to \fB/var/log/logfile\&.01\fR\&. When a log entry is written on the second of the month, \fB/var/log/logfile\&.02\fR is truncated and new entries will be added to the top\&. This example keeps approximately 1 months worth of logs without external maintenance\&.
+ 
 .SH "PORTABILITY"
  
 .PP
diff --git a/httpd.spec b/httpd.spec
index 7d0a8087..c0c788eb 100644
--- a/httpd.spec
+++ b/httpd.spec
@@ -4,7 +4,7 @@
 
 Summary: Apache HTTP Server
 Name: httpd
-Version: 2.4.55
+Version: 2.4.56
 Release: 1
 URL: http://httpd.apache.org/
 Vendor: Apache Software Foundation
diff --git a/include/ap_release.h b/include/ap_release.h
index b806dc34..c858aaea 100644
--- a/include/ap_release.h
+++ b/include/ap_release.h
@@ -43,7 +43,7 @@
 
 #define AP_SERVER_MAJORVERSION_NUMBER 2
 #define AP_SERVER_MINORVERSION_NUMBER 4
-#define AP_SERVER_PATCHLEVEL_NUMBER   55
+#define AP_SERVER_PATCHLEVEL_NUMBER   56
 #define AP_SERVER_DEVBUILD_BOOLEAN    0
 
 /* Synchronize the above with docs/manual/style/version.ent */
diff --git a/modules/http2/h2_c2_filter.c b/modules/http2/h2_c2_filter.c
index f537a19f..37254fc1 100644
--- a/modules/http2/h2_c2_filter.c
+++ b/modules/http2/h2_c2_filter.c
@@ -615,7 +615,7 @@ apr_status_t h2_c2_filter_catch_h1_out(ap_filter_t* f, apr_bucket_brigade* bb)
     ap_assert(conn_ctx);
     H2_FILTER_LOG("c2_catch_h1_out", f->c, APLOG_TRACE2, 0, "check", bb);
 
-    if (!conn_ctx->has_final_response) {
+    if (!f->c->aborted && !conn_ctx->has_final_response) {
         if (!parser) {
             parser = apr_pcalloc(f->c->pool, sizeof(*parser));
             parser->id = apr_psprintf(f->c->pool, "%s-%d", conn_ctx->id, conn_ctx->stream_id);
diff --git a/modules/http2/mod_proxy_http2.c b/modules/http2/mod_proxy_http2.c
index 3faf0347..aa299b93 100644
--- a/modules/http2/mod_proxy_http2.c
+++ b/modules/http2/mod_proxy_http2.c
@@ -158,6 +158,16 @@ static int proxy_http2_canon(request_rec *r, char *url)
             path = ap_proxy_canonenc(r->pool, url, (int)strlen(url),
                                      enc_path, 0, r->proxyreq);
             search = r->args;
+            if (search && *(ap_scan_vchar_obstext(search))) {
+                /*
+                 * We have a raw control character or a ' ' in r->args.
+                 * Correct encoding was missed.
+                 */
+                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO()
+                              "To be forwarded query string contains control "
+                              "characters or spaces");
+                return HTTP_FORBIDDEN;
+            }
         }
         break;
     case PROXYREQ_PROXY:
diff --git a/modules/ldap/util_ldap.c b/modules/ldap/util_ldap.c
index 4d92ec9a..14b774a0 100644
--- a/modules/ldap/util_ldap.c
+++ b/modules/ldap/util_ldap.c
@@ -2752,12 +2752,14 @@ static const char *util_ldap_set_conn_ttl(cmd_parms *cmd,
                                           void *dummy,
                                           const char *val)
 {
-    apr_interval_time_t timeout;
+    apr_interval_time_t timeout = -1;
     util_ldap_state_t *st =
         (util_ldap_state_t *)ap_get_module_config(cmd->server->module_config,
                                                   &ldap_module);
 
-    if (ap_timeout_parameter_parse(val, &timeout, "s") != APR_SUCCESS) {
+    /* Negative values mean AP_LDAP_CONNPOOL_INFINITE */
+    if (val[0] != '-' &&
+        ap_timeout_parameter_parse(val, &timeout, "s") != APR_SUCCESS) {
         return "LDAPConnectionPoolTTL has wrong format";
     }
 
diff --git a/modules/mappers/mod_rewrite.c b/modules/mappers/mod_rewrite.c
index 94399656..5195ceee 100644
--- a/modules/mappers/mod_rewrite.c
+++ b/modules/mappers/mod_rewrite.c
@@ -173,6 +173,7 @@ static const char* really_last_key = "rewrite_really_last";
 #define RULEFLAG_END                (1<<17)
 #define RULEFLAG_ESCAPENOPLUS       (1<<18)
 #define RULEFLAG_QSLAST             (1<<19)
+#define RULEFLAG_QSNONE             (1<<20) /* programattic only */
 
 /* return code of the rewrite rule
  * the result may be escaped - or not
@@ -769,11 +770,19 @@ static char *escape_absolute_uri(apr_pool_t *p, char *uri, unsigned scheme)
  * split out a QUERY_STRING part from
  * the current URI string
  */
-static void splitout_queryargs(request_rec *r, int qsappend, int qsdiscard, 
-                               int qslast)
+static void splitout_queryargs(request_rec *r, int flags)
 {
     char *q;
     int split, skip;
+    int qsappend = flags & RULEFLAG_QSAPPEND;
+    int qsdiscard = flags & RULEFLAG_QSDISCARD;
+    int qslast = flags & RULEFLAG_QSLAST;
+
+    if (flags & RULEFLAG_QSNONE) {
+        rewritelog((r, 2, NULL, "discarding query string, no parse from substitution"));
+        r->args = NULL;
+        return;
+    }
 
     /* don't touch, unless it's a scheme for which a query string makes sense.
      * See RFC 1738 and RFC 2368.
@@ -798,7 +807,7 @@ static void splitout_queryargs(request_rec *r, int qsappend, int qsdiscard,
         olduri = apr_pstrdup(r->pool, r->filename);
         *q++ = '\0';
         if (qsappend) {
-            if (*q) { 
+            if (*q) {
                 r->args = apr_pstrcat(r->pool, q, "&" , r->args, NULL);
             }
         }
@@ -806,9 +815,9 @@ static void splitout_queryargs(request_rec *r, int qsappend, int qsdiscard,
             r->args = apr_pstrdup(r->pool, q);
         }
 
-        if (r->args) { 
+        if (r->args) {
            len = strlen(r->args);
-      
+
            if (!len) {
                r->args = NULL;
            }
@@ -2761,7 +2770,7 @@ static apr_status_t rewritelock_remove(void *data)
  * XXX: what an inclined parser. Seems we have to leave it so
  *      for backwards compat. *sigh*
  */
-static int parseargline(char *str, char **a1, char **a2, char **a3)
+static int parseargline(char *str, char **a1, char **a2, char **a2_end, char **a3)
 {
     char quote;
 
@@ -2812,8 +2821,10 @@ static int parseargline(char *str, char **a1, char **a2, char **a3)
 
     if (!*str) {
         *a3 = NULL; /* 3rd argument is optional */
+        *a2_end = str;
         return 0;
     }
+    *a2_end = str;
     *str++ = '\0';
 
     while (apr_isspace(*str)) {
@@ -3353,7 +3364,7 @@ static const char *cmd_rewritecond(cmd_parms *cmd, void *in_dconf,
     rewrite_server_conf *sconf;
     rewritecond_entry *newcond;
     ap_regex_t *regexp;
-    char *a1 = NULL, *a2 = NULL, *a3 = NULL;
+    char *a1 = NULL, *a2 = NULL, *a2_end, *a3 = NULL;
     const char *err;
 
     sconf = ap_get_module_config(cmd->server->module_config, &rewrite_module);
@@ -3371,7 +3382,7 @@ static const char *cmd_rewritecond(cmd_parms *cmd, void *in_dconf,
      * of the argument line. So we can use a1 .. a3 without
      * copying them again.
      */
-    if (parseargline(str, &a1, &a2, &a3)) {
+    if (parseargline(str, &a1, &a2, &a2_end, &a3)) {
         return apr_pstrcat(cmd->pool, "RewriteCond: bad argument line '", str,
                            "'", NULL);
     }
@@ -3779,7 +3790,7 @@ static const char *cmd_rewriterule(cmd_parms *cmd, void *in_dconf,
     rewrite_server_conf *sconf;
     rewriterule_entry *newrule;
     ap_regex_t *regexp;
-    char *a1 = NULL, *a2 = NULL, *a3 = NULL;
+    char *a1 = NULL, *a2 = NULL, *a2_end, *a3 = NULL;
     const char *err;
 
     sconf = ap_get_module_config(cmd->server->module_config, &rewrite_module);
@@ -3793,7 +3804,7 @@ static const char *cmd_rewriterule(cmd_parms *cmd, void *in_dconf,
     }
 
     /*  parse the argument line ourself */
-    if (parseargline(str, &a1, &a2, &a3)) {
+    if (parseargline(str, &a1, &a2, &a2_end, &a3)) {
         return apr_pstrcat(cmd->pool, "RewriteRule: bad argument line '", str,
                            "'", NULL);
     }
@@ -3840,6 +3851,16 @@ static const char *cmd_rewriterule(cmd_parms *cmd, void *in_dconf,
         newrule->flags |= RULEFLAG_NOSUB;
     }
 
+    if (*(a2_end-1) == '?') {
+        /* a literal ? at the end of the unsubstituted rewrite rule */
+        newrule->flags |= RULEFLAG_QSNONE;
+    }
+    else if (newrule->flags & RULEFLAG_QSDISCARD) {
+        if (NULL == ap_strchr(newrule->output, '?')) {
+            newrule->flags |= RULEFLAG_QSNONE;
+        }
+    }
+
     /* now, if the server or per-dir config holds an
      * array of RewriteCond entries, we take it for us
      * and clear the array
@@ -4245,9 +4266,7 @@ static int apply_rewrite_rule(rewriterule_entry *p, rewrite_ctx *ctx)
         r->path_info = NULL;
     }
 
-    splitout_queryargs(r, p->flags & RULEFLAG_QSAPPEND, 
-                          p->flags & RULEFLAG_QSDISCARD, 
-                          p->flags & RULEFLAG_QSLAST);
+    splitout_queryargs(r, p->flags);
 
     /* Add the previously stripped per-directory location prefix, unless
      * (1) it's an absolute URL path and
@@ -4729,6 +4748,17 @@ static int hook_uri2file(request_rec *r)
         unsigned skip;
         apr_size_t flen;
 
+        if (r->args && *(ap_scan_vchar_obstext(r->args))) {
+            /*
+             * We have a raw control character or a ' ' in r->args.
+             * Correct encoding was missed.
+             */
+            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10410)
+                          "Rewritten query string contains control "
+                          "characters or spaces");
+            return HTTP_FORBIDDEN;
+        }
+
         if (ACTION_STATUS == rulestatus) {
             int n = r->status;
 
@@ -5013,6 +5043,17 @@ static int hook_fixup(request_rec *r)
     if (rulestatus) {
         unsigned skip;
 
+        if (r->args && *(ap_scan_vchar_obstext(r->args))) {
+            /*
+             * We have a raw control character or a ' ' in r->args.
+             * Correct encoding was missed.
+             */
+            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10411)
+                          "Rewritten query string contains control "
+                          "characters or spaces");
+            return HTTP_FORBIDDEN;
+        }
+
         if (ACTION_STATUS == rulestatus) {
             int n = r->status;
 
diff --git a/modules/md/md.h b/modules/md/md.h
index af695f14..1d75d102 100644
--- a/modules/md/md.h
+++ b/modules/md/md.h
@@ -103,7 +103,8 @@ struct md_t {
     
     struct apr_array_header_t *acme_tls_1_domains; /* domains supporting "acme-tls/1" protocol */
     int stapling;                   /* if OCSP stapling is enabled */
-    
+    const char *dns01_cmd;          /* DNS challenge command, override global command */
+
     int watched;               /* if certificate is supervised (renew or expiration warning) */
     const struct md_srv_conf_t *sc; /* server config where it was defined or NULL */
     const char *defn_name;          /* config file this MD was defined */
diff --git a/modules/md/md_acme_authz.c b/modules/md/md_acme_authz.c
index 1e9aa762..a55804e4 100644
--- a/modules/md/md_acme_authz.c
+++ b/modules/md/md_acme_authz.c
@@ -243,7 +243,7 @@ static apr_status_t setup_key_authz(md_acme_authz_cha_t *cha, md_acme_authz_t *a
 static apr_status_t cha_http_01_setup(md_acme_authz_cha_t *cha, md_acme_authz_t *authz,
                                       md_acme_t *acme, md_store_t *store, 
                                       md_pkeys_spec_t *key_specs,
-                                      apr_array_header_t *acme_tls_1_domains, const char *mdomain,
+                                      apr_array_header_t *acme_tls_1_domains, const md_t *md,
                                       apr_table_t *env, md_result_t *result, apr_pool_t *p)
 {
     const char *data;
@@ -253,7 +253,7 @@ static apr_status_t cha_http_01_setup(md_acme_authz_cha_t *cha, md_acme_authz_t
     (void)key_specs;
     (void)env;
     (void)acme_tls_1_domains;
-    (void)mdomain;
+    (void)md;
 
     if (APR_SUCCESS != (rv = setup_key_authz(cha, authz, acme, p, &notify_server))) {
         goto out;
@@ -301,7 +301,7 @@ void tls_alpn01_fnames(apr_pool_t *p, md_pkey_spec_t *kspec, char **keyfn, char
 static apr_status_t cha_tls_alpn_01_setup(md_acme_authz_cha_t *cha, md_acme_authz_t *authz, 
                                           md_acme_t *acme, md_store_t *store, 
                                           md_pkeys_spec_t *key_specs,
-                                          apr_array_header_t *acme_tls_1_domains, const char *mdomain,
+                                          apr_array_header_t *acme_tls_1_domains, const md_t *md,
                                           apr_table_t *env, md_result_t *result, apr_pool_t *p)
 {
     const char *acme_id, *token;
@@ -311,7 +311,7 @@ static apr_status_t cha_tls_alpn_01_setup(md_acme_authz_cha_t *cha, md_acme_auth
     int i;
 
     (void)env;
-    (void)mdomain;
+    (void)md;
     if (md_array_str_index(acme_tls_1_domains, authz->domain, 0, 0) < 0) {
         rv = APR_ENOTIMPL;
         if (acme_tls_1_domains->nelts) {
@@ -413,7 +413,7 @@ out:
 static apr_status_t cha_dns_01_setup(md_acme_authz_cha_t *cha, md_acme_authz_t *authz, 
                                      md_acme_t *acme, md_store_t *store, 
                                      md_pkeys_spec_t *key_specs,
-                                     apr_array_header_t *acme_tls_1_domains, const char *mdomain,
+                                     apr_array_header_t *acme_tls_1_domains, const md_t *md,
                                      apr_table_t *env, md_result_t *result, apr_pool_t *p)
 {
     const char *token;
@@ -429,7 +429,9 @@ static apr_status_t cha_dns_01_setup(md_acme_authz_cha_t *cha, md_acme_authz_t *
     (void)key_specs;
     (void)acme_tls_1_domains;
 
-    dns01_cmd = apr_table_get(env, MD_KEY_CMD_DNS01);
+    dns01_cmd = md->dns01_cmd;
+    if (!dns01_cmd)
+      dns01_cmd = apr_table_get(env, MD_KEY_CMD_DNS01);
     if (!dns01_cmd) {
         rv = APR_ENOTIMPL;
         md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p, "%s: dns-01 command not set", 
@@ -445,7 +447,7 @@ static apr_status_t cha_dns_01_setup(md_acme_authz_cha_t *cha, md_acme_authz_t *
     rv = md_crypt_sha256_digest64(&token, p, &data);
     if (APR_SUCCESS != rv) {
         md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: create dns-01 token for %s",
-                      mdomain, authz->domain);
+                      md->name, authz->domain);
         goto out;
     }
 
@@ -456,13 +458,13 @@ static apr_status_t cha_dns_01_setup(md_acme_authz_cha_t *cha, md_acme_authz_t *
     apr_tokenize_to_argv(cmdline, (char***)&argv, p);
     if (APR_SUCCESS != (rv = md_util_exec(p, argv[0], argv, NULL, &exit_code))) {
         md_log_perror(MD_LOG_MARK, MD_LOG_WARNING, rv, p, 
-                      "%s: dns-01 setup command failed to execute for %s", mdomain, authz->domain);
+                      "%s: dns-01 setup command failed to execute for %s", md->name, authz->domain);
         goto out;
     }
     if (exit_code) {
         rv = APR_EGENERAL;
         md_log_perror(MD_LOG_MARK, MD_LOG_INFO, rv, p, 
-                      "%s: dns-01 setup command returns %d for %s", mdomain, exit_code, authz->domain);
+                      "%s: dns-01 setup command returns %d for %s", md->name, exit_code, authz->domain);
         goto out;
     }
     
@@ -478,7 +480,7 @@ static apr_status_t cha_dns_01_setup(md_acme_authz_cha_t *cha, md_acme_authz_t *
     }
     /* challenge is setup, tell ACME server so it may (re)try verification */
     md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p, "%s: dns-01 setup succeeded for %s",
-       mdomain, authz->domain);
+       md->name, authz->domain);
     authz_req_ctx_init(&ctx, acme, NULL, authz, p);
     ctx.challenge = cha;
     rv = md_acme_POST(acme, cha->uri, on_init_authz_resp, authz_http_set, NULL, NULL, &ctx);
@@ -487,7 +489,7 @@ out:
     return rv;
 }
 
-static apr_status_t cha_dns_01_teardown(md_store_t *store, const char *domain, const char *mdomain,
+static apr_status_t cha_dns_01_teardown(md_store_t *store, const char *domain, const md_t *md,
                                         apr_table_t *env, apr_pool_t *p)
 {
     const char * const *argv;
@@ -496,12 +498,14 @@ static apr_status_t cha_dns_01_teardown(md_store_t *store, const char *domain, c
     int exit_code;
     
     (void)store;
-    
-    dns01_cmd = apr_table_get(env, MD_KEY_CMD_DNS01);
+
+    dns01_cmd = md->dns01_cmd;
+    if (!dns01_cmd)
+      dns01_cmd = apr_table_get(env, MD_KEY_CMD_DNS01);
     if (!dns01_cmd) {
         rv = APR_ENOTIMPL;
         md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, 0, p, "%s: dns-01 command not set for %s",
-            mdomain, domain);
+            md->name, domain);
         goto out;
     }
     
@@ -510,27 +514,27 @@ static apr_status_t cha_dns_01_teardown(md_store_t *store, const char *domain, c
     if (APR_SUCCESS != (rv = md_util_exec(p, argv[0], argv, NULL, &exit_code)) || exit_code) {
         md_log_perror(MD_LOG_MARK, MD_LOG_WARNING, rv, p, 
                       "%s: dns-01 teardown command failed (exit code=%d) for %s",
-                      mdomain, exit_code, domain);
+                      md->name, exit_code, domain);
     }
 out:    
     return rv;
 }
 
-static apr_status_t cha_teardown_dir(md_store_t *store, const char *domain, const char *mdomain,
+static apr_status_t cha_teardown_dir(md_store_t *store, const char *domain, const md_t *md,
                                      apr_table_t *env, apr_pool_t *p)
 {
+    (void)md;
     (void)env;
-    (void)mdomain;
     return md_store_purge(store, p, MD_SG_CHALLENGES, domain);
 }
 
 typedef apr_status_t cha_setup(md_acme_authz_cha_t *cha, md_acme_authz_t *authz, 
                                md_acme_t *acme, md_store_t *store, 
                                md_pkeys_spec_t *key_specs,
-                               apr_array_header_t *acme_tls_1_domains, const char *mdomain,
+                               apr_array_header_t *acme_tls_1_domains, const md_t *md,
                                apr_table_t *env, md_result_t *result, apr_pool_t *p);
                                
-typedef apr_status_t cha_teardown(md_store_t *store, const char *domain, const char *mdomain,
+typedef apr_status_t cha_teardown(md_store_t *store, const char *domain, const md_t *md,
                                   apr_table_t *env, apr_pool_t *p);
                                  
 typedef struct {
@@ -579,7 +583,7 @@ static apr_status_t find_type(void *baton, size_t index, md_json_t *json)
 
 apr_status_t md_acme_authz_respond(md_acme_authz_t *authz, md_acme_t *acme, md_store_t *store, 
                                    apr_array_header_t *challenges, md_pkeys_spec_t *key_specs,
-                                   apr_array_header_t *acme_tls_1_domains, const char *mdomain,
+                                   apr_array_header_t *acme_tls_1_domains, const md_t *md,
                                    apr_table_t *env, apr_pool_t *p, const char **psetup_token,
                                    md_result_t *result)
 {
@@ -616,7 +620,7 @@ apr_status_t md_acme_authz_respond(md_acme_authz_t *authz, md_acme_t *acme, md_s
         md_json_itera(find_type, &fctx, authz->resource, MD_KEY_CHALLENGES, NULL);
         md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, 0, p,
                       "%s: challenge type '%s' for %s: %s",
-                      authz->domain, fctx.type, mdomain,
+                      authz->domain, fctx.type, md->name,
                       fctx.accepted? "maybe acceptable" : "not applicable");
 
         if (fctx.accepted) {
@@ -625,17 +629,17 @@ apr_status_t md_acme_authz_respond(md_acme_authz_t *authz, md_acme_t *acme, md_s
                     md_result_activity_printf(result, "Setting up challenge '%s' for domain %s", 
                                               fctx.accepted->type, authz->domain);
                     rv = CHA_TYPES[j].setup(fctx.accepted, authz, acme, store, key_specs,
-                                            acme_tls_1_domains, mdomain, env, result, p);
+                                            acme_tls_1_domains, md, env, result, p);
                     if (APR_SUCCESS == rv) {
                         md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p, 
                                       "%s: set up challenge '%s' for %s", 
-                                      authz->domain, fctx.accepted->type, mdomain);
-                        challenge_setup = CHA_TYPES[i].name;
+                                      authz->domain, fctx.accepted->type, md->name);
+                        challenge_setup = CHA_TYPES[j].name;
                         goto out;
                     }
                     md_result_printf(result, rv, "error setting up challenge '%s' for %s, "
                                      "for domain %s, looking for other option",
-                                     fctx.accepted->type, authz->domain, mdomain);
+                                     fctx.accepted->type, authz->domain, md->name);
                     md_result_log(result, MD_LOG_INFO);
                 }
             }
@@ -670,7 +674,7 @@ out:
 }
 
 apr_status_t md_acme_authz_teardown(struct md_store_t *store, const char *token,
-                                    const char *mdomain, apr_table_t *env, apr_pool_t *p)
+                                    const md_t *md, apr_table_t *env, apr_pool_t *p)
 {
     char *challenge, *domain;
     int i;
@@ -682,7 +686,7 @@ apr_status_t md_acme_authz_teardown(struct md_store_t *store, const char *token,
         for (i = 0; i < (int)CHA_TYPES_LEN; ++i) {
             if (!apr_strnatcasecmp(CHA_TYPES[i].name, challenge)) {
                 if (CHA_TYPES[i].teardown) {
-                    return CHA_TYPES[i].teardown(store, domain, mdomain, env, p);
+                    return CHA_TYPES[i].teardown(store, domain, md, env, p);
                 }
                 break;
             }
diff --git a/modules/md/md_acme_authz.h b/modules/md/md_acme_authz.h
index 90193af1..d74beeba 100644
--- a/modules/md/md_acme_authz.h
+++ b/modules/md/md_acme_authz.h
@@ -68,12 +68,12 @@ apr_status_t md_acme_authz_update(md_acme_authz_t *authz, struct md_acme_t *acme
 apr_status_t md_acme_authz_respond(md_acme_authz_t *authz, struct md_acme_t *acme, 
                                    struct md_store_t *store, apr_array_header_t *challenges, 
                                    struct md_pkeys_spec_t *key_spec,
-                                   apr_array_header_t *acme_tls_1_domains, const char *mdomain,
+                                   apr_array_header_t *acme_tls_1_domains, const md_t *md,
                                    struct apr_table_t *env,
                                    apr_pool_t *p, const char **setup_token,
                                    struct md_result_t *result);
 
 apr_status_t md_acme_authz_teardown(struct md_store_t *store, const char *setup_token, 
-                                    const char *mdomain, struct apr_table_t *env, apr_pool_t *p);
+                                    const md_t *md, struct apr_table_t *env, apr_pool_t *p);
 
 #endif /* md_acme_authz_h */
diff --git a/modules/md/md_acme_drive.c b/modules/md/md_acme_drive.c
index abe7d644..4bb04f32 100644
--- a/modules/md/md_acme_drive.c
+++ b/modules/md/md_acme_drive.c
@@ -587,7 +587,9 @@ static apr_status_t acme_driver_init(md_proto_driver_t *d, md_result_t *result)
             ad->ca_challenges = md_array_str_remove(d->p, ad->ca_challenges, MD_AUTHZ_TYPE_TLSALPN01, 0);
             dis_alpn_acme = 1;
         }
-        if (!apr_table_get(d->env, MD_KEY_CMD_DNS01) && md_array_str_index(ad->ca_challenges, MD_AUTHZ_TYPE_DNS01, 0, 1) >= 0) {
+        if (!apr_table_get(d->env, MD_KEY_CMD_DNS01)
+            && NULL == d->md->dns01_cmd
+            && md_array_str_index(ad->ca_challenges, MD_AUTHZ_TYPE_DNS01, 0, 1) >= 0) {
             ad->ca_challenges = md_array_str_remove(d->p, ad->ca_challenges, MD_AUTHZ_TYPE_DNS01, 0);
             dis_dns = 1;
         }
@@ -832,7 +834,7 @@ static apr_status_t acme_renew(md_proto_driver_t *d, md_result_t *result)
                                 md_result_printf(result, rv, "Certificate and private key do not match.");
 
                                 /* Delete the order */
-                                md_acme_order_purge(d->store, d->p, MD_SG_STAGING, d->md->name, d->env);
+                                md_acme_order_purge(d->store, d->p, MD_SG_STAGING, d->md, d->env);
 
                                 goto out;
                             }
@@ -849,7 +851,7 @@ static apr_status_t acme_renew(md_proto_driver_t *d, md_result_t *result)
                 }
                 
                 /* Clean up the order, so the next pkey spec sets up a new one */
-                md_acme_order_purge(d->store, d->p, MD_SG_STAGING, d->md->name, d->env);
+                md_acme_order_purge(d->store, d->p, MD_SG_STAGING, d->md, d->env);
             }
         }
     }
@@ -857,7 +859,7 @@ static apr_status_t acme_renew(md_proto_driver_t *d, md_result_t *result)
     
     /* As last step, cleanup any order we created so that challenge data
      * may be removed asap. */
-    md_acme_order_purge(d->store, d->p, MD_SG_STAGING, d->md->name, d->env);
+    md_acme_order_purge(d->store, d->p, MD_SG_STAGING, d->md, d->env);
     
     /* first time this job ran through */
     first = 1;    
@@ -998,7 +1000,7 @@ static apr_status_t acme_preload(md_proto_driver_t *d, md_store_group_t load_gro
     }
 
     md_result_activity_setn(result, "purging order information");
-    md_acme_order_purge(d->store, d->p, MD_SG_STAGING, name, d->env);
+    md_acme_order_purge(d->store, d->p, MD_SG_STAGING, md, d->env);
 
     md_result_activity_setn(result, "purging store tmp space");
     rv = md_store_purge(d->store, d->p, load_group, name);
diff --git a/modules/md/md_acme_order.c b/modules/md/md_acme_order.c
index 8037c762..9e25e84c 100644
--- a/modules/md/md_acme_order.c
+++ b/modules/md/md_acme_order.c
@@ -226,32 +226,33 @@ static apr_status_t p_purge(void *baton, apr_pool_t *p, apr_pool_t *ptemp, va_li
     md_store_t *store = baton;
     md_acme_order_t *order;
     md_store_group_t group;
-    const char *md_name, *setup_token;
+    const md_t *md;
+    const char *setup_token;
     apr_table_t *env;
     int i;
 
     group = (md_store_group_t)va_arg(ap, int);
-    md_name = va_arg(ap, const char *);
+    md = va_arg(ap, const md_t *);
     env = va_arg(ap, apr_table_t *);
 
-    if (APR_SUCCESS == md_acme_order_load(store, group, md_name, &order, p)) {
-        md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, 0, p, "order loaded for %s", md_name);
+    if (APR_SUCCESS == md_acme_order_load(store, group, md->name, &order, p)) {
+        md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, 0, p, "order loaded for %s", md->name);
         for (i = 0; i < order->challenge_setups->nelts; ++i) {
             setup_token = APR_ARRAY_IDX(order->challenge_setups, i, const char*);
             if (setup_token) {
                 md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, 0, p, 
                               "order teardown setup %s", setup_token);
-                md_acme_authz_teardown(store, setup_token, md_name, env, p);
+                md_acme_authz_teardown(store, setup_token, md, env, p);
             }
         }
     }
-    return md_store_remove(store, group, md_name, MD_FN_ORDER, ptemp, 1);
+    return md_store_remove(store, group, md->name, MD_FN_ORDER, ptemp, 1);
 }
 
 apr_status_t md_acme_order_purge(md_store_t *store, apr_pool_t *p, md_store_group_t group,
-                                 const char *md_name, apr_table_t *env)
+                                 const md_t *md, apr_table_t *env)
 {
-    return md_util_pool_vdo(p_purge, store, p, group, md_name, env, NULL);
+    return md_util_pool_vdo(p_purge, store, p, group, md, env, NULL);
 }
 
 /**************************************************************************************************/
@@ -465,7 +466,7 @@ apr_status_t md_acme_order_start_challenges(md_acme_order_t *order, md_acme_t *a
                               md->name, authz->domain);
                 rv = md_acme_authz_respond(authz, acme, store, challenge_types,
                                            md->pks,
-                                           md->acme_tls_1_domains, md->name,
+                                           md->acme_tls_1_domains, md,
                                            env, p, &setup_token, result);
                 if (APR_SUCCESS != rv) {
                     goto leave;
diff --git a/modules/md/md_acme_order.h b/modules/md/md_acme_order.h
index 868fb56b..41704401 100644
--- a/modules/md/md_acme_order.h
+++ b/modules/md/md_acme_order.h
@@ -60,7 +60,7 @@ apr_status_t md_acme_order_save(struct md_store_t *store, apr_pool_t *p,
                                     md_acme_order_t *authz_set, int create);
 
 apr_status_t md_acme_order_purge(struct md_store_t *store, apr_pool_t *p, 
-                                 md_store_group_t group, const char *md_name,
+                                 md_store_group_t group, const md_t *md,
                                  apr_table_t *env);
 
 apr_status_t md_acme_order_start_challenges(md_acme_order_t *order, md_acme_t *acme,
diff --git a/modules/md/md_acmev2_drive.c b/modules/md/md_acmev2_drive.c
index 7ee4790b..9dfca967 100644
--- a/modules/md/md_acmev2_drive.c
+++ b/modules/md/md_acmev2_drive.c
@@ -73,7 +73,7 @@ static apr_status_t ad_setup_order(md_proto_driver_t *d, md_result_t *result, in
     }
     else if (!APR_STATUS_IS_ENOENT(rv)) {
         md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, d->p, "%s: loading order", md->name);
-        md_acme_order_purge(d->store, d->p, MD_SG_STAGING, md->name, d->env);
+        md_acme_order_purge(d->store, d->p, MD_SG_STAGING, md, d->env);
     }
     
     md_result_activity_setn(result, "Creating new order");
@@ -128,7 +128,7 @@ apr_status_t md_acmev2_drive_renew(md_acme_driver_t *ad, md_proto_driver_t *d, m
         || MD_ACME_ORDER_ST_INVALID == ad->order->status) {
         /* order is invalid or no longer known at the ACME server */
         ad->order = NULL;
-        md_acme_order_purge(d->store, d->p, MD_SG_STAGING, d->md->name, d->env);
+        md_acme_order_purge(d->store, d->p, MD_SG_STAGING, d->md, d->env);
     }
     else if (APR_SUCCESS != rv) {
         goto leave;
@@ -145,7 +145,7 @@ retry:
     if (!is_new_order && APR_STATUS_IS_EINVAL(rv)) {
         /* found 'invalid' domains in previous order, need to start over */
         ad->order = NULL;
-        md_acme_order_purge(d->store, d->p, MD_SG_STAGING, d->md->name, d->env);
+        md_acme_order_purge(d->store, d->p, MD_SG_STAGING, d->md, d->env);
         goto retry;
     }
     if (APR_SUCCESS != rv) goto leave;
diff --git a/modules/md/md_core.c b/modules/md/md_core.c
index 8c7c4536..7aacff04 100644
--- a/modules/md/md_core.c
+++ b/modules/md/md_core.c
@@ -255,6 +255,7 @@ md_t *md_clone(apr_pool_t *p, const md_t *src)
         }
         md->acme_tls_1_domains = md_array_str_compact(p, src->acme_tls_1_domains, 0);
         md->stapling = src->stapling;
+        if (src->dns01_cmd) md->dns01_cmd = apr_pstrdup(p, src->dns01_cmd);
         if (src->cert_files) md->cert_files = md_array_str_clone(p, src->cert_files);
         if (src->pkey_files) md->pkey_files = md_array_str_clone(p, src->pkey_files);
     }    
@@ -311,6 +312,7 @@ md_json_t *md_to_json(const md_t *md, apr_pool_t *p)
         if (md->cert_files) md_json_setsa(md->cert_files, json, MD_KEY_CERT_FILES, NULL);
         if (md->pkey_files) md_json_setsa(md->pkey_files, json, MD_KEY_PKEY_FILES, NULL);
         md_json_setb(md->stapling > 0, json, MD_KEY_STAPLING, NULL);
+        if (md->dns01_cmd) md_json_sets(md->dns01_cmd, json, MD_KEY_CMD_DNS01, NULL);
         if (md->ca_eab_kid && strcmp("none", md->ca_eab_kid)) {
             md_json_sets(md->ca_eab_kid, json, MD_KEY_EAB, MD_KEY_KID, NULL);
             if (md->ca_eab_hmac) md_json_sets(md->ca_eab_hmac, json, MD_KEY_EAB, MD_KEY_HMAC, NULL);
@@ -376,7 +378,7 @@ md_t *md_from_json(md_json_t *json, apr_pool_t *p)
             md_json_dupsa(md->pkey_files, p, json, MD_KEY_PKEY_FILES, NULL);
         }
         md->stapling = (int)md_json_getb(json, MD_KEY_STAPLING, NULL);
-        
+        md->dns01_cmd = md_json_dups(p, json, MD_KEY_CMD_DNS01, NULL);
         if (md_json_has_key(json, MD_KEY_EAB, NULL)) {
             md->ca_eab_kid = md_json_dups(p, json, MD_KEY_EAB, MD_KEY_KID, NULL);
             md->ca_eab_hmac = md_json_dups(p, json, MD_KEY_EAB, MD_KEY_HMAC, NULL);
diff --git a/modules/md/md_crypt.c b/modules/md/md_crypt.c
index 8baab51c..f2b0cd54 100644
--- a/modules/md/md_crypt.c
+++ b/modules/md/md_crypt.c
@@ -61,8 +61,8 @@
 #define MD_USE_OPENSSL_PRE_1_1_API (OPENSSL_VERSION_NUMBER < 0x10100000L)
 #endif
 
-#if defined(LIBRESSL_VERSION_NUMBER) || (OPENSSL_VERSION_NUMBER < 0x10100000L) 
-/* Missing from LibreSSL and only available since OpenSSL v1.1.x */
+#if (defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER < 0x3050000fL)) || (OPENSSL_VERSION_NUMBER < 0x10100000L) 
+/* Missing from LibreSSL < 3.5.0 and only available since OpenSSL v1.1.x */
 #ifndef OPENSSL_NO_CT
 #define OPENSSL_NO_CT
 #endif
@@ -210,7 +210,8 @@ static int pem_passwd(char *buf, int size, int rwflag, void *baton)
  */
 static apr_time_t md_asn1_time_get(const ASN1_TIME* time)
 {
-#if OPENSSL_VERSION_NUMBER < 0x10002000L || defined(LIBRESSL_VERSION_NUMBER)
+#if OPENSSL_VERSION_NUMBER < 0x10002000L || (defined(LIBRESSL_VERSION_NUMBER) && \
+                                             LIBRESSL_VERSION_NUMBER < 0x3060000fL)
     /* courtesy: https://stackoverflow.com/questions/10975542/asn1-time-to-time-t-conversion#11263731
      * all bugs are mine */
     apr_time_exp_t t;
@@ -854,7 +855,8 @@ static apr_status_t gen_ec(md_pkey_t **ppkey, apr_pool_t *p, const char *curve)
         curve = EC_curve_nid2nist(curve_nid);
     }
 #endif
-#if defined(NID_X25519) && !defined(LIBRESSL_VERSION_NUMBER)
+#if defined(NID_X25519) && (!defined(LIBRESSL_VERSION_NUMBER) || \
+                            LIBRESSL_VERSION_NUMBER >= 0x3070000fL)
     if (NID_undef == curve_nid && !apr_strnatcasecmp("X25519", curve)) {
         curve_nid = NID_X25519;
         curve = EC_curve_nid2nist(curve_nid);
@@ -872,7 +874,8 @@ static apr_status_t gen_ec(md_pkey_t **ppkey, apr_pool_t *p, const char *curve)
     *ppkey = make_pkey(p);
     switch (curve_nid) {
 
-#if defined(NID_X25519) && !defined(LIBRESSL_VERSION_NUMBER)
+#if defined(NID_X25519) && (!defined(LIBRESSL_VERSION_NUMBER) || \
+                            LIBRESSL_VERSION_NUMBER >= 0x3070000fL)
     case NID_X25519:
         /* no parameters */
         if (NULL == (ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_X25519, NULL))
diff --git a/modules/md/md_version.h b/modules/md/md_version.h
index 9a8d5882..a8f3ef22 100644
--- a/modules/md/md_version.h
+++ b/modules/md/md_version.h
@@ -27,7 +27,7 @@
  * @macro
  * Version number of the md module as c string
  */
-#define MOD_MD_VERSION "2.4.19"
+#define MOD_MD_VERSION "2.4.21"
 
 /**
  * @macro
@@ -35,7 +35,7 @@
  * release. This is a 24 bit number with 8 bits for major number, 8 bits
  * for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203.
  */
-#define MOD_MD_VERSION_NUM 0x020413
+#define MOD_MD_VERSION_NUM 0x020415
 
 #define MD_ACME_DEF_URL         "https://acme-v02.api.letsencrypt.org/directory";
 #define MD_TAILSCALE_DEF_URL    "file://localhost/var/run/tailscale/tailscaled.sock"
diff --git a/modules/md/mod_md_config.c b/modules/md/mod_md_config.c
index 2f193005..e117b160 100644
--- a/modules/md/mod_md_config.c
+++ b/modules/md/mod_md_config.c
@@ -120,6 +120,7 @@ static md_srv_conf_t defconf = {
     NULL,                      /* ca eab hmac */
     0,                         /* stapling */
     1,                         /* staple others */
+    NULL,                      /* dns01_cmd */
     NULL,                      /* currently defined md */
     NULL,                      /* assigned md, post config */
     0,                         /* is_ssl, set during mod_ssl post_config */
@@ -174,6 +175,7 @@ static void srv_conf_props_clear(md_srv_conf_t *sc)
     sc->ca_eab_hmac = NULL;
     sc->stapling = DEF_VAL;
     sc->staple_others = DEF_VAL;
+    sc->dns01_cmd = NULL;
 }
 
 static void srv_conf_props_copy(md_srv_conf_t *to, const md_srv_conf_t *from)
@@ -194,6 +196,7 @@ static void srv_conf_props_copy(md_srv_conf_t *to, const md_srv_conf_t *from)
     to->ca_eab_hmac = from->ca_eab_hmac;
     to->stapling = from->stapling;
     to->staple_others = from->staple_others;
+    to->dns01_cmd = from->dns01_cmd;
 }
 
 static void srv_conf_props_apply(md_t *md, const md_srv_conf_t *from, apr_pool_t *p)
@@ -217,6 +220,7 @@ static void srv_conf_props_apply(md_t *md, const md_srv_conf_t *from, apr_pool_t
     if (from->ca_eab_kid) md->ca_eab_kid = from->ca_eab_kid;
     if (from->ca_eab_hmac) md->ca_eab_hmac = from->ca_eab_hmac;
     if (from->stapling != DEF_VAL) md->stapling = from->stapling;
+    if (from->dns01_cmd) md->dns01_cmd = from->dns01_cmd;
 }
 
 void *md_config_create_svr(apr_pool_t *pool, server_rec *s)
@@ -262,6 +266,7 @@ static void *md_config_merge(apr_pool_t *pool, void *basev, void *addv)
     nsc->ca_eab_hmac = add->ca_eab_hmac? add->ca_eab_hmac : base->ca_eab_hmac;
     nsc->stapling = (add->stapling != DEF_VAL)? add->stapling : base->stapling;
     nsc->staple_others = (add->staple_others != DEF_VAL)? add->staple_others : base->staple_others;
+    nsc->dns01_cmd = (add->dns01_cmd)? add->dns01_cmd : base->dns01_cmd;
     nsc->current = NULL;
     
     return nsc;
@@ -966,10 +971,16 @@ static const char *md_config_set_dns01_cmd(cmd_parms *cmd, void *mconfig, const
     md_srv_conf_t *sc = md_config_get(cmd->server);
     const char *err;
 
-    if ((err = md_conf_check_location(cmd, MD_LOC_NOT_MD))) {
+    if ((err = md_conf_check_location(cmd, MD_LOC_ALL))) {
         return err;
     }
-    apr_table_set(sc->mc->env, MD_KEY_CMD_DNS01, arg);
+
+    if (inside_md_section(cmd)) {
+        sc->dns01_cmd = arg;
+    } else {
+        apr_table_set(sc->mc->env, MD_KEY_CMD_DNS01, arg);
+    }
+
     (void)mconfig;
     return NULL;
 }
diff --git a/modules/md/mod_md_config.h b/modules/md/mod_md_config.h
index b34b92e1..de42169c 100644
--- a/modules/md/mod_md_config.h
+++ b/modules/md/mod_md_config.h
@@ -100,6 +100,8 @@ typedef struct md_srv_conf_t {
     int stapling;                      /* OCSP stapling enabled */
     int staple_others;                 /* Provide OCSP stapling for non-MD certificates */
 
+    const char *dns01_cmd;             /* DNS challenge command, override global command */
+
     md_t *current;                     /* md currently defined in <MDomainSet xxx> section */
     struct apr_array_header_t *assigned; /* post_config: MDs that apply to this server */
     int is_ssl;                        /* SSLEngine is enabled here */
diff --git a/modules/proxy/ajp_header.c b/modules/proxy/ajp_header.c
index b4dc47cc..a09a2e43 100644
--- a/modules/proxy/ajp_header.c
+++ b/modules/proxy/ajp_header.c
@@ -584,8 +584,15 @@ static apr_status_t ajp_unmarshal_response(ajp_msg_t *msg,
         r->headers_out = save_table;
     }
     else {
-        r->headers_out = NULL;
+        /*
+         * Reset headers, but not to NULL because things below the chain expect
+         * this to be non NULL e.g. the ap_content_length_filter.
+         */
+        r->headers_out = apr_table_make(r->pool, 1);
         num_headers = 0;
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10405)
+                "ajp_unmarshal_response: Bad number of headers");
+        return rc;
     }
 
     ap_log_rerror(APLOG_MARK, APLOG_TRACE4, 0, r,
diff --git a/modules/proxy/mod_proxy_ajp.c b/modules/proxy/mod_proxy_ajp.c
index 1449acad..e46bd903 100644
--- a/modules/proxy/mod_proxy_ajp.c
+++ b/modules/proxy/mod_proxy_ajp.c
@@ -69,6 +69,16 @@ static int proxy_ajp_canon(request_rec *r, char *url)
         path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, 0,
                                  r->proxyreq);
         search = r->args;
+        if (search && *(ap_scan_vchar_obstext(search))) {
+            /*
+             * We have a raw control character or a ' ' in r->args.
+             * Correct encoding was missed.
+             */
+             ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10406)
+                           "To be forwarded query string contains control "
+                           "characters or spaces");
+             return HTTP_FORBIDDEN;
+        }
     }
     if (path == NULL)
         return HTTP_BAD_REQUEST;
diff --git a/modules/proxy/mod_proxy_balancer.c b/modules/proxy/mod_proxy_balancer.c
index f6fb6345..7f990084 100644
--- a/modules/proxy/mod_proxy_balancer.c
+++ b/modules/proxy/mod_proxy_balancer.c
@@ -106,6 +106,16 @@ static int proxy_balancer_canon(request_rec *r, char *url)
         path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, 0,
                                  r->proxyreq);
         search = r->args;
+        if (search && *(ap_scan_vchar_obstext(search))) {
+            /*
+             * We have a raw control character or a ' ' in r->args.
+             * Correct encoding was missed.
+             */
+             ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10407)
+                           "To be forwarded query string contains control "
+                           "characters or spaces");
+             return HTTP_FORBIDDEN;
+        }
     }
     if (path == NULL)
         return HTTP_BAD_REQUEST;
diff --git a/modules/proxy/mod_proxy_http.c b/modules/proxy/mod_proxy_http.c
index ec4e7fb0..51d19a0a 100644
--- a/modules/proxy/mod_proxy_http.c
+++ b/modules/proxy/mod_proxy_http.c
@@ -125,6 +125,16 @@ static int proxy_http_canon(request_rec *r, char *url)
             path = ap_proxy_canonenc(r->pool, url, strlen(url),
                                      enc_path, 0, r->proxyreq);
             search = r->args;
+            if (search && *(ap_scan_vchar_obstext(search))) {
+                /*
+                 * We have a raw control character or a ' ' in r->args.
+                 * Correct encoding was missed.
+                 */
+                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10408)
+                              "To be forwarded query string contains control "
+                              "characters or spaces");
+                return HTTP_FORBIDDEN;
+            }
         }
         break;
     case PROXYREQ_PROXY:
diff --git a/modules/proxy/mod_proxy_uwsgi.c b/modules/proxy/mod_proxy_uwsgi.c
index e02450ef..92e153cc 100644
--- a/modules/proxy/mod_proxy_uwsgi.c
+++ b/modules/proxy/mod_proxy_uwsgi.c
@@ -307,18 +307,16 @@ static int uwsgi_response(request_rec *r, proxy_conn_rec * backend,
     pass_bb = apr_brigade_create(r->pool, c->bucket_alloc);
 
     len = ap_getline(buffer, sizeof(buffer), rp, 1);
-
     if (len <= 0) {
-        /* oops */
+        /* invalid or empty */
         return HTTP_INTERNAL_SERVER_ERROR;
     }
-
     backend->worker->s->read += len;
-
-    if (len >= sizeof(buffer) - 1) {
-        /* oops */
+    if ((apr_size_t)len >= sizeof(buffer)) {
+        /* too long */
         return HTTP_INTERNAL_SERVER_ERROR;
     }
+
     /* Position of http status code */
     if (apr_date_checkmask(buffer, "HTTP/#.# ###*")) {
         status_start = 9;
@@ -327,8 +325,8 @@ static int uwsgi_response(request_rec *r, proxy_conn_rec * backend,
         status_start = 7;
     }
     else {
-        /* oops */
-        return HTTP_INTERNAL_SERVER_ERROR;
+        /* not HTTP */
+        return HTTP_BAD_GATEWAY;
     }
     status_end = status_start + 3;
 
@@ -348,21 +346,44 @@ static int uwsgi_response(request_rec *r, proxy_conn_rec * backend,
     }
     r->status_line = apr_pstrdup(r->pool, &buffer[status_start]);
 
-    /* start parsing headers */
+    /* parse headers */
     while ((len = ap_getline(buffer, sizeof(buffer), rp, 1)) > 0) {
+        if ((apr_size_t)len >= sizeof(buffer)) {
+            /* too long */
+            len = -1;
+            break;
+        }
         value = strchr(buffer, ':');
-        /* invalid header skip */
-        if (!value)
-            continue;
-        *value = '\0';
-        ++value;
+        if (!value) {
+            /* invalid header */
+            len = -1;
+            break;
+        }
+        *value++ = '\0';
+        if (*ap_scan_http_token(buffer)) {
+            /* invalid name */
+            len = -1;
+            break;
+        }
         while (apr_isspace(*value))
             ++value;
         for (end = &value[strlen(value) - 1];
              end > value && apr_isspace(*end); --end)
             *end = '\0';
+        if (*ap_scan_http_field_content(value)) {
+            /* invalid value */
+            len = -1;
+            break;
+        }
         apr_table_add(r->headers_out, buffer, value);
     }
+    if (len < 0) {
+        /* Reset headers, but not to NULL because things below the chain expect
+         * this to be non NULL e.g. the ap_content_length_filter.
+         */
+        r->headers_out = apr_table_make(r->pool, 1);
+        return HTTP_BAD_GATEWAY;
+    }
 
     if ((buf = apr_table_get(r->headers_out, "Content-Type"))) {
         ap_set_content_type(r, apr_pstrdup(r->pool, buf));
diff --git a/modules/proxy/mod_proxy_wstunnel.c b/modules/proxy/mod_proxy_wstunnel.c
index bcbba42f..88f86a49 100644
--- a/modules/proxy/mod_proxy_wstunnel.c
+++ b/modules/proxy/mod_proxy_wstunnel.c
@@ -114,6 +114,16 @@ static int proxy_wstunnel_canon(request_rec *r, char *url)
         path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, 0,
                                  r->proxyreq);
         search = r->args;
+        if (search && *(ap_scan_vchar_obstext(search))) {
+            /*
+             * We have a raw control character or a ' ' in r->args.
+             * Correct encoding was missed.
+             */
+            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10409)
+                          "To be forwarded query string contains control "
+                          "characters or spaces");
+            return HTTP_FORBIDDEN;
+        }
     }
     if (path == NULL)
         return HTTP_BAD_REQUEST;
diff --git a/support/rotatelogs.c b/support/rotatelogs.c
index 3227b552..e0819da5 100644
--- a/support/rotatelogs.c
+++ b/support/rotatelogs.c
@@ -65,6 +65,7 @@ struct rotate_config {
     int echo;
     char *szLogRoot;
     int truncate;
+    int truncate_rotated_only;
     const char *linkfile;
     const char *postrotate_prog;
 #if APR_FILES_AS_SOCKETS
@@ -109,9 +110,9 @@ static void usage(const char *argv0, const char *reason)
     }
     fprintf(stderr,
 #if APR_FILES_AS_SOCKETS
-            "Usage: %s [-v] [-l] [-L linkname] [-p prog] [-f] [-D] [-t] [-e] [-c] [-n number] <logfile> "
+            "Usage: %s [-vlfDtTec] [-L linkname] [-p prog] [-n number] <logfile> "
 #else
-            "Usage: %s [-v] [-l] [-L linkname] [-p prog] [-f] [-D] [-t] [-e] [-n number] <logfile> "
+            "Usage: %s [-vlfDtTe] [-L linkname] [-p prog] [-n number] <logfile> "
 #endif
             "{<rotation time in seconds>|<rotation size>(B|K|M|G)} "
             "[offset minutes from UTC]\n\n",
@@ -145,6 +146,7 @@ static void usage(const char *argv0, const char *reason)
             "  -f       Force opening of log on program start.\n"
             "  -D       Create parent directories of log file.\n" 
             "  -t       Truncate logfile instead of rotating, tail friendly.\n"
+            "  -T       Truncate logfiles opened for rotation, but not the initial logfile.\n"
             "  -e       Echo log to stdout for further processing.\n"
 #if APR_FILES_AS_SOCKETS
             "  -c       Create log even if it is empty.\n"
@@ -380,6 +382,8 @@ static void doRotate(rotate_config_t *config, rotate_status_t *status)
     apr_status_t rv;
     struct logfile newlog;
     int thisLogNum = -1;
+    int oldreason = status->rotateReason;
+    int truncate = config->truncate;
 
     /* Retrieve local-time-adjusted-Unix-time. */
     now = get_now(config, &offset);
@@ -459,8 +463,17 @@ static void doRotate(rotate_config_t *config, rotate_status_t *status)
     if (config->verbose) {
         fprintf(stderr, "Opening file %s\n", newlog.name);
     }
-    rv = apr_file_open(&newlog.fd, newlog.name, APR_WRITE | APR_CREATE | APR_APPEND
-                       | (config->truncate || (config->num_files > 0 && status->current.fd) ? APR_TRUNCATE : 0), 
+
+    if (!truncate) {
+        /* -n and -T truncate subsequent files only. */
+        if (status->current.fd &&
+               (config->num_files > 0 || config->truncate_rotated_only)) {
+            truncate = 1;
+        }
+    }
+    rv = apr_file_open(&newlog.fd, newlog.name,
+                       APR_WRITE | APR_CREATE | APR_APPEND
+                       | (truncate ? APR_TRUNCATE : 0),
                        APR_OS_DEFAULT, newlog.pool);
     if (rv == APR_SUCCESS) {
         /* Handle post-rotate processing. */
@@ -474,6 +487,19 @@ static void doRotate(rotate_config_t *config, rotate_status_t *status)
 
         /* New log file is now 'current'. */
         status->current = newlog;
+
+        /* The first write to the initial file hasn't checked for size.
+         * In the normalized timestamp case and the custom strftime case with
+         * any reasonable accuracy, it's futile as the rotation will pick the
+         * same filename again. 
+         * For -n, when not truncating, check and rotate.
+         */
+        if (config->num_files > 0 && oldreason == ROTATE_NEW && !config->truncate) {
+            checkRotate(config, status);
+            if (status->rotateReason != ROTATE_NONE) {
+                doRotate(config, status);
+            }
+        }
     }
     else {
         char *error = apr_psprintf(newlog.pool, "%pm", &rv);
@@ -585,9 +611,9 @@ int main (int argc, const char * const argv[])
     apr_pool_create(&status.pool, NULL);
     apr_getopt_init(&opt, status.pool, argc, argv);
 #if APR_FILES_AS_SOCKETS
-    while ((rv = apr_getopt(opt, "lL:p:fDtvecn:", &c, &opt_arg)) == APR_SUCCESS) {
+    while ((rv = apr_getopt(opt, "lL:p:fDtTvecn:", &c, &opt_arg)) == APR_SUCCESS) {
 #else
-    while ((rv = apr_getopt(opt, "lL:p:fDtven:", &c, &opt_arg)) == APR_SUCCESS) {
+    while ((rv = apr_getopt(opt, "lL:p:fDtTven:", &c, &opt_arg)) == APR_SUCCESS) {
 #endif
         switch (c) {
         case 'l':
@@ -612,6 +638,9 @@ int main (int argc, const char * const argv[])
         case 't':
             config.truncate = 1;
             break;
+        case 'T':
+            config.truncate_rotated_only = 1;
+            break;
         case 'v':
             config.verbose = 1;
             break;
diff --git a/test/README.travis b/test/README.ci
similarity index 52%
rename from test/README.travis
rename to test/README.ci
index 2806a5fa..43600b00 100644
--- a/test/README.travis
+++ b/test/README.ci
@@ -2,7 +2,7 @@
 Variables
 ---------
 
-The Travis scripts use the following environment variables:
+The CI scripts use the following environment variables:
 
 * APR_VERSION - if set, APR of this version is built and installed in
   $HOME/root/apr-$APR_VERSION - a value of "trunk" means trunk is
@@ -44,7 +44,9 @@ The Travis scripts use the following environment variables:
 
 * TEST_ARGS - arguments to pass to ./t/TEST in the Perl test framework
 
-Caching
+* CLEAR_CACHE - if set, the cached $HOME/root is removed before each build
+
+Caching -- NOTE, BROKEN IN GITHUB ACTIONS --
 -------
 
 Perl modules installed in $HOME/perl5 are cached.
@@ -53,27 +55,72 @@ Anything installed into the $HOME/root directory is cached - notably,
 versions of APR/APR-util are installed here and cached across httpd
 build jobs without needing to be rebuilt every time.
 
+The cached installs of APR/APR-util are refreshed if the
+last-changed-revision of the build is stale.
+
+If APR_VERSION and APU_VERSION are both set to 1.x versions, then
+CLEAR_CACHE should also be set to disable APR* caching.  APR-util can
+only be rebuilt if an APR checkout is present, so a APR-util cannot be
+built from source alone.  (i.e. the scripts do not handle the case of
+cached, fresh APR plus a cached but stale APR-util)
+
+Travis to Github Actions Migration TODO
+---------------------------------------
+
+* better path filtering so e.g. CHANGES changes don't trigger CI
+* support branch conditionals again (some tests are 2.4.x only, some trunk only)
+* make caching work properly for APR + CPAN modules
+  - this is using the wrong model at the moment
+  - the cache key needs to be based off (source code, job configuration)
+  - rather than done on the fly in test/travis_before_linux.sh
+  - pebble + Rustls builds should also be cached
+* turn on failure notifications?
+* test across different Ubuntu versions again
+ - and test against OpenSSL 1.x since we're now ONLY building against 3.x
+* update the docs below for testing from PRs/feature branches
+* introduce some job ordering rather than having a flat/concurrent
+  set, if the default "./configure && make && test" works *then* start
+  jobs doing 200 different variations on ./configure --enable-XXX 
+  i.e. stop burning CPU time for a typo which breaks every job
+
 TODO list
 ---------
 
+* non-x86 builds
 * MacOS build
 * Windows build
 * clang-on-Linux build
 * Use containers for non-Ubuntu-based Linux testing
-* sanity checks for use of APLOGNO() - empty arguments, accidental duplicates, etc.
- - not sure how exactly
-* Known test failures
- - "apt-get install" timeout/fails - workaround by moving apt install to before_script phase?
 
-Testing from a Feature Branch
+Known Failures
+--------------
+
+Some known failures:
+
+* prefork, and more rarely non-prefork testing sometimes catches child
+  segfaults under pool-debug from assert()s in (e.g.)
+  __pthread_tpp_change_priority where one child is destroying threads
+  which another is waiting for, or iterating through via
+  apr_pool_walk_tree().
+
+  See dev@httpd threads:
+  msg <5f4abde1b5789_13fde2ecacb40795a1@travis-tasks-5b566d48fc-drkb9.mail>
+  msg <73060f7b-df7f-ad3c-a9fa-dd666a59b31e@kippdata.de> and
+  https://bz.apache.org/bugzilla/show_bug.cgi?id=63098
+  https://bz.apache.org/bugzilla/show_bug.cgi?id=46185
+
+  Not clear if there is a real bug here which can be reproduced
+  outside of pool-debug.
+
+Testing from a Feature Branch [*** N/A FOR GITHUB ACTIONS ***]
 -----------------------------
 
 An SVN branch off trunk should be mirrored to github, and will be
-tested in the same way that trunk is in Travis, so this workflow is
+tested in the same way that trunk is in CI, so this workflow is
 available for those familiar with using Subversion and the standard
 ASF/httpd repository layout.
 
-Tested branches are listed at: https://travis-ci.org/github/apache/httpd/branches
+Tested branches are listed at: https://travis-ci.com/github/apache/httpd/branches
 
 Travis will also run the tests for a PR filed against the httpd Github
 repository at https://github.com/apache/httpd or from a fork of this
@@ -91,16 +138,17 @@ $USERNAME for your github username:
   $ git push -u $USERNAME my-feature:my-feature
 
 To enable testing for a fork, visit the settings page at
-https://travis-ci.org/$USERNAME/httpd/settings - you may need to sync
-your account via https://travis-ci.org/account/repositories for a
+https://travis-ci.com/$USERNAME/httpd/settings - you may need to sync
+your account via https://travis-ci.com/account/repositories for a
 freshly created fork.
 
-To create a Pull Request, go to a URL like:
+To create a Pull Request, go to the URL produced in the "git push"
+command output when pushing to your fork, which is something like:
 https://github.com/apache/httpd/compare/trunk...$USERNAME:trunk
 
 Once a PR has been created, travis will run the tests and link the
 results from a PR comment. All tested PRs are listed here:
-https://travis-ci.org/github/apache/httpd/pull_requests
+https://travis-ci.com/github/apache/httpd/pull_requests
 
 To merge from github back to SVN trunk, create a patch from e.g.:
 
diff --git a/test/modules/http2/htdocs/cgi/echo.py b/test/modules/http2/htdocs/cgi/echo.py
index 58d811c4..c9083e1d 100644
--- a/test/modules/http2/htdocs/cgi/echo.py
+++ b/test/modules/http2/htdocs/cgi/echo.py
@@ -1,5 +1,6 @@
 #!/usr/bin/env python3
-import sys, cgi, os
+import os, sys
+import multipart
 
 status = '200 Ok'
 
diff --git a/test/modules/http2/htdocs/cgi/echohd.py b/test/modules/http2/htdocs/cgi/echohd.py
index 371ae8b0..2a138cd8 100644
--- a/test/modules/http2/htdocs/cgi/echohd.py
+++ b/test/modules/http2/htdocs/cgi/echohd.py
@@ -1,11 +1,25 @@
 #!/usr/bin/env python3
-import cgi, os
-import cgitb; cgitb.enable()
+import os, sys
+import multipart
+from urllib import parse
 
-status = '200 Ok'
 
-form = cgi.FieldStorage()
-name = form.getvalue('name')
+def get_request_params():
+    oforms = {}
+    if "REQUEST_URI" in os.environ:
+        qforms = parse.parse_qs(parse.urlsplit(os.environ["REQUEST_URI"]).query)
+        for name, values in qforms.items():
+            oforms[name] = values[0]
+    myenv = os.environ.copy()
+    myenv['wsgi.input'] = sys.stdin.buffer
+    mforms, ofiles = multipart.parse_form_data(environ=myenv)
+    for name, item in mforms.items():
+        oforms[name] = item
+    return oforms, ofiles
+
+
+forms, files = get_request_params()
+name = forms['name'] if 'name' in forms else None
 
 if name:
     print("Status: 200")
diff --git a/test/modules/http2/htdocs/cgi/env.py b/test/modules/http2/htdocs/cgi/env.py
index 5c9c0b1a..3af57649 100644
--- a/test/modules/http2/htdocs/cgi/env.py
+++ b/test/modules/http2/htdocs/cgi/env.py
@@ -1,28 +1,45 @@
 #!/usr/bin/env python3
-import cgi, os
-import cgitb; cgitb.enable()
+import os, sys
+import multipart
+from urllib import parse
+
+
+def get_request_params():
+    oforms = {}
+    if "REQUEST_URI" in os.environ:
+        qforms = parse.parse_qs(parse.urlsplit(os.environ["REQUEST_URI"]).query)
+        for name, values in qforms.items():
+            oforms[name] = values[0]
+    myenv = os.environ.copy()
+    myenv['wsgi.input'] = sys.stdin.buffer
+    mforms, ofiles = multipart.parse_form_data(environ=myenv)
+    for name, item in mforms.items():
+        oforms[name] = item
+    return oforms, ofiles
+
+
+forms, files = get_request_params()
 
 status = '200 Ok'
 
 try:
-    form = cgi.FieldStorage()
-    input = form['name']
+    ename = forms['name']
 
     # Test if the file was uploaded
-    if input.value is not None:
-        val = os.environ[input.value] if input.value in os.environ else ""
+    if ename is not None:
+        val = os.environ[ename] if ename in os.environ else ""
         print("Status: 200")
         print("""\
 Content-Type: text/plain\n""")
-        print("{0}={1}".format(input.value, val))
+        print(f"{ename}={val}")
 
     else:
         print("Status: 400 Parameter Missing")
         print("""\
 Content-Type: text/html\n
     <html><body>
-    <p>No name was specified: %s</p>
-    </body></html>""" % (count.value))
+    <p>No name was specified: name</p>
+    </body></html>""")
 
 except KeyError:
     print("Status: 200 Ok")
diff --git a/test/modules/http2/htdocs/cgi/hecho.py b/test/modules/http2/htdocs/cgi/hecho.py
index 5c1f79a3..fb9e330b 100644
--- a/test/modules/http2/htdocs/cgi/hecho.py
+++ b/test/modules/http2/htdocs/cgi/hecho.py
@@ -1,18 +1,35 @@
 #!/usr/bin/env python3
-import cgi, os
-import cgitb; cgitb.enable()
+import os, sys
+import multipart
+from urllib import parse
+
+
+def get_request_params():
+    oforms = {}
+    if "REQUEST_URI" in os.environ:
+        qforms = parse.parse_qs(parse.urlsplit(os.environ["REQUEST_URI"]).query)
+        for name, values in qforms.items():
+            oforms[name] = values[0]
+    myenv = os.environ.copy()
+    myenv['wsgi.input'] = sys.stdin.buffer
+    mforms, ofiles = multipart.parse_form_data(environ=myenv)
+    for name, item in mforms.items():
+        oforms[name] = item
+    return oforms, ofiles
+
+
+forms, files = get_request_params()
 
 status = '200 Ok'
 
 try:
-    form = cgi.FieldStorage()
-    
+
     # A nested FieldStorage instance holds the file
-    name = form['name'].value
+    name = forms['name']
     value = ''
     
     try:
-        value = form['value'].value
+        value = forms['value']
     except KeyError:
         value = os.environ.get("HTTP_"+name, "unset")
     
diff --git a/test/modules/http2/htdocs/cgi/mnot164.py b/test/modules/http2/htdocs/cgi/mnot164.py
index 0e5d1072..c29ccc18 100644
--- a/test/modules/http2/htdocs/cgi/mnot164.py
+++ b/test/modules/http2/htdocs/cgi/mnot164.py
@@ -1,19 +1,26 @@
 #!/usr/bin/env python3
+import os, sys
+import multipart
+from urllib import parse
 
-import cgi
-import cgitb; cgitb.enable()
-import os
-import sys
 
-try:
-    form = cgi.FieldStorage()
-    count = form['count'].value
-    text = form['text'].value
-except KeyError:
-    text="a"
-    count=77784
+def get_request_params():
+    oforms = {}
+    if "REQUEST_URI" in os.environ:
+        qforms = parse.parse_qs(parse.urlsplit(os.environ["REQUEST_URI"]).query)
+        for name, values in qforms.items():
+            oforms[name] = values[0]
+    myenv = os.environ.copy()
+    myenv['wsgi.input'] = sys.stdin.buffer
+    mforms, ofiles = multipart.parse_form_data(environ=myenv)
+    for name, item in mforms.items():
+        oforms[name] = item
+    return oforms, ofiles
 
-count = int(count)
+
+forms, files = get_request_params()
+text = forms['text'] if 'text' in forms else "a"
+count = int(forms['count']) if 'count' in forms else 77784
 
 print("Status: 200 OK")
 print("Content-Type: text/html")
diff --git a/test/modules/http2/htdocs/cgi/necho.py b/test/modules/http2/htdocs/cgi/necho.py
index b9249b89..78e2aad3 100644
--- a/test/modules/http2/htdocs/cgi/necho.py
+++ b/test/modules/http2/htdocs/cgi/necho.py
@@ -1,33 +1,49 @@
 #!/usr/bin/env python3
-import cgi, os
 import time
-import cgitb; cgitb.enable()
+import os, sys
+import multipart
+from urllib import parse
 
+
+def get_request_params():
+    oforms = {}
+    if "REQUEST_URI" in os.environ:
+        qforms = parse.parse_qs(parse.urlsplit(os.environ["REQUEST_URI"]).query)
+        for name, values in qforms.items():
+            oforms[name] = values[0]
+    myenv = os.environ.copy()
+    myenv['wsgi.input'] = sys.stdin.buffer
+    mforms, ofiles = multipart.parse_form_data(environ=myenv)
+    for name, item in mforms.items():
+        oforms[name] = item
+    return oforms, ofiles
+
+
+forms, files = get_request_params()
 status = '200 Ok'
 
 try:
-    form = cgi.FieldStorage()
-    count = form['count']
-    text = form['text']
+    count = forms['count']
+    text = forms['text']
     
-    waitsec = float(form['wait1'].value) if 'wait1' in form else 0.0
+    waitsec = float(forms['wait1']) if 'wait1' in forms else 0.0
     if waitsec > 0:
         time.sleep(waitsec)
     
-    if int(count.value):
+    if int(count):
         print("Status: 200")
         print("""\
 Content-Type: text/plain\n""")
 
-        waitsec = float(form['wait2'].value) if 'wait2' in form else 0.0
+        waitsec = float(forms['wait2']) if 'wait2' in forms else 0.0
         if waitsec > 0:
             time.sleep(waitsec)
     
         i = 0;
-        for i in range(0, int(count.value)):
-            print("%s" % (text.value))
+        for i in range(0, int(count)):
+            print("%s" % (text))
 
-        waitsec = float(form['wait3'].value) if 'wait3' in form else 0.0
+        waitsec = float(forms['wait3']) if 'wait3' in forms else 0.0
         if waitsec > 0:
             time.sleep(waitsec)
     
@@ -37,7 +53,7 @@ Content-Type: text/plain\n""")
 Content-Type: text/html\n
     <html><body>
     <p>No count was specified: %s</p>
-    </body></html>""" % (count.value))
+    </body></html>""" % (count))
 
 except KeyError:
     print("Status: 200 Ok")
diff --git a/test/modules/http2/htdocs/cgi/upload.py b/test/modules/http2/htdocs/cgi/upload.py
index 2c8d63aa..59fbb586 100644
--- a/test/modules/http2/htdocs/cgi/upload.py
+++ b/test/modules/http2/htdocs/cgi/upload.py
@@ -1,42 +1,58 @@
 #!/usr/bin/env python3
-import cgi, os
-import cgitb
-cgitb.enable()
+import os
+import sys
+import multipart
+from urllib import parse
 
-status = '200 Ok'
 
-try: # Windows needs stdio set for binary mode.
+try:  # Windows needs stdio set for binary mode.
     import msvcrt
-    msvcrt.setmode (0, os.O_BINARY) # stdin  = 0
-    msvcrt.setmode (1, os.O_BINARY) # stdout = 1
+
+    msvcrt.setmode(0, os.O_BINARY)  # stdin  = 0
+    msvcrt.setmode(1, os.O_BINARY)  # stdout = 1
 except ImportError:
     pass
 
-form = cgi.FieldStorage()
+def get_request_params():
+    oforms = {}
+    if "REQUEST_URI" in os.environ:
+        qforms = parse.parse_qs(parse.urlsplit(os.environ["REQUEST_URI"]).query)
+        for name, values in qforms.items():
+            oforms[name] = values[0]
+    myenv = os.environ.copy()
+    myenv['wsgi.input'] = sys.stdin.buffer
+    mforms, ofiles = multipart.parse_form_data(environ=myenv)
+    for name, item in mforms.items():
+        oforms[name] = item
+    return oforms, ofiles
+
+
+forms, files = get_request_params()
+
+status = '200 Ok'
 
 # Test if the file was uploaded
-if 'file' in form:
-    fileitem = form['file']
+if 'file' in files:
+    fitem = files['file']
     # strip leading path from file name to avoid directory traversal attacks
-    fn = os.path.basename(fileitem.filename)
-    f = open(('%s/files/%s' % (os.environ["DOCUMENT_ROOT"], fn)), 'wb');
-    f.write(fileitem.file.read())
-    f.close()
-    message = "The file %s was uploaded successfully" % (fn)
+    fname = fitem.filename
+    fpath = f'{os.environ["DOCUMENT_ROOT"]}/files/{fname}'
+    fitem.save_as(fpath)
+    message = "The file %s was uploaded successfully" % (fname)
     print("Status: 201 Created")
     print("Content-Type: text/html")
-    print("Location: %s://%s/files/%s" % (os.environ["REQUEST_SCHEME"], os.environ["HTTP_HOST"], fn))
+    print("Location: %s://%s/files/%s" % (os.environ["REQUEST_SCHEME"], os.environ["HTTP_HOST"], fname))
     print("")
     print("<html><body><p>%s</p></body></html>" % (message))
-        
-elif 'remove' in form:
-    remove = form['remove'].value
+
+elif 'remove' in forms:
+    remove = forms['remove']
     try:
-        fn = os.path.basename(remove)
-        os.remove('./files/' + fn)
-        message = 'The file "' + fn + '" was removed successfully'
+        fname = os.path.basename(remove)
+        os.remove('./files/' + fname)
+        message = 'The file "' + fname + '" was removed successfully'
     except OSError as e:
-        message = 'Error removing ' + fn + ': ' + e.strerror
+        message = 'Error removing ' + fname + ': ' + e.strerror
         status = '404 File Not Found'
     print("Status: %s" % (status))
     print("""
diff --git a/test/modules/md/conftest.py b/test/modules/md/conftest.py
index a25ea1aa..04165a2d 100755
--- a/test/modules/md/conftest.py
+++ b/test/modules/md/conftest.py
@@ -50,6 +50,7 @@ def _session_scope(env):
         'AH01909',  # mod_ssl, cert alt name complains
         'AH10170',  # mod_md, wrong config, tested
         'AH10171',  # mod_md, wrong config, tested
+        'AH10373',  # SSL errors on uncompleted handshakes
         'AH10398',  # test on global store lock
     ])
 
diff --git a/test/modules/md/test_702_auto.py b/test/modules/md/test_702_auto.py
index 00d535b5..8e8f5f15 100644
--- a/test/modules/md/test_702_auto.py
+++ b/test/modules/md/test_702_auto.py
@@ -664,7 +664,7 @@ class TestAutov2:
             "<IfModule tls_module>",
             f"  TLSEngine {env.https_port}",
             "</IfModule>",
-            ])
+        ])
         conf.add_md([domain])
         conf.install()
         assert env.apache_restart() == 0
diff --git a/test/modules/md/test_720_wildcard.py b/test/modules/md/test_720_wildcard.py
index 07d0dcad..23b311c3 100644
--- a/test/modules/md/test_720_wildcard.py
+++ b/test/modules/md/test_720_wildcard.py
@@ -1,4 +1,4 @@
-# test wildcard certificates
+# test wildcard certifcates
 import os
 
 import pytest
@@ -25,9 +25,7 @@ class TestWildcard:
         env.clear_store()
         self.test_domain = env.get_request_domain(request)
 
-    # -----------------------------------------------------------------------------------------------
     # test case: a wildcard certificate with ACMEv2, no dns-01 supported
-    #
     def test_md_720_001(self, env):
         domain = self.test_domain
         
@@ -47,9 +45,7 @@ class TestWildcard:
         assert md['renewal']['errors'] > 0
         assert md['renewal']['last']['problem'] == 'challenge-mismatch'
 
-    # -----------------------------------------------------------------------------------------------
-    # test case: a wildcard certificate with ACMEv2, only dns-01 configured, invalid command path 
-    #
+    # test case: a wildcard certificate with ACMEv2, only dns-01 configured, invalid command path
     def test_md_720_002(self, env):
         dns01cmd = os.path.join(env.test_dir, "../modules/md/dns01-not-found.py")
 
@@ -96,9 +92,7 @@ class TestWildcard:
         for domain in domains:
             assert domain in altnames
 
-    # -----------------------------------------------------------------------------------------------
-    # test case: a wildcard certificate with ACMEv2, only dns-01 configured, invalid command option 
-    #
+    # test case: a wildcard certificate with ACMEv2, only dns-01 configured, invalid command option
     def test_md_720_003(self, env):
         dns01cmd = os.path.join(env.test_dir, "../modules/md/dns01.py fail")
         domain = self.test_domain
@@ -120,9 +114,7 @@ class TestWildcard:
         assert md['renewal']['errors'] > 0
         assert md['renewal']['last']['problem'] == 'challenge-setup-failure'
 
-    # -----------------------------------------------------------------------------------------------
-    # test case: a wildcard name certificate with ACMEv2, only dns-01 configured 
-    #
+    # test case: a wildcard name certificate with ACMEv2, only dns-01 configured
     def test_md_720_004(self, env):
         dns01cmd = os.path.join(env.test_dir, "../modules/md/dns01.py")
         domain = self.test_domain
@@ -147,9 +139,7 @@ class TestWildcard:
         for domain in domains:
             assert domain in altnames
 
-    # -----------------------------------------------------------------------------------------------
     # test case: a wildcard name and 2nd normal vhost, not overlapping
-    #
     def test_md_720_005(self, env):
         dns01cmd = os.path.join(env.test_dir, "../modules/md/dns01.py")
         domain = self.test_domain
@@ -176,7 +166,6 @@ class TestWildcard:
         for domain in domains:
             assert domain in altnames
 
-    # -----------------------------------------------------------------------------------------------
     # test case: a wildcard name and 2nd normal vhost, overlapping
     def test_md_720_006(self, env):
         dns01cmd = os.path.join(env.test_dir, "../modules/md/dns01.py")
@@ -205,7 +194,6 @@ class TestWildcard:
         for domain in [domain, dwild]:
             assert domain in altnames
 
-    # -----------------------------------------------------------------------------------------------
     # test case: a MDomain with just a wildcard, see #239
     def test_md_720_007(self, env):
         dns01cmd = os.path.join(env.test_dir, "../modules/md/dns01.py")
@@ -231,3 +219,36 @@ class TestWildcard:
         cert_a = env.get_cert(wwwdomain)
         altnames = cert_a.get_san_list()
         assert domains == altnames
+
+    # test case: a plain name, only dns-01 configured,
+    # http-01 should not be intercepted. See #279
+    def test_md_720_008(self, env):
+        dns01cmd = os.path.join(env.test_dir, "../modules/md/dns01.py")
+        domain = self.test_domain
+        domains = [domain]
+
+        conf = MDConf(env)
+        conf.add("MDCAChallenges dns-01")
+        conf.add(f"MDChallengeDns01 {dns01cmd}")
+        conf.add_md(domains)
+        conf.add_vhost(domains)
+        conf.add("LogLevel http:trace4")
+        conf.install()
+
+        challengedir = os.path.join(env.server_dir, "htdocs/test1/.well-known/acme-challenge")
+        env.mkpath(challengedir)
+        content = b'not a challenge'
+        with open(os.path.join(challengedir, "123456"), "wb") as fd:
+            fd.write(content)
+
+        # restart, check that md is in store
+        assert env.apache_restart() == 0
+        env.check_md(domains)
+        # await drive completion
+        assert env.await_completion([domain], restart=False)
+        # access a fake http-01 challenge on the domain
+        r = env.curl_get(f"http://{domain}:{env.http_port}/.well-known/acme-challenge/123456";)
+        assert r.response['status'] == 200
+        assert r.response['body'] == content
+        assert env.apache_restart() == 0
+        env.check_md_complete(domain)
diff --git a/test/modules/md/test_800_must_staple.py b/test/modules/md/test_800_must_staple.py
index 06e881c2..32edee33 100644
--- a/test/modules/md/test_800_must_staple.py
+++ b/test/modules/md/test_800_must_staple.py
@@ -47,7 +47,7 @@ class TestMustStaple:
         cert1 = MDCertUtil(env.store_domain_file(self.domain, 'pubcert.pem'))
         assert not cert1.get_must_staple()
         stat = env.get_ocsp_status(self.domain)
-        assert stat['ocsp'] == "no response sent" 
+        assert 'ocsp' not in stat or stat['ocsp'] == "no response sent"
 
     # MD that must staple and toggle off again
     @pytest.mark.skipif(MDTestEnv.lacks_ocsp(), reason="no OCSP responder")
diff --git a/test/modules/tls/env.py b/test/modules/tls/env.py
index e60c3217..a39fcaaa 100644
--- a/test/modules/tls/env.py
+++ b/test/modules/tls/env.py
@@ -3,13 +3,9 @@ import logging
 import os
 import re
 import subprocess
-import sys
-import time
 
 from datetime import timedelta, datetime
-from http.client import HTTPConnection
 from typing import List, Optional, Dict, Tuple, Union
-from urllib.parse import urlparse
 
 from pyhttpd.certs import CertificateSpec
 from pyhttpd.env import HttpdTestEnv, HttpdTestSetup
@@ -57,6 +53,22 @@ class TlsCipher:
 
 class TlsTestEnv(HttpdTestEnv):
 
+    CURL_SUPPORTS_TLS_1_3 = None
+
+    @classmethod
+    def curl_supports_tls_1_3(cls) -> bool:
+        if cls.CURL_SUPPORTS_TLS_1_3 is None:
+            # Unfortunately, there is no reliable, platform-independant
+            # way to verify that TLSv1.3 is properly supported by curl.
+            #
+            # p = subprocess.run(['curl', '--tlsv1.3', 'https://shouldneverexistreally'],
+            #                    stderr=subprocess.PIPE, stdout=subprocess.PIPE)
+            # return code 6 means the site could not be resolved, but the
+            # tls parameter was recognized
+            cls.CURL_SUPPORTS_TLS_1_3 = False
+        return cls.CURL_SUPPORTS_TLS_1_3
+
+
     # current rustls supported ciphers in their order of preference
     # used to test cipher selection, see test_06_ciphers.py
     RUSTLS_CIPHERS = [
@@ -159,14 +171,6 @@ class TlsTestEnv(HttpdTestEnv):
         args.extend([])
         return self.openssl(args)
 
-    CURL_SUPPORTS_TLS_1_3 = None
-
-    def curl_supports_tls_1_3(self) -> bool:
-        if self.CURL_SUPPORTS_TLS_1_3 is None:
-            r = self.tls_get(self.domain_a, "/index.json", options=["--tlsv1.3"])
-            self.CURL_SUPPORTS_TLS_1_3 = r.exit_code == 0
-        return self.CURL_SUPPORTS_TLS_1_3
-
     OPENSSL_SUPPORTED_PROTOCOLS = None
 
     @staticmethod
diff --git a/test/modules/tls/htdocs/a.mod-tls.test/vars.py b/test/modules/tls/htdocs/a.mod-tls.test/vars.py
index 4ab491b5..f41ec6a5 100755
--- a/test/modules/tls/htdocs/a.mod-tls.test/vars.py
+++ b/test/modules/tls/htdocs/a.mod-tls.test/vars.py
@@ -1,7 +1,25 @@
 #!/usr/bin/env python3
 import json
-import os, cgi
-import re
+import os, sys
+import multipart
+from urllib import parse
+
+
+def get_request_params():
+    oforms = {}
+    if "REQUEST_URI" in os.environ:
+        qforms = parse.parse_qs(parse.urlsplit(os.environ["REQUEST_URI"]).query)
+        for name, values in qforms.items():
+            oforms[name] = values[0]
+    myenv = os.environ.copy()
+    myenv['wsgi.input'] = sys.stdin.buffer
+    mforms, ofiles = multipart.parse_form_data(environ=myenv)
+    for name, item in mforms.items():
+        oforms[name] = item
+    return oforms, ofiles
+
+
+forms, files = get_request_params()
 
 jenc = json.JSONEncoder()
 
@@ -15,13 +33,7 @@ def get_json_var(name: str, def_val: str = ""):
     return jenc.encode(var)
 
 
-name = None
-try:
-    form = cgi.FieldStorage()
-    if 'name' in form:
-        name = str(form['name'].value)
-except Exception:
-    pass
+name = forms['name'] if 'name' in forms else None
 
 print("Content-Type: application/json\n")
 if name:
diff --git a/test/modules/tls/htdocs/b.mod-tls.test/vars.py b/test/modules/tls/htdocs/b.mod-tls.test/vars.py
index 9289c5cb..f41ec6a5 100755
--- a/test/modules/tls/htdocs/b.mod-tls.test/vars.py
+++ b/test/modules/tls/htdocs/b.mod-tls.test/vars.py
@@ -1,6 +1,25 @@
 #!/usr/bin/env python3
 import json
-import os, cgi
+import os, sys
+import multipart
+from urllib import parse
+
+
+def get_request_params():
+    oforms = {}
+    if "REQUEST_URI" in os.environ:
+        qforms = parse.parse_qs(parse.urlsplit(os.environ["REQUEST_URI"]).query)
+        for name, values in qforms.items():
+            oforms[name] = values[0]
+    myenv = os.environ.copy()
+    myenv['wsgi.input'] = sys.stdin.buffer
+    mforms, ofiles = multipart.parse_form_data(environ=myenv)
+    for name, item in mforms.items():
+        oforms[name] = item
+    return oforms, ofiles
+
+
+forms, files = get_request_params()
 
 jenc = json.JSONEncoder()
 
@@ -14,13 +33,7 @@ def get_json_var(name: str, def_val: str = ""):
     return jenc.encode(var)
 
 
-name = None
-try:
-    form = cgi.FieldStorage()
-    if 'name' in form:
-        name = str(form['name'].value)
-except Exception:
-    pass
+name = forms['name'] if 'name' in forms else None
 
 print("Content-Type: application/json\n")
 if name:
diff --git a/test/modules/tls/test_01_apache.py b/test/modules/tls/test_01_apache.py
index eb9b32e1..cb6af6d4 100644
--- a/test/modules/tls/test_01_apache.py
+++ b/test/modules/tls/test_01_apache.py
@@ -10,5 +10,5 @@ class TestApache:
         TlsTestConf(env=env).install()
         assert env.apache_restart() == 0
 
-    def test_01_apache_http(self, env):
+    def test_tls_01_apache_http(self, env):
         assert env.is_live(env.http_base_url)
diff --git a/test/modules/tls/test_02_conf.py b/test/modules/tls/test_02_conf.py
index f34b85e5..4d6aa602 100644
--- a/test/modules/tls/test_02_conf.py
+++ b/test/modules/tls/test_02_conf.py
@@ -18,25 +18,25 @@ class TestConf:
         if env.is_live(timeout=timedelta(milliseconds=100)):
             assert env.apache_stop() == 0
 
-    def test_02_conf_cert_args_missing(self, env):
+    def test_tls_02_conf_cert_args_missing(self, env):
         conf = TlsTestConf(env=env)
         conf.add("TLSCertificate")
         conf.install()
         assert env.apache_fail() == 0
 
-    def test_02_conf_cert_single_arg(self, env):
+    def test_tls_02_conf_cert_single_arg(self, env):
         conf = TlsTestConf(env=env)
         conf.add("TLSCertificate cert.pem")
         conf.install()
         assert env.apache_fail() == 0
 
-    def test_02_conf_cert_file_missing(self, env):
+    def test_tls_02_conf_cert_file_missing(self, env):
         conf = TlsTestConf(env=env)
         conf.add("TLSCertificate cert.pem key.pem")
         conf.install()
         assert env.apache_fail() == 0
 
-    def test_02_conf_cert_file_exist(self, env):
+    def test_tls_02_conf_cert_file_exist(self, env):
         conf = TlsTestConf(env=env)
         conf.add("TLSCertificate test-02-cert.pem test-02-key.pem")
         conf.install()
@@ -45,13 +45,13 @@ class TestConf:
                 fd.write("")
         assert env.apache_fail() == 0
 
-    def test_02_conf_cert_listen_missing(self, env):
+    def test_tls_02_conf_cert_listen_missing(self, env):
         conf = TlsTestConf(env=env)
         conf.add("TLSEngine")
         conf.install()
         assert env.apache_fail() == 0
 
-    def test_02_conf_cert_listen_wrong(self, env):
+    def test_tls_02_conf_cert_listen_wrong(self, env):
         conf = TlsTestConf(env=env)
         conf.add("TLSEngine ^^^^^")
         conf.install()
@@ -62,20 +62,20 @@ class TestConf:
         "129.168.178.188:443",
         "[::]:443",
     ])
-    def test_02_conf_cert_listen_valid(self, env, listen: str):
+    def test_tls_02_conf_cert_listen_valid(self, env, listen: str):
         conf = TlsTestConf(env=env)
         conf.add("TLSEngine {listen}".format(listen=listen))
         conf.install()
         assert env.apache_restart() == 0
 
-    def test_02_conf_cert_listen_cert(self, env):
+    def test_tls_02_conf_cert_listen_cert(self, env):
         domain = env.domain_a
         conf = TlsTestConf(env=env)
         conf.add_tls_vhosts(domains=[domain])
         conf.install()
         assert env.apache_restart() == 0
 
-    def test_02_conf_proto_wrong(self, env):
+    def test_tls_02_conf_proto_wrong(self, env):
         conf = TlsTestConf(env=env)
         conf.add("TLSProtocol wrong")
         conf.install()
@@ -87,13 +87,13 @@ class TestConf:
         "TLSv1.3+",
         "TLSv0x0303+",
     ])
-    def test_02_conf_proto_valid(self, env, proto):
+    def test_tls_02_conf_proto_valid(self, env, proto):
         conf = TlsTestConf(env=env)
         conf.add("TLSProtocol {proto}".format(proto=proto))
         conf.install()
         assert env.apache_restart() == 0
 
-    def test_02_conf_honor_wrong(self, env):
+    def test_tls_02_conf_honor_wrong(self, env):
         conf = TlsTestConf(env=env)
         conf.add("TLSHonorClientOrder wrong")
         conf.install()
@@ -103,7 +103,7 @@ class TestConf:
         "on",
         "OfF",
     ])
-    def test_02_conf_honor_valid(self, env, honor: str):
+    def test_tls_02_conf_honor_valid(self, env, honor: str):
         conf = TlsTestConf(env=env)
         conf.add("TLSHonorClientOrder {honor}".format(honor=honor))
         conf.install()
@@ -119,7 +119,7 @@ class TestConf:
         TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384  TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384\\
         TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"""
     ])
-    def test_02_conf_cipher_valid(self, env, cipher):
+    def test_tls_02_conf_cipher_valid(self, env, cipher):
         conf = TlsTestConf(env=env)
         conf.add("TLSCiphersPrefer {cipher}".format(cipher=cipher))
         conf.install()
@@ -131,7 +131,7 @@ class TestConf:
         "TLS_NULL_WITH_NULL_NULLX",       # not supported
         "TLS_DHE_RSA_WITH_AES128_GCM_SHA256",     # not supported
     ])
-    def test_02_conf_cipher_wrong(self, env, cipher):
+    def test_tls_02_conf_cipher_wrong(self, env, cipher):
         conf = TlsTestConf(env=env)
         conf.add("TLSCiphersPrefer {cipher}".format(cipher=cipher))
         conf.install()
diff --git a/test/modules/tls/test_03_sni.py b/test/modules/tls/test_03_sni.py
index eda9a33a..cf421c0f 100644
--- a/test/modules/tls/test_03_sni.py
+++ b/test/modules/tls/test_03_sni.py
@@ -3,6 +3,7 @@ from datetime import timedelta
 import pytest
 
 from .conf import TlsTestConf
+from .env import TlsTestEnv
 
 
 class TestSni:
@@ -13,29 +14,28 @@ class TestSni:
         conf.add_tls_vhosts(domains=[env.domain_a, env.domain_b])
         conf.install()
         assert env.apache_restart() == 0
-        env.curl_supports_tls_1_3()  # init
 
     @pytest.fixture(autouse=True, scope='function')
     def _function_scope(self, env):
         pass
 
-    def test_03_sni_get_a(self, env):
+    def test_tls_03_sni_get_a(self, env):
         # do we see the correct json for the domain_a?
         data = env.tls_get_json(env.domain_a, "/index.json")
         assert data == {'domain': env.domain_a}
 
-    def test_03_sni_get_b(self, env):
+    def test_tls_03_sni_get_b(self, env):
         # do we see the correct json for the domain_a?
         data = env.tls_get_json(env.domain_b, "/index.json")
         assert data == {'domain': env.domain_b}
 
-    def test_03_sni_unknown(self, env):
+    def test_tls_03_sni_unknown(self, env):
         # connection will be denied as cert does not cover this domain
         domain_unknown = "unknown.test"
         r = env.tls_get(domain_unknown, "/index.json")
         assert r.exit_code != 0
 
-    def test_03_sni_request_other_same_config(self, env):
+    def test_tls_03_sni_request_other_same_config(self, env):
         # do we see the first vhost response for another domain with different certs?
         r = env.tls_get(env.domain_a, "/index.json", options=[
             "-vvvv", "--header", "Host: {0}".format(env.domain_b)
@@ -45,10 +45,7 @@ class TestSni:
         assert r.json is None
         assert r.response['status'] == 421
 
-    def test_03_sni_request_other_other_honor(self, env):
-        if env.curl_supports_tls_1_3():
-            # can't do this test then
-            return
+    def test_tls_03_sni_request_other_other_honor(self, env):
         # do we see the first vhost response for an unknown domain?
         conf = TlsTestConf(env=env, extras={
             env.domain_a: "TLSProtocol TLSv1.2+",
@@ -58,13 +55,14 @@ class TestSni:
         conf.install()
         assert env.apache_restart() == 0
         r = env.tls_get(env.domain_a, "/index.json", options=[
-            "-vvvv", "--header", "Host: {0}".format(env.domain_b)
+            "-vvvv", "--tls-max", "1.2", "--header", "Host: {0}".format(env.domain_b)
         ])
         # request denied
         assert r.exit_code == 0
         assert r.json is None
 
-    def test_03_sni_bad_hostname(self, env):
+    @pytest.mark.skip('openssl behaviour changed on ventura, unreliable')
+    def test_tls_03_sni_bad_hostname(self, env):
         # curl checks hostnames we give it, but the openssl client
         # does not. Good for us, since we need to test it.
         r = env.openssl(["s_client", "-connect",
diff --git a/test/modules/tls/test_04_get.py b/test/modules/tls/test_04_get.py
index 6621f8aa..4412a66d 100644
--- a/test/modules/tls/test_04_get.py
+++ b/test/modules/tls/test_04_get.py
@@ -39,7 +39,7 @@ class TestGet:
         ("1m.txt", 1000 * 1024),
         ("10m.txt", 10000 * 1024),
     ])
-    def test_04_get(self, env, fname, flen):
+    def test_tls_04_get(self, env, fname, flen):
         # do we see the correct json for the domain_a?
         docs_a = os.path.join(env.server_docs_dir, env.domain_a)
         r = env.tls_get(env.domain_a, "/{0}".format(fname))
@@ -55,7 +55,7 @@ class TestGet:
     @pytest.mark.parametrize("fname, flen", [
         ("1k.txt", 1024),
     ])
-    def test_04_double_get(self, env, fname, flen):
+    def test_tls_04_double_get(self, env, fname, flen):
         # we'd like to check that we can do >1 requests on the same connection
         # however curl hides that from us, unless we analyze its verbose output
         docs_a = os.path.join(env.server_docs_dir, env.domain_a)
diff --git a/test/modules/tls/test_05_proto.py b/test/modules/tls/test_05_proto.py
index 7165f21b..447d052b 100644
--- a/test/modules/tls/test_05_proto.py
+++ b/test/modules/tls/test_05_proto.py
@@ -6,6 +6,7 @@ from threading import Thread
 import pytest
 
 from .conf import TlsTestConf
+from .env import TlsTestEnv
 
 
 class TestProto:
@@ -29,28 +30,26 @@ class TestProto:
     def _function_scope(self, env):
         pass
 
-    CURL_SUPPORTS_TLS_1_3 = None
-
-    def test_05_proto_1_2(self, env):
+    def test_tls_05_proto_1_2(self, env):
         r = env.tls_get(env.domain_b, "/index.json", options=["--tlsv1.2"])
         assert r.exit_code == 0, r.stderr
-        if env.curl_supports_tls_1_3():
+        if TlsTestEnv.curl_supports_tls_1_3():
             r = env.tls_get(env.domain_b, "/index.json", options=["--tlsv1.3"])
             assert r.exit_code == 0, r.stderr
 
-    def test_05_proto_1_3(self, env):
+    def test_tls_05_proto_1_3(self, env):
         r = env.tls_get(env.domain_a, "/index.json", options=["--tlsv1.3"])
-        if env.curl_supports_tls_1_3():
+        if TlsTestEnv.curl_supports_tls_1_3():
             assert r.exit_code == 0, r.stderr
         else:
             assert r.exit_code == 4, r.stderr
 
-    def test_05_proto_close(self, env):
+    def test_tls_05_proto_close(self, env):
         s = socket.create_connection(('localhost', env.https_port))
         time.sleep(0.1)
         s.close()
 
-    def test_05_proto_ssl_close(self, env):
+    def test_tls_05_proto_ssl_close(self, env):
         conf = TlsTestConf(env=env, extras={
             'base': "LogLevel ssl:debug",
             env.domain_a: "SSLProtocol TLSv1.3",
diff --git a/test/modules/tls/test_06_ciphers.py b/test/modules/tls/test_06_ciphers.py
index 650c0dab..2e60bdd7 100644
--- a/test/modules/tls/test_06_ciphers.py
+++ b/test/modules/tls/test_06_ciphers.py
@@ -35,7 +35,7 @@ class TestCiphers:
                 cipher = m.group(1)
         return protocol, cipher
 
-    def test_06_ciphers_ecdsa(self, env):
+    def test_tls_06_ciphers_ecdsa(self, env):
         ecdsa_1_2 = [c for c in env.RUSTLS_CIPHERS
                      if c.max_version == 1.2 and c.flavour == 'ECDSA'][0]
         # client speaks only this cipher, see that it gets it
@@ -46,7 +46,7 @@ class TestCiphers:
         assert protocol == "TLSv1.2", r.stdout
         assert cipher == ecdsa_1_2.openssl_name, r.stdout
 
-    def test_06_ciphers_rsa(self, env):
+    def test_tls_06_ciphers_rsa(self, env):
         rsa_1_2 = [c for c in env.RUSTLS_CIPHERS
                    if c.max_version == 1.2 and c.flavour == 'RSA'][0]
         # client speaks only this cipher, see that it gets it
@@ -62,7 +62,7 @@ class TestCiphers:
     ], ids=[
         c.name for c in TlsTestEnv.RUSTLS_CIPHERS if c.max_version == 1.2 and c.flavour == 'ECDSA'
     ])
-    def test_06_ciphers_server_prefer_ecdsa(self, env, cipher):
+    def test_tls_06_ciphers_server_prefer_ecdsa(self, env, cipher):
         # Select a ECSDA ciphers as preference and suppress all RSA ciphers.
         # The last is not strictly necessary since rustls prefers ECSDA anyway
         suppress_names = [c.name for c in env.RUSTLS_CIPHERS
@@ -89,7 +89,7 @@ class TestCiphers:
     ], ids=[
         c.name for c in TlsTestEnv.RUSTLS_CIPHERS if c.max_version == 1.2 and c.flavour == 'RSA'
     ])
-    def test_06_ciphers_server_prefer_rsa(self, env, cipher):
+    def test_tls_06_ciphers_server_prefer_rsa(self, env, cipher):
         # Select a RSA ciphers as preference and suppress all ECDSA ciphers.
         # The last is necessary since rustls prefers ECSDA and openssl leaks that it can.
         suppress_names = [c.name for c in env.RUSTLS_CIPHERS
@@ -116,7 +116,7 @@ class TestCiphers:
     ], ids=[
         c.openssl_name for c in TlsTestEnv.RUSTLS_CIPHERS if c.max_version == 1.2 and c.flavour == 'RSA'
     ])
-    def test_06_ciphers_server_prefer_rsa_alias(self, env, cipher):
+    def test_tls_06_ciphers_server_prefer_rsa_alias(self, env, cipher):
         # same as above, but using openssl names for ciphers
         suppress_names = [c.openssl_name for c in env.RUSTLS_CIPHERS
                           if c.max_version == 1.2 and c.flavour == 'ECDSA']
@@ -142,7 +142,7 @@ class TestCiphers:
     ], ids=[
         c.id_name for c in TlsTestEnv.RUSTLS_CIPHERS if c.max_version == 1.2 and c.flavour == 'RSA'
     ])
-    def test_06_ciphers_server_prefer_rsa_id(self, env, cipher):
+    def test_tls_06_ciphers_server_prefer_rsa_id(self, env, cipher):
         # same as above, but using openssl names for ciphers
         suppress_names = [c.id_name for c in env.RUSTLS_CIPHERS
                           if c.max_version == 1.2 and c.flavour == 'ECDSA']
@@ -161,7 +161,7 @@ class TestCiphers:
         assert client_proto == "TLSv1.2", r.stdout
         assert client_cipher == cipher.openssl_name, r.stdout
 
-    def test_06_ciphers_pref_unknown(self, env):
+    def test_tls_06_ciphers_pref_unknown(self, env):
         conf = TlsTestConf(env=env, extras={
             env.domain_b: "TLSCiphersPrefer TLS_MY_SUPER_CIPHER:SSL_WHAT_NOT"
         })
@@ -174,7 +174,7 @@ class TestCiphers:
         conf.install()
         env.apache_restart()
 
-    def test_06_ciphers_pref_unsupported(self, env):
+    def test_tls_06_ciphers_pref_unsupported(self, env):
         # a warning on preferring a known, but not supported cipher
         env.httpd_error_log.ignore_recent()
         conf = TlsTestConf(env=env, extras={
@@ -187,7 +187,7 @@ class TestCiphers:
         assert errors == 0
         assert warnings == 2  # once on dry run, once on start
 
-    def test_06_ciphers_supp_unknown(self, env):
+    def test_tls_06_ciphers_supp_unknown(self, env):
         conf = TlsTestConf(env=env, extras={
             env.domain_b: "TLSCiphersSuppress TLS_MY_SUPER_CIPHER:SSL_WHAT_NOT"
         })
@@ -195,7 +195,7 @@ class TestCiphers:
         conf.install()
         assert env.apache_restart() != 0
 
-    def test_06_ciphers_supp_unsupported(self, env):
+    def test_tls_06_ciphers_supp_unsupported(self, env):
         # no warnings on suppressing known, but not supported ciphers
         env.httpd_error_log.ignore_recent()
         conf = TlsTestConf(env=env, extras={
diff --git a/test/modules/tls/test_07_alpn.py b/test/modules/tls/test_07_alpn.py
index 9f70f5f6..06aff3ca 100644
--- a/test/modules/tls/test_07_alpn.py
+++ b/test/modules/tls/test_07_alpn.py
@@ -23,19 +23,19 @@ class TestAlpn:
 
     def _get_protocol(self, output: str):
         for line in output.splitlines():
-            m = re.match(r'^\*\s+ALPN, server accepted to use\s+(.*)$', line)
+            m = re.match(r'^\*\s+ALPN[:,] server accepted (to use\s+)?(.*)$', line)
             if m:
-                return m.group(1)
+                return m.group(2)
         return None
 
-    def test_07_alpn_get_a(self, env):
+    def test_tls_07_alpn_get_a(self, env):
         # do we see the correct json for the domain_a?
-        r = env.tls_get(env.domain_a, "/index.json", options=["-vvvvvv"])
+        r = env.tls_get(env.domain_a, "/index.json", options=["-vvvvvv", "--http1.1"])
         assert r.exit_code == 0, r.stderr
         protocol = self._get_protocol(r.stderr)
         assert protocol == "http/1.1", r.stderr
 
-    def test_07_alpn_get_b(self, env):
+    def test_tls_07_alpn_get_b(self, env):
         # do we see the correct json for the domain_a?
         r = env.tls_get(env.domain_b, "/index.json", options=["-vvvvvv"])
         assert r.exit_code == 0, r.stderr
diff --git a/test/modules/tls/test_08_vars.py b/test/modules/tls/test_08_vars.py
index 45272133..f1bd9b41 100644
--- a/test/modules/tls/test_08_vars.py
+++ b/test/modules/tls/test_08_vars.py
@@ -20,7 +20,7 @@ class TestVars:
         conf.install()
         assert env.apache_restart() == 0
 
-    def test_08_vars_root(self, env):
+    def test_tls_08_vars_root(self, env):
         # in domain_b root, the StdEnvVars is switch on
         exp_proto = "TLSv1.2"
         exp_cipher = "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"
@@ -44,7 +44,7 @@ class TestVars:
         ("SSL_CIPHER_EXPORT", "false"),
         ("SSL_CLIENT_VERIFY", "NONE"),
     ])
-    def test_08_vars_const(self, env, name: str, value: str):
+    def test_tls_08_vars_const(self, env, name: str, value: str):
         r = env.tls_get(env.domain_b, f"/vars.py?name={name}")
         assert r.exit_code == 0, r.stderr
         assert r.json == {name: value}, r.stdout
@@ -53,7 +53,7 @@ class TestVars:
         ("SSL_VERSION_INTERFACE", r'mod_tls/\d+\.\d+\.\d+'),
         ("SSL_VERSION_LIBRARY", r'rustls-ffi/\d+\.\d+\.\d+/rustls/\d+\.\d+\.\d+'),
     ])
-    def test_08_vars_match(self, env, name: str, pattern: str):
+    def test_tls_08_vars_match(self, env, name: str, pattern: str):
         r = env.tls_get(env.domain_b, f"/vars.py?name={name}")
         assert r.exit_code == 0, r.stderr
         assert name in r.json
diff --git a/test/modules/tls/test_09_timeout.py b/test/modules/tls/test_09_timeout.py
index 567f2562..70cc8941 100644
--- a/test/modules/tls/test_09_timeout.py
+++ b/test/modules/tls/test_09_timeout.py
@@ -21,7 +21,7 @@ class TestTimeout:
     def _function_scope(self, env):
         pass
 
-    def test_09_timeout_handshake(self, env):
+    def test_tls_09_timeout_handshake(self, env):
         # in domain_b root, the StdEnvVars is switch on
         s = socket.create_connection(('localhost', env.https_port))
         s.send(b'1234')
diff --git a/test/modules/tls/test_10_session_id.py b/test/modules/tls/test_10_session_id.py
index 1ac03e94..848bc1a5 100644
--- a/test/modules/tls/test_10_session_id.py
+++ b/test/modules/tls/test_10_session_id.py
@@ -25,7 +25,7 @@ class TestSessionID:
                 ids.append(m.group(1))
         return ids
 
-    def test_10_session_id_12(self, env):
+    def test_tls_10_session_id_12(self, env):
         r = env.openssl_client(env.domain_b, extra_args=[
             "-reconnect", "-tls1_2"
         ])
@@ -37,7 +37,7 @@ class TestSessionID:
 
     @pytest.mark.skipif(True or not TlsTestEnv.openssl_supports_tls_1_3(),
                         reason="openssl TLSv1.3 session storage test incomplete")
-    def test_10_session_id_13(self, env):
+    def test_tls_10_session_id_13(self, env):
         r = env.openssl_client(env.domain_b, extra_args=[
             "-reconnect", "-tls1_3"
         ])
diff --git a/test/modules/tls/test_11_md.py b/test/modules/tls/test_11_md.py
index de318c9e..9d733db9 100644
--- a/test/modules/tls/test_11_md.py
+++ b/test/modules/tls/test_11_md.py
@@ -17,17 +17,17 @@ class TestMD:
         conf.install()
         assert env.apache_restart() == 0
 
-    def test_11_get_a(self, env):
+    def test_tls_11_get_a(self, env):
         # do we see the correct json for the domain_a?
         data = env.tls_get_json(env.domain_a, "/index.json")
         assert data == {'domain': env.domain_a}
 
-    def test_11_get_b(self, env):
+    def test_tls_11_get_b(self, env):
         # do we see the correct json for the domain_a?
         data = env.tls_get_json(env.domain_b, "/index.json")
         assert data == {'domain': env.domain_b}
 
-    def test_11_get_base(self, env):
+    def test_tls_11_get_base(self, env):
         # give the base server domain_a and lookup its index.json
         conf = TlsTestConf(env=env)
         conf.add_md_base(domain=env.domain_a)
diff --git a/test/modules/tls/test_12_cauth.py b/test/modules/tls/test_12_cauth.py
index 580df773..14116091 100644
--- a/test/modules/tls/test_12_cauth.py
+++ b/test/modules/tls/test_12_cauth.py
@@ -45,7 +45,7 @@ class TestTLS:
         assert r.json, r.stderr + r.stdout
         return r.json[name] if name in r.json else None
 
-    def test_12_set_ca_non_existing(self, env):
+    def test_tls_12_set_ca_non_existing(self, env):
         conf = TlsTestConf(env=env, extras={
             env.domain_a: "TLSClientCA xxx"
         })
@@ -53,7 +53,7 @@ class TestTLS:
         conf.install()
         assert env.apache_restart() == 1
 
-    def test_12_set_ca_existing(self, env, cax_file):
+    def test_tls_12_set_ca_existing(self, env, cax_file):
         conf = TlsTestConf(env=env, extras={
             env.domain_a: f"TLSClientCA {cax_file}"
         })
@@ -61,7 +61,7 @@ class TestTLS:
         conf.install()
         assert env.apache_restart() == 0
 
-    def test_12_set_auth_no_ca(self, env):
+    def test_tls_12_set_auth_no_ca(self, env):
         conf = TlsTestConf(env=env, extras={
             env.domain_a: "TLSClientCertificate required"
         })
@@ -70,7 +70,7 @@ class TestTLS:
         # will fail bc lacking clien CA
         assert env.apache_restart() == 1
 
-    def test_12_auth_option_std(self, env, cax_file, clients_x):
+    def test_tls_12_auth_option_std(self, env, cax_file, clients_x):
         conf = TlsTestConf(env=env, extras={
             env.domain_b: [
                 f"TLSClientCertificate required",
@@ -102,7 +102,7 @@ class TestTLS:
         val = self.get_ssl_var(env, env.domain_b, ccert, "SSL_CLIENT_CERT")
         assert val == ""
 
-    def test_12_auth_option_cert(self, env, test_ca, cax_file, clients_x):
+    def test_tls_12_auth_option_cert(self, env, test_ca, cax_file, clients_x):
         conf = TlsTestConf(env=env, extras={
             env.domain_b: [
                 "TLSClientCertificate required",
@@ -124,7 +124,7 @@ class TestTLS:
         server_certs = test_ca.get_credentials_for_name(env.domain_b)
         assert val in [c.cert_pem.decode() for c in server_certs]
 
-    def test_12_auth_ssl_optional(self, env, cax_file, clients_x):
+    def test_tls_12_auth_ssl_optional(self, env, cax_file, clients_x):
         domain = env.domain_b
         conf = TlsTestConf(env=env, extras={
             domain: [
@@ -164,7 +164,7 @@ class TestTLS:
         val = self.get_ssl_var(env, env.domain_b, ccert, "SSL_CLIENT_CERT")
         assert val == ccert.cert_pem.decode()
 
-    def test_12_auth_optional(self, env, cax_file, clients_x):
+    def test_tls_12_auth_optional(self, env, cax_file, clients_x):
         domain = env.domain_b
         conf = TlsTestConf(env=env, extras={
             domain: [
@@ -197,7 +197,7 @@ class TestTLS:
             'SSL_CLIENT_S_DN_CN': 'Not Implemented',
         }, r.stdout
 
-    def test_12_auth_expired(self, env, cax_file, clients_x):
+    def test_tls_12_auth_expired(self, env, cax_file, clients_x):
         conf = TlsTestConf(env=env, extras={
             env.domain_b: [
                 "TLSClientCertificate required",
@@ -213,7 +213,7 @@ class TestTLS:
         ])
         assert r.exit_code != 0
 
-    def test_12_auth_other_ca(self, env, cax_file, clients_y):
+    def test_tls_12_auth_other_ca(self, env, cax_file, clients_y):
         conf = TlsTestConf(env=env, extras={
             env.domain_b: [
                 "TLSClientCertificate required",
diff --git a/test/modules/tls/test_13_proxy.py b/test/modules/tls/test_13_proxy.py
index affea979..8bd305f7 100644
--- a/test/modules/tls/test_13_proxy.py
+++ b/test/modules/tls/test_13_proxy.py
@@ -22,7 +22,7 @@ class TestProxy:
         conf.install()
         assert env.apache_restart() == 0
 
-    def test_13_proxy_http_get(self, env):
+    def test_tls_13_proxy_http_get(self, env):
         data = env.tls_get_json(env.domain_b, "/proxy/index.json")
         assert data == {'domain': env.domain_b}
 
@@ -34,7 +34,7 @@ class TestProxy:
         ("SSL_CIPHER_EXPORT", ""),
         ("SSL_CLIENT_VERIFY", ""),
     ])
-    def test_13_proxy_http_vars(self, env, name: str, value: str):
+    def test_tls_13_proxy_http_vars(self, env, name: str, value: str):
         r = env.tls_get(env.domain_b, f"/proxy/vars.py?name={name}")
         assert r.exit_code == 0, r.stderr
         assert r.json == {name: value}, r.stdout
diff --git a/test/modules/tls/test_14_proxy_ssl.py b/test/modules/tls/test_14_proxy_ssl.py
index 18b7b0f1..79b2fb4b 100644
--- a/test/modules/tls/test_14_proxy_ssl.py
+++ b/test/modules/tls/test_14_proxy_ssl.py
@@ -40,16 +40,16 @@ class TestProxySSL:
         conf.install()
         assert env.apache_restart() == 0
 
-    def test_14_proxy_ssl_get(self, env):
+    def test_tls_14_proxy_ssl_get(self, env):
         data = env.tls_get_json(env.domain_b, "/proxy-ssl/index.json")
         assert data == {'domain': env.domain_b}
 
-    def test_14_proxy_ssl_get_local(self, env):
+    def test_tls_14_proxy_ssl_get_local(self, env):
         # does not work, since SSLProxy* not configured
         data = env.tls_get_json(env.domain_b, "/proxy-local/index.json")
         assert data is None
 
-    def test_14_proxy_ssl_h2_get(self, env):
+    def test_tls_14_proxy_ssl_h2_get(self, env):
         r = env.tls_get(env.domain_b, "/proxy-h2-ssl/index.json")
         assert r.exit_code == 0
         assert r.json == {'domain': env.domain_b}
@@ -62,7 +62,7 @@ class TestProxySSL:
         ("SSL_CIPHER_EXPORT", "false"),
         ("SSL_CLIENT_VERIFY", "NONE"),
     ])
-    def test_14_proxy_ssl_vars_const(self, env, name: str, value: str):
+    def test_tls_14_proxy_ssl_vars_const(self, env, name: str, value: str):
         r = env.tls_get(env.domain_b, f"/proxy-ssl/vars.py?name={name}")
         assert r.exit_code == 0, r.stderr
         assert r.json == {name: value}, r.stdout
@@ -71,7 +71,7 @@ class TestProxySSL:
         ("SSL_VERSION_INTERFACE", r'mod_tls/\d+\.\d+\.\d+'),
         ("SSL_VERSION_LIBRARY", r'rustls-ffi/\d+\.\d+\.\d+/rustls/\d+\.\d+\.\d+'),
     ])
-    def test_14_proxy_ssl_vars_match(self, env, name: str, pattern: str):
+    def test_tls_14_proxy_ssl_vars_match(self, env, name: str, pattern: str):
         r = env.tls_get(env.domain_b, f"/proxy-ssl/vars.py?name={name}")
         assert r.exit_code == 0, r.stderr
         assert name in r.json
diff --git a/test/modules/tls/test_15_proxy_tls.py b/test/modules/tls/test_15_proxy_tls.py
index efc27017..f2f670d7 100644
--- a/test/modules/tls/test_15_proxy_tls.py
+++ b/test/modules/tls/test_15_proxy_tls.py
@@ -45,16 +45,16 @@ class TestProxyTLS:
         conf.install()
         assert env.apache_restart() == 0
 
-    def test_15_proxy_tls_get(self, env):
+    def test_tls_15_proxy_tls_get(self, env):
         data = env.tls_get_json(env.domain_b, "/proxy-tls/index.json")
         assert data == {'domain': env.domain_b}
 
-    def test_15_proxy_tls_get_local(self, env):
+    def test_tls_15_proxy_tls_get_local(self, env):
         # does not work, since SSLProxy* not configured
         data = env.tls_get_json(env.domain_b, "/proxy-local/index.json")
         assert data is None
 
-    def test_15_proxy_tls_h2_get(self, env):
+    def test_tls_15_proxy_tls_h2_get(self, env):
         r = env.tls_get(env.domain_b, "/proxy-h2-tls/index.json")
         assert r.exit_code == 0
         assert r.json == {'domain': env.domain_b}, f"{r.stdout}"
@@ -69,21 +69,18 @@ class TestProxyTLS:
         ("SSL_CIPHER_EXPORT", "false"),
         ("SSL_CLIENT_VERIFY", "NONE"),
     ])
-    def test_15_proxy_tls_h1_vars(self, env, name: str, value: str):
+    def test_tls_15_proxy_tls_h1_vars(self, env, name: str, value: str):
         r = env.tls_get(env.domain_b, f"/proxy-tls/vars.py?name={name}")
         assert r.exit_code == 0, r.stderr
         assert r.json == {name: value}, r.stdout
 
     @pytest.mark.parametrize("name, value", [
-        ("SERVER_NAME", "b.mod-tls.test"),
-        ("SERVER_NAME", "b.mod-tls.test"),
-        ("SERVER_NAME", "b.mod-tls.test"),
         ("SERVER_NAME", "b.mod-tls.test"),
         ("SSL_PROTOCOL", "TLSv1.3"),
         ("SSL_CIPHER", "TLS_CHACHA20_POLY1305_SHA256"),
         ("SSL_SESSION_RESUMED", "Initial"),
     ])
-    def test_15_proxy_tls_h2_vars(self, env, name: str, value: str):
+    def test_tls_15_proxy_tls_h2_vars(self, env, name: str, value: str):
         r = env.tls_get(env.domain_b, f"/proxy-h2-tls/vars.py?name={name}")
         assert r.exit_code == 0, r.stderr
         assert r.json == {name: value}, r.stdout
diff --git a/test/modules/tls/test_16_proxy_mixed.py b/test/modules/tls/test_16_proxy_mixed.py
index a37c530b..ca082362 100644
--- a/test/modules/tls/test_16_proxy_mixed.py
+++ b/test/modules/tls/test_16_proxy_mixed.py
@@ -1,3 +1,5 @@
+import time
+
 import pytest
 
 from .conf import TlsTestConf
@@ -9,7 +11,7 @@ class TestProxyMixed:
     def _class_scope(self, env):
         conf = TlsTestConf(env=env, extras={
             'base': [
-                "LogLevel proxy:trace1 proxy_http:trace1 ssl:trace1 proxy_http2:trace1",
+                "LogLevel proxy:trace1 proxy_http:trace1 ssl:trace1 proxy_http2:trace1 http2:debug",
                 "ProxyPreserveHost on",
             ],
             env.domain_a: [
@@ -34,10 +36,12 @@ class TestProxyMixed:
         conf.install()
         assert env.apache_restart() == 0
 
-    def test_16_proxy_mixed_ssl_get(self, env):
+    def test_tls_16_proxy_mixed_ssl_get(self, env, repeat):
         data = env.tls_get_json(env.domain_b, "/proxy-ssl/index.json")
         assert data == {'domain': env.domain_b}
 
-    def test_16_proxy_mixed_tls_get(self, env):
+    def test_tls_16_proxy_mixed_tls_get(self, env, repeat):
         data = env.tls_get_json(env.domain_a, "/proxy-tls/index.json")
+        if data is None:
+            time.sleep(300)
         assert data == {'domain': env.domain_a}
diff --git a/test/modules/tls/test_17_proxy_machine_cert.py b/test/modules/tls/test_17_proxy_machine_cert.py
index efaa15af..7b5ef44d 100644
--- a/test/modules/tls/test_17_proxy_machine_cert.py
+++ b/test/modules/tls/test_17_proxy_machine_cert.py
@@ -54,7 +54,7 @@ class TestProxyMachineCert:
         conf.install()
         assert env.apache_restart() == 0
 
-    def test_17_proxy_machine_cert_get_a(self, env):
+    def test_tls_17_proxy_machine_cert_get_a(self, env):
         data = env.tls_get_json(env.domain_a, "/proxy-tls/index.json")
         assert data == {'domain': env.domain_a}
 
@@ -63,7 +63,7 @@ class TestProxyMachineCert:
         ("SSL_CLIENT_VERIFY", "SUCCESS"),
         ("REMOTE_USER", "user1"),
     ])
-    def test_17_proxy_machine_cert_vars(self, env, name: str, value: str):
+    def test_tls_17_proxy_machine_cert_vars(self, env, name: str, value: str):
         r = env.tls_get(env.domain_a, f"/proxy-tls/vars.py?name={name}")
         assert r.exit_code == 0, r.stderr
         assert r.json == {name: value}, r.stdout
diff --git a/test/travis_before_linux.sh b/test/travis_before_linux.sh
index 7f4f9b53..bc4d6594 100755
--- a/test/travis_before_linux.sh
+++ b/test/travis_before_linux.sh
@@ -68,9 +68,9 @@ function install_apx() {
 
     local revision=`svn info --show-item last-changed-revision ${url}`
 
-    # Blow away the cached install root if the revision does not
-    # match.
-    test -f ${prefix}/.revision-is-${revision} || rm -rf ${prefix}
+    # Blow away the cached install root if the cached install is stale
+    # or doesn't match the expected configuration.
+    grep -q "${version} ${revision} ${config} CC=$CC" ${HOME}/root/.key-${name} || rm -rf ${prefix}
 
     if test -d ${prefix}; then
         return 0
@@ -84,13 +84,33 @@ function install_apx() {
          make install
     popd
 
-    touch ${prefix}/.revision-is-${revision}
+    echo ${version} ${revision} "${config}" "CC=${CC}" > ${HOME}/root/.key-${name}
 }
 
+# Allow to load $HOME/build/apache/httpd/.gdbinit
+echo "add-auto-load-safe-path $HOME/build/apache/httpd/.gdbinit" >> $HOME/.gdbinit
 
+# Prepare perl-framework test environment
 if ! test -v SKIP_TESTING; then
-    ### Temporary: purge old svn checkout from the cache
-    rm -rf $HOME/root/framework
+    # Clear CPAN cache if necessary
+    if [ -v CLEAR_CACHE ]; then rm -rf ~/perl5; fi
+    
+    cpanm --local-lib=~/perl5 local::lib && eval $(perl -I ~/perl5/lib/perl5/ -Mlocal::lib)
+
+    pkgs="Net::SSL LWP::Protocol::https                                 \
+           LWP::Protocol::AnyEvent::http ExtUtils::Embed Test::More     \
+           AnyEvent DateTime HTTP::DAV FCGI                             \
+           AnyEvent::WebSocket::Client Apache::Test"
+
+    # CPAN modules are to be used with the system Perl and always with
+    # CC=gcc, e.g. for the CC="gcc -m32" case the builds are not correct
+    # otherwise.
+    CC=gcc cpanm --notest $pkgs
+
+    # Set cache key.
+    echo $pkgs > ~/perl5/.key
+    unset pkgs
+
     # Make a shallow clone of httpd-tests git repo.
     git clone --depth=1 https://github.com/apache/httpd-tests.git test/perl-framework
 fi
diff --git a/test/travis_run_linux.sh b/test/travis_run_linux.sh
index fd13385e..58370700 100755
--- a/test/travis_run_linux.sh
+++ b/test/travis_run_linux.sh
@@ -39,6 +39,9 @@ if test ! -v SKIP_TESTING; then
         CONFIG="--with-test-suite=test/perl-framework $CONFIG"
         WITH_TEST_SUITE=1
     fi
+
+    # Use the CPAN environment.
+    eval $(perl -I ~/perl5/lib/perl5/ -Mlocal::lib)
 fi
 if test -v APR_VERSION; then
     CONFIG="$CONFIG --with-apr=$HOME/root/apr-${APR_VERSION}"
@@ -191,7 +194,6 @@ if ! test -v SKIP_TESTING; then
         # Run ACME tests.
         # need the go based pebble as ACME test server
         # which is a package on debian sid, but not on focal
-        export GOROOT=/usr/lib/go-1.14
         export GOPATH=${PREFIX}/gocode
         mkdir -p "${GOPATH}"
         export PATH="${GOROOT}/bin:${GOPATH}/bin:${PATH}"

--- End Message ---
--- Begin Message ---
Unblocked.

--- End Message ---

Reply to: