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: stable/9/lib/libncp/ncpl_nls.c 237420 2012-06-22 05:36:50Z eadler $");
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  * Characters mapping for codepages used in Germany.
205  */
206 static u_int8_t de_nw2unix[] = {
207 	0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, /* 0x00 */
208 	0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
209 	0x5f, 0x5f, 0x5f, 0x5f, 0xb6, 0xa7, 0x5f, 0x5f, /* 0x10 */
210 	0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
211 	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20 */
212 	0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
213 	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30 */
214 	0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
215 	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40 */
216 	0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
217 	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50 */
218 	0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
219 	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60 */
220 	0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
221 	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70 */
222 	0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
223 	0xc7, 0xfc, 0xe9, 0xe2, 0xe4, 0xe0, 0xe5, 0xe7, /* 0x80 */
224 	0xea, 0xeb, 0xe8, 0xef, 0xee, 0xec, 0xc4, 0xc5,
225 	0xc9, 0xe6, 0xc6, 0xf4, 0xf6, 0xf2, 0xfb, 0xf9, /* 0x90 */
226 	0xff, 0xd6, 0xdc, 0xa2, 0xa3, 0xa5, 0x5f, 0x5f,
227 	0xe1, 0xed, 0xf3, 0xfa, 0xf1, 0xd1, 0xaa, 0xba, /* 0xA0 */
228 	0xbf, 0x5f, 0xac, 0xbd, 0xbc, 0xa1, 0xab, 0xbb,
229 	0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, /* 0xB0 */
230 	0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
231 	0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, /* 0xC0 */
232 	0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
233 	0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, /* 0xD0 */
234 	0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
235 	0x5f, 0xdf, 0x5f, 0x5f, 0x5f, 0x5f, 0xb5, 0x5f, /* 0xE0 */
236 	0x5f, 0x5f, 0x5f, 0xf0, 0x5f, 0xf8, 0x5f, 0x5f,
237 	0x5f, 0xb1, 0x5f, 0x5f, 0x5f, 0x5f, 0xf7, 0x5f, /* 0xF0 */
238 	0xb0, 0x5f, 0xb7, 0x5f, 0x5f, 0xb2, 0x5f, 0xa0
239 };
240 
241 static u_int8_t de_unix2nw[] = {
242 	0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,	/* 0x00 */
243 	0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
244 	0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,	/* 0x10 */
245 	0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
246 	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20 */
247 	0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
248 	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30 */
249 	0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
250 	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40 */
251 	0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
252 	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50 */
253 	0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
254 	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60 */
255 	0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
256 	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70 */
257 	0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
258 	0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, /* 0x80 */
259 	0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
260 	0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, /* 0x90 */
261 	0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
262 	0xff, 0xad, 0x9b, 0x9c, 0x5f, 0x9d, 0x5f, 0x15, /* 0xA0 */
263 	0x5f, 0x5f, 0xa6, 0xae, 0xaa, 0x5f, 0x5f, 0x5f,
264 	0xf8, 0xf1, 0xfd, 0x5f, 0x5f, 0xe6, 0x14, 0xfa, /* 0xB0 */
265 	0x5f, 0x5f, 0xa7, 0xaf, 0xac, 0xab, 0x5f, 0xa8,
266 	0x5f, 0x5f, 0x5f, 0x5f, 0x8e, 0x8f, 0x92, 0x80, /* 0xC0 */
267 	0x5f, 0x90, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
268 	0x5f, 0xa5, 0x5f, 0x5f, 0x5f, 0x5f, 0x99, 0x5f, /* 0xD0 */
269 	0x5f, 0x5f, 0x5f, 0x5f, 0x9a, 0x5f, 0x5f, 0xe1,
270 	0x85, 0xa0, 0x83, 0x5f, 0x84, 0x86, 0x91, 0x87, /* 0xE0 */
271 	0x8a, 0x82, 0x88, 0x89, 0x8d, 0xa1, 0x8c, 0x8b,
272 	0xeb, 0xa4, 0x95, 0xa2, 0x93, 0x5f, 0x94, 0xf6, /* 0xF0 */
273 	0xed, 0x97, 0xa3, 0x96, 0x81, 0x5f, 0x5f, 0x98
274 };
275 
276 
277 static u_int8_t def2lower[256];
278 static u_int8_t def2upper[256];
279 
280 /*
281  * List of available charsets
282  */
283 struct ncp_nlsdesc {
284 	int	scheme;
285 	char	*name;
286 	struct ncp_nlstables nls;
287 };
288 
289 static struct ncp_nlsdesc ncp_nlslist[] = {
290 	{NCP_NLS_AS_IS, NCP_NLS_AS_IS_NAME,
291 	    {def2lower, def2upper, NULL, NULL, 0}
292 	},
293 #ifdef NCP_NLS_KOI2CP866
294 	{NCP_NLS_KOI_866, NCP_NLS_KOI_866_NAME,
295 	    {def2lower, def2upper, alt2koi8, koi82alt, 0}
296 	},
297 #endif
298 	{NCP_NLS_SE, NCP_NLS_SE_NAME,
299 	    {def2lower, def2upper, se_nw2unix, se_unix2nw, 0}
300 	},
301 	{NCP_NLS_DE, NCP_NLS_DE_NAME,
302 	    {def2lower, def2upper, de_nw2unix, de_unix2nw, 0}
303 	},
304 	{0}
305 };
306 
307 struct ncp_nlstables ncp_nls;
308 
309 int
ncp_nls_setlocale(char * name)310 ncp_nls_setlocale(char *name) {
311 	int i;
312 
313 	ncp_nls.to_lower = def2lower;
314 	ncp_nls.to_upper = def2upper;
315 	if (setlocale(LC_CTYPE, name) == NULL) {
316 		fprintf(stderr, "Can't set locale '%s'\n", name);
317 		return EINVAL;
318 	}
319 	for (i = 0; i < 256; i++) {
320 		ncp_nls.to_lower[i] = tolower(i);
321 		ncp_nls.to_upper[i] = toupper(i);
322 	}
323 	return 0;
324 }
325 
326 int
ncp_nls_setrecode(int scheme)327 ncp_nls_setrecode(int scheme) {
328 	struct ncp_nlsdesc *nd;
329 
330 	if (scheme == 0) {
331 #if NCP_NLS_DEFAULT
332 		scheme = NCP_NLS_DEFAULT;
333 #else
334 		scheme = NCP_NLS_AS_IS;
335 #endif
336 	}
337 	for (nd = ncp_nlslist; nd->name; nd++) {
338 		if (nd->scheme != scheme) continue;
339 		ncp_nls.u2n = nd->nls.u2n;
340 		ncp_nls.n2u = nd->nls.n2u;
341 		return ncp_nls_setlocale("");
342 	}
343 	fprintf(stderr, "Character conversion scheme %d was not compiled in\n", scheme);
344 	return EINVAL;
345 }
346 
347 int
ncp_nls_setrecodebyname(char * name)348 ncp_nls_setrecodebyname(char *name) {
349 	struct ncp_nlsdesc *nd;
350 
351 	for (nd = ncp_nlslist; nd->name; nd++) {
352 		if (strcmp(nd->name, name) != 0) continue;
353 		ncp_nls.u2n = nd->nls.u2n;
354 		ncp_nls.n2u = nd->nls.n2u;
355 		return 0;
356 	}
357 	fprintf(stderr, "Character conversion scheme %s was not compiled in\n", name);
358 	return EINVAL;
359 }
360 
361 char *
ncp_nls_str_n2u(char * dst,const char * src)362 ncp_nls_str_n2u(char *dst, const char *src) {
363 	char *p;
364 
365 	if (ncp_nls.n2u == NULL) {
366 		return strcpy(dst, src);
367 	}
368 	p = dst;
369 	while (*src)
370 		*p++ = ncp_nls.n2u[(u_char)*(src++)];
371 	*p = 0;
372 	return dst;
373 }
374 
375 char *
ncp_nls_str_u2n(char * dst,const char * src)376 ncp_nls_str_u2n(char *dst, const char *src) {
377 	char *p;
378 
379 	if (ncp_nls.u2n == NULL) {
380 		return strcpy(dst, src);
381 	}
382 	p = dst;
383 	while (*src)
384 		*p++ = ncp_nls.u2n[(u_char)*(src++)];
385 	*p = 0;
386 	return dst;
387 }
388 
389 char *
ncp_nls_mem_n2u(char * dst,const char * src,int size)390 ncp_nls_mem_n2u(char *dst, const char *src, int size) {
391 	char *p;
392 
393 	if (size == 0) return NULL;
394 	if (ncp_nls.n2u == NULL) {
395 		return memcpy(dst, src, size);
396 	}
397 	for(p = dst; size; size--, p++)
398 		*p = ncp_nls.n2u[(u_char)*(src++)];
399 	return dst;
400 }
401 
402 char *
ncp_nls_mem_u2n(char * dst,const char * src,int size)403 ncp_nls_mem_u2n(char *dst, const char *src, int size) {
404 	char *p;
405 
406 	if (size == 0) return NULL;
407 	if (ncp_nls.u2n == NULL) {
408 		return strcpy(dst, src);
409 	}
410 	for(p = dst; size; size--, p++)
411 		*p = ncp_nls.u2n[(u_char)*(src++)];
412 	return dst;
413 }
414 
415 char *
ncp_str_upper(char * s)416 ncp_str_upper(char *s) {
417 	char *p = s;
418 	while (*s) {
419 		*s = toupper(*s);
420 		s++;
421 	}
422 	return p;
423 }
424