Consider the following minimalistic code fragment:
#include <stdio.h>
#include <errno.h>
#include <locale.h>
int main() {
const char *locale = setlocale(LC_ALL, "");
if (errno == ENOENT) {
printf("Locale %s unavailable.\n", locale ? locale : "<unknown>");
} else if (errno) {
printf("setlocale() failed: errno = %d\n", errno);
perror("setlocale() failed");
}
if (locale) {
printf("Current locale: %s\n", locale);
}
return errno;
}
This runs successfully on a number of UNIX boxes (Solaris 8, Debian Linux 8, OpenBSD 5.8). There's a few exceptions, however.
According to the manual page, setlocale
returns NULL
if locale specified by the process environment (LC_ALL
et al.) is unavailable (i. e. the corresponding files are missing and need to be generated with localegen
or a similar tool). Testing reveals that errno
is set to ENOENT
in this case, but on one of Debian 7 boxes setlocale
returns a valid non-NULL
locale string and sets errno
to ENOENT
.
The other strange behaviour is exhibited by Cygwin: for each of the single-byte Cyrillic locales (ru_RU.CP1251
, ru_RU.CP866
, ru_RU.KOI8-R
, ru_RU.ISO-8859-5
), setlocale
returns a correct locale string and sets errno
to EILSEQ
. At the same time, ru_RU.UTF-8
is not affected.
How can any of the above cases be further diagnosed?
POSIX does not specify how setlocale
affects errno
(see section ERRORS where it says “no errors are specified”). You can safely disregard the value of errno
after a setlocale
call.
An implementation of setlocale
should never touch errno
, but it seems like some of the implementations you tested are buggy in this regard. I recommend you to file a bug report against the projects that supplied the faulty setlocale
implementation.