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