3 ms·
And if you just don't want to be bothered by locales, it's not enough to setlocale(LC_ALL, "C"); Other libraries may call setlocale() behind your back (e.g. GT
by smcameron 3y ago
And if you just don't want to be bothered by locales, it's not enough to setlocale(LC_ALL, "C"); Other libraries may call setlocale() behind your back (e.g. GTK2). So, what you have to do is, you have to break setlocale's arms off:
#define _GNU_SOURCE
#include <stdio.h>
#include <dlfcn.h>
#include <locale.h>
typedef char *(*setlocale_prototype)(int category, const char *locale);
static setlocale_prototype real_setlocale = NULL;
static char *the_only_locale = "C";
char *setlocale(__attribute__((unused)) int category,
__attribute__((unused)) const char *locale)
{
char *msg;
if (!real_setlocale) {
*(void **) &real_setlocale = dlsym(RTLD_NEXT, "setlocale");
msg = dlerror();
if (msg) {
fprintf(stderr, "Failed to override setlocale(): %s\n", msg);
fflush(stderr);
real_setlocale = NULL;
return the_only_locale;
}
}
/* C is the locale, and the locale shall be C */
return real_setlocale(LC_ALL, "C");
}
Now it doesn't matter if GTK or whatever library calls setlocale() with whatever weird parameters, the locale shall be "C".
- 0xr0kk3r 3y agoAnother library can call setlocale and it will impact my code? I've never, ever written locale-specific code, so this is kinda surprise.
- teddyh 3y agoLocale is process-wide, so yes. But they shouldn’t; libraries should not call setlocale(). If it does, you should probably report it as a bug. It’s like if a library called chdir(); there are some things which libraries should not do, and setlocale() is one of them.
- JohnFen 3y agoI would be a bit more nuanced than that. I think it's OK if libraries change process state as long as they restore it as it was before the library call returns. And as long as this behavior is clearly documented.
- teddyh 3y agoMany state changes are not as reversible as one might think. Even chdir() can be non-reversible if the mountpoint has since changed. And if the locale has not been set, and then a library sets it, AFAIK you can’t “unset” it, only set it to something else.