summaryrefslogtreecommitdiffstats
path: root/lib/libc/nls/msgcat.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc/nls/msgcat.c')
-rw-r--r--lib/libc/nls/msgcat.c447
1 files changed, 0 insertions, 447 deletions
diff --git a/lib/libc/nls/msgcat.c b/lib/libc/nls/msgcat.c
deleted file mode 100644
index 4532e90..0000000
--- a/lib/libc/nls/msgcat.c
+++ /dev/null
@@ -1,447 +0,0 @@
-/***********************************************************
-Copyright 1990, by Alfalfa Software Incorporated, Cambridge, Massachusetts.
-Copyright 2010, Gabor Kovesdan <gabor@FreeBSD.org>
-
- All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that Alfalfa's name not be used in
-advertising or publicity pertaining to distribution of the software
-without specific, written prior permission.
-
-ALPHALPHA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-ALPHALPHA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-If you make any modifications, bugfixes or other changes to this software
-we'd appreciate it if you could send a copy to us so we can keep things
-up-to-date. Many thanks.
- Kee Hinckley
- Alfalfa Software, Inc.
- 267 Allston St., #3
- Cambridge, MA 02139 USA
- nazgul@alfalfa.com
-
-******************************************************************/
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#define _NLS_PRIVATE
-
-#include "namespace.h"
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include <sys/queue.h>
-
-#include <arpa/inet.h> /* for ntohl() */
-
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <locale.h>
-#include <nl_types.h>
-#include <pthread.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include "un-namespace.h"
-
-#include "../locale/setlocale.h" /* for ENCODING_LEN */
-
-#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"
-
-#define RLOCK(fail) { int ret; \
- if (__isthreaded && \
- ((ret = _pthread_rwlock_rdlock(&rwlock)) != 0)) { \
- errno = ret; \
- return (fail); \
- }}
-#define WLOCK(fail) { int ret; \
- if (__isthreaded && \
- ((ret = _pthread_rwlock_wrlock(&rwlock)) != 0)) { \
- errno = ret; \
- return (fail); \
- }}
-#define UNLOCK { if (__isthreaded) \
- _pthread_rwlock_unlock(&rwlock); }
-
-#define NLERR ((nl_catd) -1)
-#define NLRETERR(errc) { errno = errc; return (NLERR); }
-#define SAVEFAIL(n, l, e) { WLOCK(NLERR); \
- np = malloc(sizeof(struct catentry)); \
- if (np != NULL) { \
- np->name = strdup(n); \
- np->path = NULL; \
- np->lang = (l == NULL) ? NULL : \
- strdup(l); \
- np->caterrno = e; \
- SLIST_INSERT_HEAD(&cache, np, list); \
- } \
- UNLOCK; \
- errno = e; \
- }
-
-static nl_catd load_msgcat(const char *, const char *, const char *);
-
-static pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
-
-struct catentry {
- SLIST_ENTRY(catentry) list;
- char *name;
- char *path;
- int caterrno;
- nl_catd catd;
- char *lang;
- int refcount;
-};
-
-SLIST_HEAD(listhead, catentry) cache =
- SLIST_HEAD_INITIALIZER(cache);
-
-nl_catd
-catopen(const char *name, int type)
-{
- struct stat sbuf;
- struct catentry *np;
- char *base, *cptr, *cptr1, *lang, *nlspath, *pathP, *pcode;
- char *plang, *pter, *tmpptr;
- int saverr, spcleft;
- char path[PATH_MAX];
-
- /* sanity checking */
- if (name == NULL || *name == '\0')
- NLRETERR(EINVAL);
-
- if (strchr(name, '/') != NULL)
- /* have a pathname */
- lang = NULL;
- else {
- if (type == NL_CAT_LOCALE)
- lang = setlocale(LC_MESSAGES, NULL);
- else
- lang = getenv("LANG");
-
- if (lang == NULL || *lang == '\0' || strlen(lang) > ENCODING_LEN ||
- (lang[0] == '.' &&
- (lang[1] == '\0' || (lang[1] == '.' && lang[2] == '\0'))) ||
- strchr(lang, '/') != NULL)
- lang = "C";
- }
-
- /* Try to get it from the cache first */
- RLOCK(NLERR);
- SLIST_FOREACH(np, &cache, list) {
- if ((strcmp(np->name, name) == 0) &&
- ((lang != NULL && np->lang != NULL &&
- strcmp(np->lang, lang) == 0) || (np->lang == lang))) {
- if (np->caterrno != 0) {
- /* Found cached failing entry */
- UNLOCK;
- NLRETERR(np->caterrno);
- } else {
- /* Found cached successful entry */
- np->refcount++;
- UNLOCK;
- return (np->catd);
- }
- }
- }
- UNLOCK;
-
- /* is it absolute path ? if yes, load immediately */
- if (strchr(name, '/') != NULL)
- return (load_msgcat(name, name, lang));
-
- /* sanity checking */
- if ((plang = cptr1 = strdup(lang)) == NULL)
- return (NLERR);
- if ((cptr = strchr(cptr1, '@')) != NULL)
- *cptr = '\0';
- pter = pcode = "";
- if ((cptr = strchr(cptr1, '_')) != NULL) {
- *cptr++ = '\0';
- pter = cptr1 = cptr;
- }
- if ((cptr = strchr(cptr1, '.')) != NULL) {
- *cptr++ = '\0';
- pcode = cptr;
- }
-
- if ((nlspath = getenv("NLSPATH")) == NULL || issetugid())
- nlspath = _DEFAULT_NLS_PATH;
-
- if ((base = cptr = strdup(nlspath)) == NULL) {
- saverr = errno;
- free(plang);
- errno = saverr;
- return (NLERR);
- }
-
- while ((nlspath = strsep(&cptr, ":")) != NULL) {
- pathP = path;
- if (*nlspath) {
- for (; *nlspath; ++nlspath) {
- if (*nlspath == '%') {
- switch (*(nlspath + 1)) {
- case 'l':
- tmpptr = plang;
- break;
- case 't':
- tmpptr = pter;
- break;
- case 'c':
- tmpptr = pcode;
- break;
- case 'L':
- tmpptr = lang;
- break;
- case 'N':
- tmpptr = (char *)name;
- break;
- case '%':
- ++nlspath;
- /* FALLTHROUGH */
- default:
- if (pathP - path >=
- sizeof(path) - 1)
- goto too_long;
- *(pathP++) = *nlspath;
- continue;
- }
- ++nlspath;
- put_tmpptr:
- spcleft = sizeof(path) -
- (pathP - path) - 1;
- if (strlcpy(pathP, tmpptr, spcleft) >=
- spcleft) {
- too_long:
- free(plang);
- free(base);
- SAVEFAIL(name, lang, ENAMETOOLONG);
- NLRETERR(ENAMETOOLONG);
- }
- pathP += strlen(tmpptr);
- } else {
- if (pathP - path >= sizeof(path) - 1)
- goto too_long;
- *(pathP++) = *nlspath;
- }
- }
- *pathP = '\0';
- if (stat(path, &sbuf) == 0) {
- free(plang);
- free(base);
- return (load_msgcat(path, name, lang));
- }
- } else {
- tmpptr = (char *)name;
- --nlspath;
- goto put_tmpptr;
- }
- }
- free(plang);
- free(base);
- SAVEFAIL(name, lang, ENOENT);
- NLRETERR(ENOENT);
-}
-
-char *
-catgets(nl_catd catd, int set_id, int msg_id, const char *s)
-{
- struct _nls_cat_hdr *cat_hdr;
- struct _nls_msg_hdr *msg_hdr;
- struct _nls_set_hdr *set_hdr;
- int i, l, r, u;
-
- if (catd == NULL || catd == NLERR) {
- errno = EBADF;
- /* LINTED interface problem */
- return ((char *)s);
- }
-
- cat_hdr = (struct _nls_cat_hdr *)catd->__data;
- set_hdr = (struct _nls_set_hdr *)(void *)((char *)catd->__data +
- sizeof(struct _nls_cat_hdr));
-
- /* binary search, see knuth algorithm b */
- l = 0;
- u = ntohl((u_int32_t)cat_hdr->__nsets) - 1;
- while (l <= u) {
- i = (l + u) / 2;
- r = set_id - ntohl((u_int32_t)set_hdr[i].__setno);
-
- if (r == 0) {
- msg_hdr = (struct _nls_msg_hdr *)
- (void *)((char *)catd->__data +
- sizeof(struct _nls_cat_hdr) +
- ntohl((u_int32_t)cat_hdr->__msg_hdr_offset));
-
- l = ntohl((u_int32_t)set_hdr[i].__index);
- u = l + ntohl((u_int32_t)set_hdr[i].__nmsgs) - 1;
- while (l <= u) {
- i = (l + u) / 2;
- r = msg_id -
- ntohl((u_int32_t)msg_hdr[i].__msgno);
- if (r == 0) {
- return ((char *) catd->__data +
- sizeof(struct _nls_cat_hdr) +
- ntohl((u_int32_t)
- cat_hdr->__msg_txt_offset) +
- ntohl((u_int32_t)
- msg_hdr[i].__offset));
- } else if (r < 0) {
- u = i - 1;
- } else {
- l = i + 1;
- }
- }
-
- /* not found */
- goto notfound;
-
- } else if (r < 0) {
- u = i - 1;
- } else {
- l = i + 1;
- }
- }
-
-notfound:
- /* not found */
- errno = ENOMSG;
- /* LINTED interface problem */
- return ((char *)s);
-}
-
-int
-catclose(nl_catd catd)
-{
- struct catentry *np;
-
- /* sanity checking */
- if (catd == NULL || catd == NLERR) {
- errno = EBADF;
- return (-1);
- }
-
- /* Remove from cache if not referenced any more */
- WLOCK(-1);
- SLIST_FOREACH(np, &cache, list) {
- if (catd == np->catd) {
- np->refcount--;
- if (np->refcount == 0) {
- munmap(catd->__data, (size_t)catd->__size);
- free(catd);
- SLIST_REMOVE(&cache, np, catentry, list);
- free(np->name);
- free(np->path);
- free(np->lang);
- free(np);
- }
- break;
- }
- }
- UNLOCK;
- return (0);
-}
-
-/*
- * Internal support functions
- */
-
-static nl_catd
-load_msgcat(const char *path, const char *name, const char *lang)
-{
- struct stat st;
- nl_catd catd;
- struct catentry *np;
- void *data;
- int fd;
-
- /* path/name will never be NULL here */
-
- /*
- * One more try in cache; if it was not found by name,
- * it might still be found by absolute path.
- */
- RLOCK(NLERR);
- SLIST_FOREACH(np, &cache, list) {
- if ((np->path != NULL) && (strcmp(np->path, path) == 0)) {
- np->refcount++;
- UNLOCK;
- return (np->catd);
- }
- }
- UNLOCK;
-
- if ((fd = _open(path, O_RDONLY)) == -1) {
- SAVEFAIL(name, lang, errno);
- NLRETERR(errno);
- }
-
- if (_fstat(fd, &st) != 0) {
- _close(fd);
- SAVEFAIL(name, lang, EFTYPE);
- NLRETERR(EFTYPE);
- }
-
- /*
- * If the file size cannot be held in size_t we cannot mmap()
- * it to the memory. Probably, this will not be a problem given
- * that catalog files are usually small.
- */
- if (st.st_size > SIZE_T_MAX) {
- _close(fd);
- SAVEFAIL(name, lang, EFBIG);
- NLRETERR(EFBIG);
- }
-
- if ((data = mmap(0, (size_t)st.st_size, PROT_READ,
- MAP_FILE|MAP_SHARED, fd, (off_t)0)) == MAP_FAILED) {
- int saved_errno = errno;
- _close(fd);
- SAVEFAIL(name, lang, saved_errno);
- NLRETERR(saved_errno);
- }
- _close(fd);
-
- if (ntohl((u_int32_t)((struct _nls_cat_hdr *)data)->__magic) !=
- _NLS_MAGIC) {
- munmap(data, (size_t)st.st_size);
- SAVEFAIL(name, lang, EFTYPE);
- NLRETERR(EFTYPE);
- }
-
- if ((catd = malloc(sizeof (*catd))) == NULL) {
- munmap(data, (size_t)st.st_size);
- SAVEFAIL(name, lang, ENOMEM);
- NLRETERR(ENOMEM);
- }
-
- catd->__data = data;
- catd->__size = (int)st.st_size;
-
- /* Caching opened catalog */
- WLOCK(NLERR);
- if ((np = malloc(sizeof(struct catentry))) != NULL) {
- np->name = strdup(name);
- np->path = strdup(path);
- np->catd = catd;
- np->lang = (lang == NULL) ? NULL : strdup(lang);
- np->refcount = 1;
- np->caterrno = 0;
- SLIST_INSERT_HEAD(&cache, np, list);
- }
- UNLOCK;
- return (catd);
-}
OpenPOWER on IntegriCloud