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 */
58static 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
93static 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 */
133static 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
168static 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 */
206static 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
241static 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
277static u_int8_t def2lower[256];
278static u_int8_t def2upper[256];
279
280/*
281 * List of available charsets
282 */
283struct ncp_nlsdesc {
284	int	scheme;
285	char	*name;
286	struct ncp_nlstables nls;
287};
288
289static 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
307struct ncp_nlstables ncp_nls;
308
309int
310ncp_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
326int
327ncp_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
347int
348ncp_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
361char *
362ncp_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
375char *
376ncp_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
389char *
390ncp_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
402char *
403ncp_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
415char *
416ncp_str_upper(char *s) {
417	char *p = s;
418	while (*s) {
419		*s = toupper(*s);
420		s++;
421	}
422	return p;
423}
424