Hash :
7411d053
Author :
Thomas de Grivel
Date :
2023-01-21T15:08:37
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
/*
* Nasty preload hack to allow message catalogs to be read from the "po"
* subdir of the build tree.
*
* export LD_PRELOAD="hacklocaledir.so preloadable_libintl.so"
* export TEXTDOMAIN=program
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <dlfcn.h>
#define PRELOAD "hacklocaledir.so"
static void *xmalloc(size_t len)
{
void *r = malloc(len);
if (!r)
{
fprintf(stderr, PRELOAD ": can't malloc %d bytes (%s)\n", len,
strerror(errno));
exit(1);
}
return r;
}
int __open(char const *path, int flags, mode_t mode)
{
static int (*open)(char const *, int, mode_t) = 0;
static char const *textdomain = 0;
static char const *localedir = 0;
static size_t localedirlen;
static char *match = 0;
static size_t matchlen;
char *newpath = 0;
int r;
if (!open && !(open = dlsym(RTLD_NEXT, "open")))
{
fprintf(stderr, PRELOAD ": can't find open(): %s\n", dlerror());
return -1;
}
if (textdomain || (textdomain = getenv("TEXTDOMAIN")))
{
size_t pathlen = strlen(path);
char const *check;
if (!localedir)
{
if (!(localedir = getenv("LOCALEDIR")))
localedir = "po";
localedirlen = strlen(localedir);
}
if (!match)
{
matchlen = sizeof("/LC_MESSAGES/")-1 + strlen(textdomain)
+ sizeof(".mo")-1;
match = xmalloc(matchlen + 1);
strcpy(match, "/LC_MESSAGES/");
strcat(match, textdomain);
strcat(match, ".mo");
}
if (*path == '/' && pathlen > matchlen &&
!strcmp(check = (path + pathlen - matchlen), match))
{
char const *p = path;
char const *locale = 0;
do {
locale = p + 1;
p = strchr(locale, '/');
} while (p && p < check);
if (locale)
{
size_t len = strcspn(locale, "/");
newpath = xmalloc(localedirlen + 1 + len + sizeof(".gmo"));
strcpy(newpath, localedir);
strcat(newpath, "/");
strncat(newpath, locale, len);
strcat(newpath, ".gmo");
if (access(newpath, R_OK))
{
free(newpath);
newpath = 0;
}
}
}
}
r = (*open)(newpath ? newpath : path, flags, mode);
if (newpath)
{
fprintf(stderr, "note: mapped %s to %s\n", path, newpath);
free(newpath);
}
return r;
}
int open(char const *path, int flags, mode_t mode)
__attribute__((weak, alias("__open")));