1 /***********************************************************
2 Copyright 1990, by Alfalfa Software Incorporated, Cambridge, Massachusetts.
6 Permission to use, copy, modify, and distribute this software and its
7 documentation for any purpose and without fee is hereby granted,
8 provided that the above copyright notice appear in all copies and that
9 both that copyright notice and this permission notice appear in
10 supporting documentation, and that Alfalfa's name not be used in
11 advertising or publicity pertaining to distribution of the software
12 without specific, written prior permission.
14 ALPHALPHA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16 ALPHALPHA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
22 If you make any modifications, bugfixes or other changes to this software
23 we'd appreciate it if you could send a copy to us so we can keep things
24 up-to-date. Many thanks.
26 Alfalfa Software, Inc.
28 Cambridge, MA 02139 USA
31 ******************************************************************/
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
38 #include "namespace.h"
39 #include <sys/types.h>
43 #include <arpa/inet.h> /* for ntohl() */
54 #include "un-namespace.h"
56 #include "../locale/setlocale.h" /* for ENCODING_LEN */
58 #define _DEFAULT_NLS_PATH "/usr/share/nls/%L/%N.cat:/usr/share/nls/%N/%L:/usr/local/share/nls/%L/%N.cat:/usr/local/share/nls/%N/%L"
60 #define NLERR ((nl_catd) -1)
61 #define NLRETERR(errc) { errno = errc; return (NLERR); }
63 static nl_catd load_msgcat(const char *);
66 catopen(const char *name, int type)
70 char *nlspath, *lang, *base, *cptr, *pathP, *tmpptr;
71 char *cptr1, *plang, *pter, *pcode;
74 if (name == NULL || *name == '\0')
77 /* is it absolute path ? if yes, load immediately */
78 if (strchr(name, '/') != NULL)
79 return (load_msgcat(name));
81 if (type == NL_CAT_LOCALE)
82 lang = setlocale(LC_MESSAGES, NULL);
84 lang = getenv("LANG");
86 if (lang == NULL || *lang == '\0' || strlen(lang) > ENCODING_LEN ||
88 (lang[1] == '\0' || (lang[1] == '.' && lang[2] == '\0'))) ||
89 strchr(lang, '/') != NULL)
92 if ((plang = cptr1 = strdup(lang)) == NULL)
94 if ((cptr = strchr(cptr1, '@')) != NULL)
97 if ((cptr = strchr(cptr1, '_')) != NULL) {
101 if ((cptr = strchr(cptr1, '.')) != NULL) {
106 if ((nlspath = getenv("NLSPATH")) == NULL || issetugid())
107 nlspath = _DEFAULT_NLS_PATH;
109 if ((base = cptr = strdup(nlspath)) == NULL) {
116 while ((nlspath = strsep(&cptr, ":")) != NULL) {
119 for (; *nlspath; ++nlspath) {
120 if (*nlspath == '%') {
121 switch (*(nlspath + 1)) {
135 tmpptr = (char *)name;
144 *(pathP++) = *nlspath;
149 spcleft = sizeof(path) -
151 if (strlcpy(pathP, tmpptr, spcleft) >=
156 NLRETERR(ENAMETOOLONG);
158 pathP += strlen(tmpptr);
160 if (pathP - path >= sizeof(path) - 1)
162 *(pathP++) = *nlspath;
166 if (stat(path, &sbuf) == 0) {
169 return (load_msgcat(path));
172 tmpptr = (char *)name;
183 catgets(nl_catd catd, int set_id, int msg_id, const char *s)
185 struct _nls_cat_hdr *cat_hdr;
186 struct _nls_set_hdr *set_hdr;
187 struct _nls_msg_hdr *msg_hdr;
190 if (catd == NULL || catd == NLERR) {
192 /* LINTED interface problem */
196 cat_hdr = (struct _nls_cat_hdr *)catd->__data;
197 set_hdr = (struct _nls_set_hdr *)(void *)((char *)catd->__data
198 + sizeof(struct _nls_cat_hdr));
200 /* binary search, see knuth algorithm b */
202 u = ntohl((u_int32_t)cat_hdr->__nsets) - 1;
205 r = set_id - ntohl((u_int32_t)set_hdr[i].__setno);
208 msg_hdr = (struct _nls_msg_hdr *)
209 (void *)((char *)catd->__data +
210 sizeof(struct _nls_cat_hdr) +
211 ntohl((u_int32_t)cat_hdr->__msg_hdr_offset));
213 l = ntohl((u_int32_t)set_hdr[i].__index);
214 u = l + ntohl((u_int32_t)set_hdr[i].__nmsgs) - 1;
218 ntohl((u_int32_t)msg_hdr[i].__msgno);
220 return ((char *) catd->__data +
221 sizeof(struct _nls_cat_hdr) +
223 cat_hdr->__msg_txt_offset) +
225 msg_hdr[i].__offset));
246 /* LINTED interface problem */
251 catclose(nl_catd catd)
253 if (catd == NULL || catd == NLERR) {
258 munmap(catd->__data, (size_t)catd->__size);
264 * Internal support functions
268 load_msgcat(const char *path)
275 /* XXX: path != NULL? */
277 if ((fd = _open(path, O_RDONLY)) == -1)
280 if (_fstat(fd, &st) != 0) {
285 data = mmap(0, (size_t)st.st_size, PROT_READ, MAP_FILE|MAP_SHARED, fd,
289 if (data == MAP_FAILED)
292 if (ntohl((u_int32_t)((struct _nls_cat_hdr *)data)->__magic) !=
294 munmap(data, (size_t)st.st_size);
298 if ((catd = malloc(sizeof (*catd))) == NULL) {
299 munmap(data, (size_t)st.st_size);
304 catd->__size = (int)st.st_size;