#include <stdio.h>
#include <locale.h>
#include <ctype.h>
#include <stdlib.h>
#include <strings.h>
#include <errno.h>
/*
* See »locale -a«, setlocale(3), environ(5)
*
* <URL:http://www.in-ulm.de/~mascheck/locale/>
*
* "gcc -o checklocale checklocale.c ; ./checklocale"
*/
/*
* - no arguments expected
* - debug all locale categories separately, particularly if
* LC_ALL or LANG are set
*/
/*
* setlocale(<locale>, "")
* sets that <locale> to the value from the environment variables
* LC_ALL, <locale> or LANG (with this priority).
*
* setlocale(<locale>, <value>)
* e.g. sets that <locale> to that <value>
*
* setlocale(LC_ALL, "")
* is special, it tries to set the locale categories which are given in
* the environment with the same priorities like above - it's a shortcut.
* LC_ALL in the /environment/ has also a special meaning,
* it's value overrides all other variables (caution).
*
* LANG (environment) is also special, it's not a locale but
* only a possible value. If neither LC_ALL nor the specific LC_*
* are set, the value of LANG is used for the various categories.
*
* If LC_MESSAGES succeeds, it means that libc supports that value.
* Success doesn't guarantee non-english messages, though.
* Other programs have to support this with their own messages.
*
* Use a syscall tracer ([k]truss, [k|s|]trace, par) if you're
* in doubt about your installation.
*/
/* Sun BSD */
#ifndef EXIT_SUCCESS
#define EXIT_SUCCESS 0
#endif
#ifndef EXIT_FAILURE
#define EXIT_FAILURE 1
#endif
char *locale_strings[6] = {
"LC_CTYPE",
"LC_NUMERIC",
"LC_TIME",
"LC_COLLATE",
"LC_MONETARY",
"LC_MESSAGES",
};
int locale_categories[6] = {
LC_CTYPE,
LC_NUMERIC,
LC_TIME,
LC_COLLATE,
LC_MONETARY,
LC_MESSAGES,
};
/*
* print out all eight bit characters
* substitute the unprintables with '#'
*/
void do_isprint_once()
{
int i, j, k;
static int once = 1;
if (once) {
once = 0;
printf("\n Testing LC_CTYPE with isprint():\n ");
k = 0;
for (i = 0; i < 16; i++) {
for (j = 0; j < 16; j++) {
if (isprint(k)) {
printf("%c ", k);
}
else {
printf("# ");
}
k++;
}
printf("\n ");
}
printf("\n");
}
}
/*
* Print a *possibly* localized libc error message.
* Application specific messages certainly cannot be tested here.
*/
void do_error_once()
{
static int once = 1;
if (once) {
once = 0;
printf("- Testing LC_MESSAGES with perror(), but it's a libc message.\n");
errno = EAGAIN;
perror(" Error message for \"EAGAIN\"");
printf("\n");
}
}
/*
* For handling locale environment variables
* the values (char*)NULL and "" make no difference.
*/
char *my_getenv (char *env)
{
char *value = getenv(env);
if (value) {
/* if (!strcmp(value, "(null)"))
printf("alarm for %s!\n", env); */
if (!strcmp(value, "")) {
value= (char*)NULL;
}
}
return(value);
}
int main()
{
int i; /* for the categories */
char *value; /* for the categories */
char *value_LC_ALL; /* special, needed several times */
char *value_LANG; /* special, needed several times */
char *setlocale_ret; /* returned by setlocale() */
/* When debugging, only use LANG if LC_ALL is unset */
char *implicit_debug_category;
int status = EXIT_SUCCESS;
printf("\n[Latin1/9] If there's no real copyrightsymbol at the end of this sentence,\n"
"then your terminal/terminalemulator/font is not ISO8859-1/15 ready: %c\n\n", '©');
printf("- Current environment settings:\n");
/*
* the "not existent" categories LC_ALL and LANG:
*/
value_LC_ALL = my_getenv("LC_ALL");
value_LANG = my_getenv("LANG");
if (value_LC_ALL)
printf(" LC_ALL = \"%s\"\n", value_LC_ALL);
if (value_LANG)
printf(" LANG = \"%s\"\n", value_LANG);
/*
* The "real" categories:
*/
for (i=0; i<6; i++) {
value = my_getenv(locale_strings[i]);
if (value)
printf(" %-11s = \"%s\"\n", locale_strings[i], value);
}
if (value_LC_ALL) {
printf("\n");
setlocale_ret = setlocale(LC_ALL, "");
if (setlocale_ret != (char*)NULL) {
printf("- Overriding all locale categories with LC_ALL succeeded\n");
printf(" (LC_ALL is only useful for debugging purposes).\n");
/* Thanks to Alain Bench: */
if (strcmp(setlocale_ret, value_LC_ALL)) {
printf(" Note: setlocale() returned \"%s\"\n", setlocale_ret);
printf(" This might be a (system dependent) composite value.\n");
}
/*
* LC_ALL succeeded.
* Most interesting: LC_CTYPE and LC_MESSAGES
*/
do_isprint_once();
do_error_once();
} else {
printf("- Overriding all locale categories with LC_ALL failed.\n");
printf(" You really should unset it now.\n");
printf(" Programs will usually fall back to \"C\" now.\n\n");
}
}
/*
* LANG is only of interest if LC_ALL is unset.
* But even more: only then it's usable for setlocale() in any way
* (for debugging purposes here).
*/
if (!value_LC_ALL && value_LANG) {
printf("\n");
setlocale_ret = setlocale(LC_ALL, "");
printf("setlocale_ret = %s", setlocale_ret);
if (setlocale_ret != (char*)NULL) {
printf("- Implicitly setting all locale categories with LANG succeeded.\n");
if (strcmp(setlocale_ret, value_LANG)) {
printf(" Note: setlocale() returned \"%s\"\n", setlocale_ret);
printf(" This might be a (system dependent) composite value.\n");
}
/*
* LANG succeeded.
* Most interesting: LC_CTYPE and LC_MESSAGES
*/
do_isprint_once();
do_error_once();
} else {
printf("- Implicitly setting all locale categories with LANG failed.\n");
printf(" You might want to unset/fix it now and/or set supported"
" categories instead.\n");
status = EXIT_FAILURE;
}
}
for (i=0; i<6; i++) {
value = my_getenv(locale_strings[i]);
if (value) {
setlocale_ret = setlocale(locale_categories[i], value);
if (setlocale_ret != (char*)NULL) {
printf("- Setting %s to \"%s\" succeeded.\n", locale_strings[i], value);
if (strcmp(setlocale_ret, value)) {
printf(" Note: setlocale() returned \"%s\".\n", setlocale_ret);
}
if (locale_categories[i] == LC_MESSAGES) {
do_error_once();
}
} else {
printf("- Setting %s to its own value failed.\n",
locale_strings[i]);
status = EXIT_FAILURE;
}
/*
* LC_CTYPE might always be of interest,
* even if setlocale() failed.
*/
if (locale_categories[i] == LC_CTYPE) {
do_isprint_once();
}
} else {
/*
* If LC_ALL is set, test this value individually.
* Otherwise, if LANG is set, test this value individually.
* Otherwise there's no way for an implicit setting, skip.
*/
if (value_LC_ALL)
implicit_debug_category = "LC_ALL";
else if (value_LANG)
implicit_debug_category = "LANG";
else
implicit_debug_category = (char*)NULL;
if (implicit_debug_category) {
setlocale_ret = setlocale(locale_categories[i], "");
if (setlocale_ret != (char*)NULL) {
printf("- Implicitly setting %12s by %s succeeded.\n",
locale_strings[i], implicit_debug_category);
if (strcmp(setlocale_ret, my_getenv(implicit_debug_category))) {
printf(" Note: setlocale() returned \"%s\".\n", setlocale_ret);
}
if (!strcmp(locale_strings[i], "LC_CTYPE")) {
do_isprint_once();
}
} else {
printf("- Implicitly setting %12s by %s failed.\n",
locale_strings[i], implicit_debug_category);
status = EXIT_FAILURE;
}
}
}
}
return (status);
}
return to top