]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - lib/libncp/ncpl_nls.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / lib / libncp / ncpl_nls.c
1 /*
2  * Copyright (c) 1999-2002, 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. Neither the name of the author nor the names of any co-contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32
33 /*
34  * Languages support. Currently is very primitive.
35  */
36 #include <sys/types.h>
37 #include <ctype.h>
38 #include <errno.h>
39 #include <stdio.h>
40 #include <string.h>
41 #include <locale.h>
42
43 #include <netncp/ncp_lib.h>
44 #include <netncp/ncp_cfg.h>
45 #include <netncp/ncp_nls.h>
46
47 #ifndef NCP_NLS_DEFAULT
48 #define NCP_NLS_DEFAULT NCP_NLS_AS_IS
49 #endif
50
51 /*
52  * TODO: Make all tables dynamically loadable.
53  */
54 #ifdef NCP_NLS_KOI2CP866
55 /* Russian tables from easy-cyrillic:
56  * Copyright (C) 1993-1994 by Andrey A. Chernov, Moscow, Russia
57  */
58 static u_int8_t alt2koi8[] = {
59         0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, /* 0x00 */
60         0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
61         0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, /* 0x10 */
62         0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
63         0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20 */
64         0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
65         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30 */
66         0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x5f,
67         0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40 */
68         0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
69         0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50 */
70         0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
71         0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60 */
72         0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
73         0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70 */
74         0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
75         0xe1, 0xe2, 0xf7, 0xe7, 0xe4, 0xe5, 0xf6, 0xfa,
76         0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0,
77         0xf2, 0xf3, 0xf4, 0xf5, 0xe6, 0xe8, 0xe3, 0xfe,
78         0xfb, 0xfd, 0xff, 0xf9, 0xf8, 0xfc, 0xe0, 0xf1,
79         0xc1, 0xc2, 0xd7, 0xc7, 0xc4, 0xc5, 0xd6, 0xda,
80         0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0,
81         0x90, 0x91, 0x92, 0x81, 0x87, 0xb2, 0xb4, 0xa7,
82         0xa6, 0xb5, 0xa1, 0xa8, 0xae, 0xad, 0xac, 0x83,
83         0x84, 0x89, 0x88, 0x86, 0x80, 0x8a, 0xaf, 0xb0,
84         0xab, 0xa5, 0xbb, 0xb8, 0xb1, 0xa0, 0xbe, 0xb9,
85         0xba, 0xb6, 0xb7, 0xaa, 0xa9, 0xa2, 0xa4, 0xbd,
86         0xbc, 0x85, 0x82, 0x8d, 0x8c, 0x8e, 0x8f, 0x8b,
87         0xd2, 0xd3, 0xd4, 0xd5, 0xc6, 0xc8, 0xc3, 0xde,
88         0xdb, 0xdd, 0xdf, 0xd9, 0xd8, 0xdc, 0xc0, 0xd1,
89         0xb3, 0xa3, 0x99, 0x98, 0x93, 0x9b, 0x9f, 0x97,
90         0x9c, 0x95, 0x9e, 0x96, 0xbf, 0x9d, 0x94, 0x9a
91 };
92
93 static u_int8_t koi82alt[] = {
94         0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, /* 0x00 */
95         0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
96         0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, /* 0x10 */
97         0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
98         0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20 */
99         0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
100         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30 */
101         0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x5f,
102         0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40 */
103         0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
104         0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50 */
105         0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
106         0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60 */
107         0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
108         0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70 */
109         0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
110         0xc4, 0xb3, 0xda, 0xbf, 0xc0, 0xd9, 0xc3, 0xb4, /* 0x80 */
111         0xc2, 0xc1, 0xc5, 0xdf, 0xdc, 0xdb, 0xdd, 0xde,
112         0xb0, 0xb1, 0xb2, 0xf4, 0xfe, 0xf9, 0xfb, 0xf7,
113         0xf3, 0xf2, 0xff, 0xf5, 0xf8, 0xfd, 0xfa, 0xf6,
114         0xcd, 0xba, 0xd5, 0xf1, 0xd6, 0xc9, 0xb8, 0xb7,
115         0xbb, 0xd4, 0xd3, 0xc8, 0xbe, 0xbd, 0xbc, 0xc6,
116         0xc7, 0xcc, 0xb5, 0xf0, 0xb6, 0xb9, 0xd1, 0xd2,
117         0xcb, 0xcf, 0xd0, 0xca, 0xd8, 0xd7, 0xce, 0xfc,
118         0xee, 0xa0, 0xa1, 0xe6, 0xa4, 0xa5, 0xe4, 0xa3,
119         0xe5, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae,
120         0xaf, 0xef, 0xe0, 0xe1, 0xe2, 0xe3, 0xa6, 0xa2,
121         0xec, 0xeb, 0xa7, 0xe8, 0xed, 0xe9, 0xe7, 0xea,
122         0x9e, 0x80, 0x81, 0x96, 0x84, 0x85, 0x94, 0x83,
123         0x95, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e,
124         0x8f, 0x9f, 0x90, 0x91, 0x92, 0x93, 0x86, 0x82, /* 0xf0 */ 
125         0x9c, 0x9b, 0x87, 0x98, 0x9d, 0x99, 0x97, 0x9a
126 };
127
128 #endif
129
130 /*
131  * Characters mapping for codepages used in Sweden.
132  */
133 static u_int8_t se_nw2unix[] = {
134         0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, /* 0x00 */
135         0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
136         0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, /* 0x10 */
137         0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
138         0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20 */
139         0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
140         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30 */
141         0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x5f,
142         0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40 */
143         0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
144         0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50 */
145         0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
146         0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60 */
147         0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
148         0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70 */
149         0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
150         0xe1, 0xe2, 0xf7, 0xe7, 0xE4, 0xc4, 0xE5, 0xfa, /* 0x80 */
151         0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xC4, 0xC5,
152         0xf2, 0xf3, 0xf4, 0xf5, 0xF6, 0xe8, 0xe3, 0xfe, /* 0x90 */
153         0xfb, 0xD6, 0xff, 0xf9, 0xf8, 0xfc, 0xe0, 0xf1,
154         0xc1, 0xc2, 0xd7, 0xc7, 0xc4, 0xc5, 0xd6, 0xda, /* 0xA0 */
155         0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0,
156         0x90, 0x91, 0x92, 0x81, 0x87, 0xb2, 0xb4, 0xa7, /* 0xB0 */
157         0xa6, 0xb5, 0xa1, 0xa8, 0xae, 0xad, 0xac, 0x83,
158         0x84, 0x89, 0x88, 0x86, 0x80, 0x8a, 0xaf, 0xb0, /* 0xC0 */
159         0xab, 0xa5, 0xbb, 0xb8, 0xb1, 0xa0, 0xbe, 0xb9,
160         0xba, 0xb6, 0xb7, 0xaa, 0xa9, 0xa2, 0xa4, 0xbd, /* 0xD0 */
161         0xbc, 0x85, 0x82, 0x8d, 0x8c, 0x8e, 0x8f, 0x8b,
162         0xd2, 0xd3, 0xd4, 0xd5, 0xc6, 0xc8, 0xc3, 0xde, /* 0xE0 */
163         0xdb, 0xdd, 0xdf, 0xd9, 0xd8, 0xdc, 0xc0, 0xd1,
164         0xb3, 0xa3, 0x99, 0x98, 0x93, 0x9b, 0x9f, 0x97, /* 0xF0 */
165         0x9c, 0x95, 0x9e, 0x96, 0xbf, 0x9d, 0x94, 0x9a
166 };
167
168 static u_int8_t se_unix2nw[] = {
169         0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, /* 0x00 */
170         0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
171         0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, /* 0x10 */
172         0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
173         0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20 */
174         0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
175         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30 */
176         0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x5f,
177         0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40 */
178         0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
179         0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50 */
180         0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
181         0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60 */
182         0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
183         0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70 */
184         0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
185         0xc4, 0xb3, 0xda, 0xbf, 0xc0, 0xd9, 0xc3, 0xb4, /* 0x80 */
186         0xc2, 0xc1, 0xc5, 0xdf, 0xdc, 0xdb, 0xdd, 0xde,
187         0xb0, 0xb1, 0xb2, 0xf4, 0xfe, 0xf9, 0xfb, 0xf7, /* 0x90 */
188         0xf3, 0xf2, 0xff, 0xf5, 0xf8, 0xfd, 0xfa, 0xf6,
189         0xcd, 0xba, 0xd5, 0xf1, 0xd6, 0xc9, 0xb8, 0xb7, /* 0xA0 */
190         0xbb, 0xd4, 0xd3, 0xc8, 0xbe, 0xbd, 0xbc, 0xc6,
191         0xc7, 0xcc, 0xb5, 0xf0, 0xb6, 0xb9, 0xd1, 0xd2, /* 0xB0 */
192         0xcb, 0xcf, 0xd0, 0xca, 0xd8, 0xd7, 0xce, 0xfc,
193         0xee, 0xa0, 0xa1, 0xe6, 0x8E, 0x8F, 0xe4, 0xa3, /* 0xC0 */
194         0xe5, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae,
195         0xaf, 0xef, 0xe0, 0xe1, 0xe2, 0xe3, 0x99, 0xa2, /* 0xD0 */
196         0xec, 0xeb, 0xa7, 0xe8, 0xed, 0xe9, 0xe7, 0xea,
197         0x9e, 0x80, 0x81, 0x96, 0x84, 0x86, 0x94, 0x83, /* 0xE0 */
198         0x95, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e,
199         0x8f, 0x9f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x82, /* 0xf0 */ 
200         0x9c, 0x9b, 0x87, 0x98, 0x9d, 0x99, 0x97, 0x9a
201 };
202
203
204 static u_int8_t def2lower[256];
205 static u_int8_t def2upper[256];
206
207 /*
208  * List of available charsets
209  */
210 struct ncp_nlsdesc {
211         int     scheme;
212         char    *name;
213         struct ncp_nlstables nls;
214 };
215
216 static struct ncp_nlsdesc ncp_nlslist[] = {
217         {NCP_NLS_AS_IS, NCP_NLS_AS_IS_NAME, 
218             {def2lower, def2upper, NULL, NULL, 0}
219         },
220 #ifdef NCP_NLS_KOI2CP866
221         {NCP_NLS_KOI_866, NCP_NLS_KOI_866_NAME, 
222             {def2lower, def2upper, alt2koi8, koi82alt, 0}
223         },
224 #endif
225         {NCP_NLS_SE, NCP_NLS_SE_NAME, 
226             {def2lower, def2upper, se_nw2unix, se_unix2nw, 0}
227         },
228         {0}
229 };
230
231 struct ncp_nlstables ncp_nls;
232
233 int
234 ncp_nls_setlocale(char *name) {
235         int i;
236
237         ncp_nls.to_lower = def2lower;
238         ncp_nls.to_upper = def2upper;
239         if (setlocale(LC_CTYPE, name) == NULL) {
240                 fprintf(stderr, "Can't set locale '%s'\n", name);
241                 return EINVAL;
242         }
243         for (i = 0; i < 256; i++) {
244                 ncp_nls.to_lower[i] = tolower(i);
245                 ncp_nls.to_upper[i] = toupper(i);
246         }
247         return 0;
248 }
249
250 int
251 ncp_nls_setrecode(int scheme) {
252         struct ncp_nlsdesc *nd;
253
254         if (scheme == 0) {
255 #if NCP_NLS_DEFAULT
256                 scheme = NCP_NLS_DEFAULT;
257 #else
258                 scheme = NCP_NLS_AS_IS;
259 #endif
260         }
261         for (nd = ncp_nlslist; nd->name; nd++) {
262                 if (nd->scheme != scheme) continue;
263                 ncp_nls.u2n = nd->nls.u2n;
264                 ncp_nls.n2u = nd->nls.n2u;
265                 return ncp_nls_setlocale("");
266         }
267         fprintf(stderr, "Character conversion scheme %d was not compiled in\n", scheme);
268         return EINVAL;
269 }
270
271 int
272 ncp_nls_setrecodebyname(char *name) {
273         struct ncp_nlsdesc *nd;
274
275         for (nd = ncp_nlslist; nd->name; nd++) {
276                 if (strcmp(nd->name, name) != 0) continue;
277                 ncp_nls.u2n = nd->nls.u2n;
278                 ncp_nls.n2u = nd->nls.n2u;
279                 return 0;
280         }
281         fprintf(stderr, "Character conversion scheme %s was not compiled in\n", name);
282         return EINVAL;
283 }
284
285 char *
286 ncp_nls_str_n2u(char *dst, const char *src) {
287         char *p;
288
289         if (ncp_nls.n2u == NULL) {
290                 return strcpy(dst, src);
291         }
292         p = dst;
293         while (*src)
294                 *p++ = ncp_nls.n2u[(u_char)*(src++)];
295         *p = 0;
296         return dst;
297 }
298
299 char *
300 ncp_nls_str_u2n(char *dst, const char *src) {
301         char *p;
302
303         if (ncp_nls.u2n == NULL) {
304                 return strcpy(dst, src);
305         }
306         p = dst;
307         while (*src)
308                 *p++ = ncp_nls.u2n[(u_char)*(src++)];
309         *p = 0;
310         return dst;
311 }
312
313 char *
314 ncp_nls_mem_n2u(char *dst, const char *src, int size) {
315         char *p;
316
317         if (size == 0) return NULL;
318         if (ncp_nls.n2u == NULL) {
319                 return memcpy(dst, src, size);
320         }
321         for(p = dst; size; size--, p++)
322                 *p = ncp_nls.n2u[(u_char)*(src++)];
323         return dst;
324 }
325
326 char *
327 ncp_nls_mem_u2n(char *dst, const char *src, int size) {
328         char *p;
329
330         if (size == 0) return NULL;
331         if (ncp_nls.u2n == NULL) {
332                 return strcpy(dst, src);
333         }
334         for(p = dst; size; size--, p++)
335                 *p = ncp_nls.u2n[(u_char)*(src++)];
336         return dst;
337 }
338
339 char *
340 ncp_str_upper(char *s) {
341         char *p = s;
342         while (*s) {
343                 *s = toupper(*s);
344                 s++;
345         }
346         return p;
347 }