• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #define _BSD_SOURCE
2 #include <nl_types.h>
3 #include <string.h>
4 #include <stdint.h>
5 #include <endian.h>
6 #include <errno.h>
7 #include <langinfo.h>
8 #include <locale.h>
9 #include <sys/mman.h>
10 #include "libc.h"
11 
12 #define V(p) be32toh(*(uint32_t *)(p))
13 
do_catopen(const char * name)14 static nl_catd do_catopen(const char *name)
15 {
16 	size_t size;
17 	const unsigned char *map = __map_file(name, &size);
18 	/* Size recorded in the file must match file size; otherwise
19 	 * the information needed to unmap the file will be lost. */
20 	if (!map || V(map) != 0xff88ff89 || 20+V(map+8) != size) {
21 		if(map) munmap((void *)map, size);
22 		errno = ENOENT;
23 		return (nl_catd)-1;
24 	}
25 	return (nl_catd)map;
26 }
27 
catopen(const char * name,int oflag)28 nl_catd catopen(const char *name, int oflag)
29 {
30 	nl_catd catd;
31 
32 	if (strchr(name, '/')) return do_catopen(name);
33 
34 	char buf[PATH_MAX];
35 	size_t i;
36 	const char *path, *lang, *p, *z;
37 	if (libc.secure || !(path = getenv("NLSPATH"))) {
38 		errno = ENOENT;
39 		return (nl_catd)-1;
40 	}
41 	lang = oflag ? nl_langinfo(_NL_LOCALE_NAME(LC_MESSAGES)) : getenv("LANG");
42 	if (!lang) lang = "";
43 	for (p=path; *p; p=z) {
44 		i = 0;
45 		z = __strchrnul(p, ':');
46 		for (; p<z; p++) {
47 			const char *v;
48 			size_t l;
49 			if (*p!='%') v=p, l=1;
50 			else switch (*++p) {
51 			case 'N': v=name; l=strlen(v); break;
52 			case 'L': v=lang; l=strlen(v); break;
53 			case 'l': v=lang; l=strcspn(v,"_.@"); break;
54 			case 't':
55 				v=__strchrnul(lang,'_');
56 				if (*v) v++;
57 				l=strcspn(v,".@");
58 				break;
59 			case 'c': v="UTF-8"; l=5; break;
60 			case '%': v="%"; l=1; break;
61 			default: v=0;
62 			}
63 			if (!v || l >= sizeof buf - i) {
64 				break;
65 			}
66 			memcpy(buf+i, v, l);
67 			i += l;
68 		}
69 		if (!*z && (p<z || !i)) break;
70 		if (p<z) continue;
71 		if (*z) z++;
72 		buf[i] = 0;
73 		/* Leading : or :: in NLSPATH is same as %N */
74 		catd = do_catopen(i ? buf : name);
75 		if (catd != (nl_catd)-1) return catd;
76 	}
77 	errno = ENOENT;
78 	return (nl_catd)-1;
79 }
80