Fix build on OPENSSL_SYS_TANDEM and older POSIXes

It also allows for passing -DOPENSSL_NO_LOCALE as a workaround
to ./Configure command.

Fixes #18233

Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/18282)
diff --git a/crypto/ctype.c b/crypto/ctype.c
index e60ccd2..f90ef19 100644
--- a/crypto/ctype.c
+++ b/crypto/ctype.c
@@ -14,16 +14,12 @@
 
 #include "internal/e_os.h"
 #include "internal/core.h"
-
-#ifndef OPENSSL_SYS_WINDOWS
-#include <strings.h>
+#ifndef OPENSSL_NO_LOCALE
+# include <locale.h>
+# ifdef OPENSSL_SYS_MACOSX
+#  include <xlocale.h>
+# endif
 #endif
-#include <locale.h>
-
-#ifdef OPENSSL_SYS_MACOSX
-#include <xlocale.h>
-#endif
-
 /*
  * Define the character classes for each character in the seven bit ASCII
  * character set.  This is independent of the host's character set, characters
@@ -291,24 +287,14 @@
     return 0;
 }
 
-/* str[n]casecmp_l is defined in POSIX 2008-01. Value is taken accordingly
- * https://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html */
-
-#if (defined OPENSSL_SYS_WINDOWS) || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200809L)
-
-# if defined OPENSSL_SYS_WINDOWS
-# define locale_t _locale_t
-# define freelocale _free_locale
-# define strcasecmp_l _stricmp_l
-# define strncasecmp_l _strnicmp_l
-# endif
+#ifndef OPENSSL_NO_LOCALE
+# ifndef FIPS_MODULE
 static locale_t loc;
 
-# ifndef FIPS_MODULE
+
 void *ossl_c_locale() {
     return (void *)loc;
 }
-# endif
 
 int ossl_init_casecmp_int() {
 # ifdef OPENSSL_SYS_WINDOWS
@@ -322,6 +308,7 @@
 void ossl_deinit_casecmp() {
     freelocale(loc);
 }
+# endif
 
 int OPENSSL_strcasecmp(const char *s1, const char *s2)
 {
diff --git a/include/internal/e_os.h b/include/internal/e_os.h
index 514de96..fd45d20 100644
--- a/include/internal/e_os.h
+++ b/include/internal/e_os.h
@@ -409,4 +409,23 @@
 #   endif
 # endif
 
+/*
+ * str[n]casecmp_l is defined in POSIX 2008-01. Value is taken accordingly
+ * https://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html
+ * There are also equivalent functions on Windows.
+ * There is no locale_t on NONSTOP.
+ */
+# if defined(OPENSSL_SYS_WINDOWS)
+#  define locale_t _locale_t
+#  define freelocale _free_locale
+#  define strcasecmp_l _stricmp_l
+#  define strncasecmp_l _strnicmp_l
+#  define strcasecmp _stricmp
+# elif !defined(_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 200809L \
+     || defined(OPENSSL_SYS_TANDEM)
+#  ifndef OPENSSL_NO_LOCALE
+#   define OPENSSL_NO_LOCALE
+#  endif
+# endif
+
 #endif
diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c
index 1b79c00..5436c48 100644
--- a/providers/fips/fipsprov.c
+++ b/providers/fips/fipsprov.c
@@ -24,6 +24,7 @@
 #include "self_test.h"
 #include "crypto/context.h"
 #include "internal/core.h"
+#include "internal/e_os.h"
 
 static const char FIPS_DEFAULT_PROPERTIES[] = "provider=fips,fips=yes";
 static const char FIPS_UNAPPROVED_PROPERTIES[] = "provider=fips,fips=no";
@@ -38,17 +39,13 @@
 static OSSL_FUNC_provider_query_operation_fn fips_query;
 
 /* Locale object accessor functions */
-#ifdef OPENSSL_SYS_MACOSX
-# include <xlocale.h>
-#else
+#ifndef OPENSSL_NO_LOCALE
 # include <locale.h>
-#endif
-
-#if defined OPENSSL_SYS_WINDOWS
-# define locale_t _locale_t
-# define freelocale _free_locale
-#endif
+# ifdef OPENSSL_SYS_MACOSX
+#  include <xlocale.h>
+# endif
 static locale_t loc;
+#endif
 
 static int fips_init_casecmp(void);
 static void fips_deinit_casecmp(void);
@@ -495,22 +492,35 @@
     return NULL;
 }
 
+# ifndef OPENSSL_NO_LOCALE
 void *ossl_c_locale() {
     return (void *)loc;
 }
 
 static int fips_init_casecmp(void) {
-# ifdef OPENSSL_SYS_WINDOWS
+#  ifdef OPENSSL_SYS_WINDOWS
     loc = _create_locale(LC_COLLATE, "C");
-# else
+#  else
     loc = newlocale(LC_COLLATE_MASK, "C", (locale_t) 0);
-# endif
+#  endif
     return (loc == (locale_t) 0) ? 0 : 1;
 }
 
 static void fips_deinit_casecmp(void) {
     freelocale(loc);
 }
+# else
+void *ossl_c_locale() {
+    return NULL;
+}
+
+static int fips_init_casecmp(void) {
+    return 1;
+}
+
+static void fips_deinit_casecmp(void) {
+}
+# endif
 
 static void fips_teardown(void *provctx)
 {
diff --git a/test/localetest.c b/test/localetest.c
index 270236a..9f13d38 100644
--- a/test/localetest.c
+++ b/test/localetest.c
@@ -1,3 +1,11 @@
+/*
+ * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
 
 #include <stdio.h>
 #include <string.h>
@@ -6,12 +14,12 @@
 #include "testutil/output.h"
 
 #include <stdlib.h>
-#include <locale.h>
-#ifdef OPENSSL_SYS_WINDOWS
-# define strcasecmp _stricmp
-#else
-# include <strings.h>
-#endif
+#include "internal/e_os.h"
+#ifndef OPENSSL_NO_LOCALE
+# include <locale.h>
+# ifdef OPENSSL_SYS_MACOSX
+#  include <xlocale.h>
+# endif
 
 int setup_tests(void)
 {
@@ -117,7 +125,12 @@
     X509_free(cert);
     return 1;
 }
-
+#else
+int setup_tests(void)
+{
+    return TEST_skip("Locale support not available");
+}
+#endif /* OPENSSL_NO_LOCALE */
 void cleanup_tests(void)
 {
 }