xref: /freebsd/contrib/smbfs/lib/smb/nls.c (revision f1b9d12761de3c33754f03e6d2a5bf9f1b40aad9)
1 /*
2  * Copyright (c) 2000-2001, Boris Popov
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *    This product includes software developed by Boris Popov.
16  * 4. Neither the name of the author nor the names of any co-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 AUTHOR 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 AUTHOR 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  * $Id: nls.c,v 1.8 2001/04/16 12:46:46 bp Exp $
33  */
34 
35 #include <sys/types.h>
36 #include <sys/iconv.h>
37 #include <sys/sysctl.h>
38 #include <ctype.h>
39 #include <dlfcn.h>
40 #include <errno.h>
41 #include <stdio.h>
42 #include <strings.h>
43 #include <stdlib.h>
44 #include <locale.h>
45 #include <err.h>
46 #include <netsmb/smb_lib.h>
47 
48 /*
49  * prototype iconv* functions
50  */
51 typedef void *iconv_t;
52 
53 static iconv_t (*my_iconv_open)(const char *, const char *);
54 static size_t(*my_iconv)(iconv_t, const char **, size_t *, char **, size_t *);
55 static int(*my_iconv_close)(iconv_t);
56 
57 u_char nls_lower[256];
58 u_char nls_upper[256];
59 
60 static iconv_t nls_toext, nls_toloc;
61 static int iconv_loaded;
62 static void *iconv_lib;
63 
64 int
65 nls_setlocale(const char *name)
66 {
67 	int i;
68 
69 	if (setlocale(LC_CTYPE, name) == NULL) {
70 		warnx("can't set locale '%s'\n", name);
71 		return EINVAL;
72 	}
73 	for (i = 0; i < 256; i++) {
74 		nls_lower[i] = tolower(i);
75 		nls_upper[i] = toupper(i);
76 	}
77 	return 0;
78 }
79 
80 int
81 nls_setrecode(const char *local, const char *external)
82 {
83 	iconv_t icd;
84 
85 	if (iconv_loaded == 2)
86 		return ENOENT;
87 	else if (iconv_loaded == 0) {
88 		iconv_loaded++;
89 		iconv_lib = dlopen("libiconv.so", RTLD_LAZY | RTLD_GLOBAL);
90 		if (iconv_lib == NULL) {
91 			warn("Unable to load iconv library: %s\n", dlerror());
92 			iconv_loaded++;
93 			return ENOENT;
94 		}
95 		my_iconv_open = dlsym(iconv_lib, "iconv_open");
96 		my_iconv = dlsym(iconv_lib, "iconv");
97 		my_iconv_close = dlsym(iconv_lib, "iconv_close");
98 	}
99 	if (nls_toext)
100 		my_iconv_close(nls_toext);
101 	if (nls_toloc)
102 		my_iconv_close(nls_toloc);
103 	nls_toext = nls_toloc = (iconv_t)0;
104 	icd = my_iconv_open(external, local);
105 	if (icd == (iconv_t)-1)
106 		return errno;
107 	nls_toext = icd;
108 	icd = my_iconv_open(local, external);
109 	if (icd == (iconv_t)-1) {
110 		my_iconv_close(nls_toext);
111 		nls_toext = (iconv_t)0;
112 		return errno;
113 	}
114 	nls_toloc = icd;
115 	return 0;
116 }
117 
118 char *
119 nls_str_toloc(char *dst, const char *src)
120 {
121 	char *p = dst;
122 	int inlen, outlen;
123 
124 	if (!iconv_loaded)
125 		return strcpy(dst, src);
126 
127 	if (nls_toloc == (iconv_t)0)
128 		return strcpy(dst, src);
129 	inlen = outlen = strlen(src);
130 	my_iconv(nls_toloc, NULL, NULL, &p, &outlen);
131 	my_iconv(nls_toloc, &src, &inlen, &p, &outlen);
132 	*p = 0;
133 	return dst;
134 }
135 
136 char *
137 nls_str_toext(char *dst, const char *src)
138 {
139 	char *p = dst;
140 	int inlen, outlen;
141 
142 	if (!iconv_loaded)
143 		return strcpy(dst, src);
144 
145 	if (nls_toext == (iconv_t)0)
146 		return strcpy(dst, src);
147 	inlen = outlen = strlen(src);
148 	my_iconv(nls_toext, NULL, NULL, &p, &outlen);
149 	my_iconv(nls_toext, &src, &inlen, &p, &outlen);
150 	*p = 0;
151 	return dst;
152 }
153 
154 void *
155 nls_mem_toloc(void *dst, const void *src, int size)
156 {
157 	char *p = dst;
158 	const char *s = src;
159 	int inlen, outlen;
160 
161 	if (!iconv_loaded)
162 		return memcpy(dst, src, size);
163 
164 	if (size == 0)
165 		return NULL;
166 
167 	if (nls_toloc == (iconv_t)0)
168 		return memcpy(dst, src, size);
169 	inlen = outlen = size;
170 	my_iconv(nls_toloc, NULL, NULL, &p, &outlen);
171 	my_iconv(nls_toloc, &s, &inlen, &p, &outlen);
172 	return dst;
173 }
174 
175 void *
176 nls_mem_toext(void *dst, const void *src, int size)
177 {
178 	char *p = dst;
179 	const char *s = src;
180 	int inlen, outlen;
181 
182 	if (size == 0)
183 		return NULL;
184 
185 	if (!iconv_loaded || nls_toext == (iconv_t)0)
186 		return memcpy(dst, src, size);
187 
188 	inlen = outlen = size;
189 	my_iconv(nls_toext, NULL, NULL, &p, &outlen);
190 	my_iconv(nls_toext, &s, &inlen, &p, &outlen);
191 	return dst;
192 }
193 
194 char *
195 nls_str_upper(char *dst, const char *src)
196 {
197 	char *p = dst;
198 
199 	while (*src)
200 		*dst++ = toupper(*src++);
201 	*dst = 0;
202 	return p;
203 }
204 
205 char *
206 nls_str_lower(char *dst, const char *src)
207 {
208 	char *p = dst;
209 
210 	while (*src)
211 		*dst++ = tolower(*src++);
212 	*dst = 0;
213 	return p;
214 }
215