1 1.33 christos /* $NetBSD: catopen.c,v 1.33 2014/09/16 01:30:28 christos Exp $ */ 2 1.4 cgd 3 1.6 jtc /*- 4 1.6 jtc * Copyright (c) 1996 The NetBSD Foundation, Inc. 5 1.6 jtc * All rights reserved. 6 1.6 jtc * 7 1.6 jtc * This code is derived from software contributed to The NetBSD Foundation 8 1.6 jtc * by J.T. Conklin. 9 1.6 jtc * 10 1.6 jtc * Redistribution and use in source and binary forms, with or without 11 1.6 jtc * modification, are permitted provided that the following conditions 12 1.6 jtc * are met: 13 1.6 jtc * 1. Redistributions of source code must retain the above copyright 14 1.6 jtc * notice, this list of conditions and the following disclaimer. 15 1.6 jtc * 2. Redistributions in binary form must reproduce the above copyright 16 1.6 jtc * notice, this list of conditions and the following disclaimer in the 17 1.6 jtc * documentation and/or other materials provided with the distribution. 18 1.6 jtc * 19 1.6 jtc * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.6 jtc * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.6 jtc * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.12 jtc * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.12 jtc * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.6 jtc * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.6 jtc * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.6 jtc * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.6 jtc * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.6 jtc * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.6 jtc * POSSIBILITY OF SUCH DAMAGE. 30 1.1 jtc */ 31 1.1 jtc 32 1.22 lukem #include <sys/cdefs.h> 33 1.33 christos __RCSID("$NetBSD: catopen.c,v 1.33 2014/09/16 01:30:28 christos Exp $"); 34 1.22 lukem 35 1.6 jtc #define _NLS_PRIVATE 36 1.32 joerg #define __SETLOCALE_SOURCE__ 37 1.1 jtc 38 1.11 christos #include "namespace.h" 39 1.6 jtc #include <sys/param.h> 40 1.6 jtc #include <sys/stat.h> 41 1.6 jtc #include <sys/mman.h> 42 1.16 lukem 43 1.16 lukem #include <assert.h> 44 1.6 jtc #include <fcntl.h> 45 1.16 lukem #include <limits.h> 46 1.19 yamt #include <locale.h> 47 1.1 jtc #include <nl_types.h> 48 1.16 lukem #include <stdlib.h> 49 1.16 lukem #include <string.h> 50 1.16 lukem #include <unistd.h> 51 1.1 jtc 52 1.26 tnozaki #include "citrus_namespace.h" 53 1.26 tnozaki #include "citrus_bcs.h" 54 1.26 tnozaki #include "citrus_region.h" 55 1.26 tnozaki #include "citrus_lookup.h" 56 1.26 tnozaki #include "citrus_aliasname_local.h" 57 1.32 joerg #include "setlocale_local.h" 58 1.20 tshiozak 59 1.19 yamt #define NLS_ALIAS_DB "/usr/share/nls/nls.alias" 60 1.19 yamt 61 1.6 jtc #define NLS_DEFAULT_PATH "/usr/share/nls/%L/%N.cat:/usr/share/nls/%N/%L" 62 1.6 jtc #define NLS_DEFAULT_LANG "C" 63 1.15 mycroft 64 1.15 mycroft __weak_alias(catopen, _catopen) 65 1.32 joerg __weak_alias(catopen_l, _catopen_l) 66 1.1 jtc 67 1.30 matt static nl_catd load_msgcat(const char *); 68 1.7 jtc 69 1.1 jtc nl_catd 70 1.32 joerg catopen(const char *name, int oflag) 71 1.32 joerg { 72 1.32 joerg 73 1.32 joerg return catopen_l(name, oflag, _current_locale()); 74 1.32 joerg } 75 1.32 joerg 76 1.32 joerg nl_catd 77 1.32 joerg catopen_l(const char *name, int oflag, locale_t loc) 78 1.1 jtc { 79 1.18 sommerfe char tmppath[PATH_MAX+1]; 80 1.23 christos const char *nlspath; 81 1.26 tnozaki const char *lang, *reallang; 82 1.23 christos char *t; 83 1.23 christos const char *s, *u; 84 1.6 jtc nl_catd catd; 85 1.19 yamt char langbuf[PATH_MAX]; 86 1.20 tshiozak 87 1.6 jtc if (name == NULL || *name == '\0') 88 1.10 mrg return (nl_catd)-1; 89 1.6 jtc 90 1.6 jtc /* absolute or relative path? */ 91 1.10 mrg if (strchr(name, '/')) 92 1.7 jtc return load_msgcat(name); 93 1.7 jtc 94 1.17 tshiozak if (issetugid() || (nlspath = getenv("NLSPATH")) == NULL) 95 1.7 jtc nlspath = NLS_DEFAULT_PATH; 96 1.31 yamt /* 97 1.32 joerg * Historical note: 98 1.31 yamt * http://www.hauN.org/ml/b-l-j/a/800/828.html (in japanese) 99 1.31 yamt */ 100 1.19 yamt if (oflag == NL_CAT_LOCALE) { 101 1.32 joerg lang = loc->part_name[LC_MESSAGES]; 102 1.31 yamt } else { 103 1.19 yamt lang = getenv("LANG"); 104 1.19 yamt } 105 1.19 yamt if (lang == NULL || strchr(lang, '/')) 106 1.7 jtc lang = NLS_DEFAULT_LANG; 107 1.19 yamt 108 1.26 tnozaki reallang = __unaliasname(NLS_ALIAS_DB, lang, langbuf, sizeof(langbuf)); 109 1.26 tnozaki if (reallang == NULL) 110 1.26 tnozaki reallang = lang; 111 1.6 jtc 112 1.7 jtc s = nlspath; 113 1.20 tshiozak t = tmppath; 114 1.7 jtc do { 115 1.7 jtc while (*s && *s != ':') { 116 1.6 jtc if (*s == '%') { 117 1.8 jtc switch (*(++s)) { 118 1.7 jtc case 'L': /* locale */ 119 1.26 tnozaki u = reallang; 120 1.8 jtc while (*u && t < tmppath + PATH_MAX) 121 1.8 jtc *t++ = *u++; 122 1.7 jtc break; 123 1.7 jtc case 'N': /* name */ 124 1.8 jtc u = name; 125 1.8 jtc while (*u && t < tmppath + PATH_MAX) 126 1.8 jtc *t++ = *u++; 127 1.7 jtc break; 128 1.7 jtc case 'l': /* lang */ 129 1.7 jtc case 't': /* territory */ 130 1.7 jtc case 'c': /* codeset */ 131 1.7 jtc break; 132 1.7 jtc default: 133 1.8 jtc if (t < tmppath + PATH_MAX) 134 1.9 jtc *t++ = *s; 135 1.6 jtc } 136 1.6 jtc } else { 137 1.8 jtc if (t < tmppath + PATH_MAX) 138 1.9 jtc *t++ = *s; 139 1.6 jtc } 140 1.9 jtc s++; 141 1.6 jtc } 142 1.6 jtc 143 1.7 jtc *t = '\0'; 144 1.7 jtc catd = load_msgcat(tmppath); 145 1.10 mrg if (catd != (nl_catd)-1) 146 1.7 jtc return catd; 147 1.7 jtc 148 1.9 jtc if (*s) 149 1.9 jtc s++; 150 1.7 jtc t = tmppath; 151 1.7 jtc } while (*s); 152 1.7 jtc 153 1.10 mrg return (nl_catd)-1; 154 1.7 jtc } 155 1.7 jtc 156 1.7 jtc static nl_catd 157 1.30 matt load_msgcat(const char *path) 158 1.7 jtc { 159 1.7 jtc struct stat st; 160 1.7 jtc nl_catd catd; 161 1.9 jtc void *data; 162 1.7 jtc int fd; 163 1.16 lukem 164 1.16 lukem _DIAGASSERT(path != NULL); 165 1.6 jtc 166 1.33 christos if ((fd = open(path, O_RDONLY|O_CLOEXEC)) == -1) 167 1.10 mrg return (nl_catd)-1; 168 1.6 jtc 169 1.6 jtc if (fstat(fd, &st) != 0) { 170 1.6 jtc close (fd); 171 1.10 mrg return (nl_catd)-1; 172 1.6 jtc } 173 1.6 jtc 174 1.13 mycroft data = mmap(0, (size_t)st.st_size, PROT_READ, MAP_FILE|MAP_SHARED, fd, 175 1.14 christos (off_t)0); 176 1.9 jtc close (fd); 177 1.9 jtc 178 1.28 joerg if (data == MAP_FAILED) { 179 1.10 mrg return (nl_catd)-1; 180 1.6 jtc } 181 1.6 jtc 182 1.14 christos if (ntohl((u_int32_t)((struct _nls_cat_hdr *)data)->__magic) != 183 1.14 christos _NLS_MAGIC) { 184 1.10 mrg munmap(data, (size_t)st.st_size); 185 1.10 mrg return (nl_catd)-1; 186 1.6 jtc } 187 1.6 jtc 188 1.28 joerg if ((catd = malloc(sizeof (*catd))) == NULL) { 189 1.10 mrg munmap(data, (size_t)st.st_size); 190 1.10 mrg return (nl_catd)-1; 191 1.6 jtc } 192 1.6 jtc 193 1.9 jtc catd->__data = data; 194 1.14 christos catd->__size = (int)st.st_size; 195 1.6 jtc return catd; 196 1.1 jtc } 197