1/*- 2 * Copyright (c) 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Paul Borman at Krystal Technologies. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 4. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33#include <sys/cdefs.h> 34__FBSDID("$FreeBSD: src/lib/libc/locale/setrunelocale.c,v 1.51 2008/01/23 03:05:35 ache Exp $"); 35 36#include "xlocale_private.h" 37 38#include <runetype.h> 39#include <errno.h> 40#include <limits.h> 41#include <string.h> 42#include <stdio.h> 43#include <stdlib.h> 44#include <unistd.h> 45#include <wchar.h> 46#include "ldpart.h" 47#include "mblocal.h" 48#include "setlocale.h" 49 50extern struct __xlocale_st_runelocale *_Read_RuneMagi(FILE *); 51 52#ifdef UNIFDEF_LEGACY_RUNE_APIS 53/* depreciated interfaces */ 54rune_t sgetrune(const char *, size_t, char const **); 55int sputrune(rune_t, char *, size_t, char **); 56#endif /* UNIFDEF_LEGACY_RUNE_APIS */ 57 58__private_extern__ int 59__setrunelocale(const char *encoding, locale_t loc) 60{ 61 FILE *fp; 62 char name[PATH_MAX]; 63 struct __xlocale_st_runelocale *xrl; 64 _RuneLocale *rl; 65 int saverr, ret; 66 static struct __xlocale_st_runelocale *CachedRuneLocale; 67 extern int __mb_cur_max; 68 extern int __mb_sb_limit; 69 static pthread_lock_t cache_lock = LOCK_INITIALIZER; 70 71 /* 72 * The "C" and "POSIX" locale are always here. 73 */ 74 if (strcmp(encoding, "C") == 0 || strcmp(encoding, "POSIX") == 0) { 75 XL_RELEASE(loc->__lc_ctype); 76 loc->__lc_ctype = &_DefaultRuneXLocale; 77 /* no need to retain _DefaultRuneXLocale */ 78 if (loc == &__global_locale) { 79 _CurrentRuneLocale = &loc->__lc_ctype->_CurrentRuneLocale; 80 __mb_cur_max = loc->__lc_ctype->__mb_cur_max; 81 __mb_sb_limit = loc->__lc_ctype->__mb_sb_limit; 82 } 83 return (0); 84 } 85 86 /* 87 * If the locale name is the same as our cache, use the cache. 88 */ 89 LOCK(cache_lock); 90 if (CachedRuneLocale != NULL && 91 strcmp(encoding, CachedRuneLocale->__ctype_encoding) == 0) { 92 XL_RELEASE(loc->__lc_ctype); 93 loc->__lc_ctype = CachedRuneLocale; 94 XL_RETAIN(loc->__lc_ctype); 95 if (loc == &__global_locale) { 96 _CurrentRuneLocale = &loc->__lc_ctype->_CurrentRuneLocale; 97 __mb_cur_max = loc->__lc_ctype->__mb_cur_max; 98 __mb_sb_limit = loc->__lc_ctype->__mb_sb_limit; 99 } 100 UNLOCK(cache_lock); 101 return (0); 102 } 103 UNLOCK(cache_lock); 104 105 /* 106 * Slurp the locale file into the cache. 107 */ 108 109 /* Range checking not needed, encoding length already checked before */ 110 (void) strcpy(name, _PathLocale); 111 (void) strcat(name, "/"); 112 (void) strcat(name, encoding); 113 (void) strcat(name, "/LC_CTYPE"); 114 115 if ((fp = fopen(name, "r")) == NULL) 116 return (errno == 0 ? ENOENT : errno); 117 118 if ((xrl = _Read_RuneMagi(fp)) == NULL) { 119 saverr = (errno == 0 ? EFTYPE : errno); 120 (void)fclose(fp); 121 return (saverr); 122 } 123 (void)fclose(fp); 124 125 xrl->__mbrtowc = NULL; 126 xrl->__mbsinit = NULL; 127 xrl->__mbsnrtowcs = __mbsnrtowcs_std; 128 xrl->__wcrtomb = NULL; 129 xrl->__wcsnrtombs = __wcsnrtombs_std; 130 131 rl = &xrl->_CurrentRuneLocale; 132 133#ifdef UNIFDEF_LEGACY_RUNE_APIS 134 /* provide backwards compatibility (depreciated interface) */ 135 rl->__sputrune = sputrune; 136 rl->__sgetrune = sgetrune; 137#else /* UNIFDEF_LEGACY_RUNE_APIS */ 138 rl->__sputrune = NULL; 139 rl->__sgetrune = NULL; 140#endif /* UNIFDEF_LEGACY_RUNE_APIS */ 141 142 if (strcmp(rl->__encoding, "NONE") == 0) 143 ret = _none_init(xrl); 144 else if (strcmp(rl->__encoding, "ASCII") == 0) 145 ret = _ascii_init(xrl); 146 else if (strcmp(rl->__encoding, "UTF-8") == 0) 147 ret = _UTF8_init(xrl); 148 else if (strcmp(rl->__encoding, "EUC") == 0) 149 ret = _EUC_init(xrl); 150 else if (strcmp(rl->__encoding, "GB18030") == 0) 151 ret = _GB18030_init(xrl); 152 else if (strcmp(rl->__encoding, "GB2312") == 0) 153 ret = _GB2312_init(xrl); 154 else if (strcmp(rl->__encoding, "GBK") == 0) 155 ret = _GBK_init(xrl); 156 else if (strcmp(rl->__encoding, "BIG5") == 0) 157 ret = _BIG5_init(xrl); 158 else if (strcmp(rl->__encoding, "MSKanji") == 0) 159 ret = _MSKanji_init(xrl); 160 else if (strcmp(rl->__encoding, "UTF2") == 0) 161 ret = _UTF2_init(xrl); 162 else 163 ret = EFTYPE; 164 165 if (ret == 0) { 166 (void)strcpy(xrl->__ctype_encoding, encoding); 167 XL_RELEASE(loc->__lc_ctype); 168 loc->__lc_ctype = xrl; 169 if (loc == &__global_locale) { 170 _CurrentRuneLocale = &loc->__lc_ctype->_CurrentRuneLocale; 171 __mb_cur_max = loc->__lc_ctype->__mb_cur_max; 172 __mb_sb_limit = loc->__lc_ctype->__mb_sb_limit; 173 } 174 LOCK(cache_lock); 175 XL_RELEASE(CachedRuneLocale); 176 CachedRuneLocale = xrl; 177 XL_RETAIN(CachedRuneLocale); 178 UNLOCK(cache_lock); 179 } else 180 XL_RELEASE(xrl); 181 182 return (ret); 183} 184 185#ifdef UNIFDEF_LEGACY_RUNE_APIS 186int 187setrunelocale(const char *encoding) 188{ 189 int ret; 190 191 XL_LOCK(&__global_locale); 192 ret = __setrunelocale(encoding, &__global_locale); 193 XL_UNLOCK(&__global_locale); 194 return ret; 195} 196#endif /* UNIFDEF_LEGACY_RUNE_APIS */ 197 198__private_extern__ int 199__wrap_setrunelocale(const char *locale, locale_t loc) 200{ 201 int ret = __setrunelocale(locale, loc); 202 203 if (ret != 0) { 204 errno = ret; 205 return (_LDP_ERROR); 206 } 207 return (_LDP_LOADED); 208} 209 210