github.com/afumu/libc@v0.0.6/musl/src/locale/locale_map.c (about)

     1  #include <locale.h>
     2  #include <string.h>
     3  #include <sys/mman.h>
     4  #include "locale_impl.h"
     5  #include "libc.h"
     6  #include "lock.h"
     7  
     8  const char *__lctrans_impl(const char *msg, const struct __locale_map *lm)
     9  {
    10  	const char *trans = 0;
    11  	if (lm) trans = __mo_lookup(lm->map, lm->map_size, msg);
    12  	return trans ? trans : msg;
    13  }
    14  
    15  static const char envvars[][12] = {
    16  	"LC_CTYPE",
    17  	"LC_NUMERIC",
    18  	"LC_TIME",
    19  	"LC_COLLATE",
    20  	"LC_MONETARY",
    21  	"LC_MESSAGES",
    22  };
    23  
    24  const struct __locale_map *__get_locale(int cat, const char *val)
    25  {
    26  	static volatile int lock[1];
    27  	static void *volatile loc_head;
    28  	const struct __locale_map *p;
    29  	struct __locale_map *new = 0;
    30  	const char *path = 0, *z;
    31  	char buf[256];
    32  	size_t l, n;
    33  
    34  	if (!*val) {
    35  		(val = getenv("LC_ALL")) && *val ||
    36  		(val = getenv(envvars[cat])) && *val ||
    37  		(val = getenv("LANG")) && *val ||
    38  		(val = "C.UTF-8");
    39  	}
    40  
    41  	/* Limit name length and forbid leading dot or any slashes. */
    42  	for (n=0; n<LOCALE_NAME_MAX && val[n] && val[n]!='/'; n++);
    43  	if (val[0]=='.' || val[n]) val = "C.UTF-8";
    44  	int builtin = (val[0]=='C' && !val[1])
    45  		|| !strcmp(val, "C.UTF-8")
    46  		|| !strcmp(val, "POSIX");
    47  
    48  	if (builtin) {
    49  		if (cat == LC_CTYPE && val[1]=='.')
    50  			return (void *)&__c_dot_utf8;
    51  		return 0;
    52  	}
    53  
    54  	for (p=loc_head; p; p=p->next)
    55  		if (!strcmp(val, p->name)) return p;
    56  
    57  	LOCK(lock);
    58  
    59  	for (p=loc_head; p; p=p->next)
    60  		if (!strcmp(val, p->name)) {
    61  			UNLOCK(lock);
    62  			return p;
    63  		}
    64  
    65  	if (!libc.secure) path = getenv("MUSL_LOCPATH");
    66  	/* FIXME: add a default path? */
    67  
    68  	if (path) for (; *path; path=z+!!*z) {
    69  		z = __strchrnul(path, ':');
    70  		l = z - path - !!*z;
    71  		if (l >= sizeof buf - n - 2) continue;
    72  		memcpy(buf, path, l);
    73  		buf[l] = '/';
    74  		memcpy(buf+l+1, val, n);
    75  		buf[l+1+n] = 0;
    76  		size_t map_size;
    77  		const void *map = __map_file(buf, &map_size);
    78  		if (map) {
    79  			new = malloc(sizeof *new);
    80  			if (!new) {
    81  				__munmap((void *)map, map_size);
    82  				break;
    83  			}
    84  			new->map = map;
    85  			new->map_size = map_size;
    86  			memcpy(new->name, val, n);
    87  			new->name[n] = 0;
    88  			new->next = loc_head;
    89  			loc_head = new;
    90  			break;
    91  		}
    92  	}
    93  
    94  	/* If no locale definition was found, make a locale map
    95  	 * object anyway to store the name, which is kept for the
    96  	 * sake of being able to do message translations at the
    97  	 * application level. */
    98  	if (!new && (new = malloc(sizeof *new))) {
    99  		new->map = __c_dot_utf8.map;
   100  		new->map_size = __c_dot_utf8.map_size;
   101  		memcpy(new->name, val, n);
   102  		new->name[n] = 0;
   103  		new->next = loc_head;
   104  		loc_head = new;
   105  	}
   106  
   107  	/* For LC_CTYPE, never return a null pointer unless the
   108  	 * requested name was "C" or "POSIX". */
   109  	if (!new && cat == LC_CTYPE) new = (void *)&__c_dot_utf8;
   110  
   111  	UNLOCK(lock);
   112  	return new;
   113  }