187866Ssheldonh/*
287866Ssheldonh * Copyright (c) 2000-2001, Boris Popov
387866Ssheldonh * All rights reserved.
487866Ssheldonh *
587866Ssheldonh * Redistribution and use in source and binary forms, with or without
687866Ssheldonh * modification, are permitted provided that the following conditions
787866Ssheldonh * are met:
887866Ssheldonh * 1. Redistributions of source code must retain the above copyright
987866Ssheldonh *    notice, this list of conditions and the following disclaimer.
1087866Ssheldonh * 2. Redistributions in binary form must reproduce the above copyright
1187866Ssheldonh *    notice, this list of conditions and the following disclaimer in the
1287866Ssheldonh *    documentation and/or other materials provided with the distribution.
1387866Ssheldonh * 3. All advertising materials mentioning features or use of this software
1487866Ssheldonh *    must display the following acknowledgement:
1587866Ssheldonh *    This product includes software developed by Boris Popov.
1687866Ssheldonh * 4. Neither the name of the author nor the names of any co-contributors
1787866Ssheldonh *    may be used to endorse or promote products derived from this software
1887866Ssheldonh *    without specific prior written permission.
1987866Ssheldonh *
2087866Ssheldonh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2187866Ssheldonh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2287866Ssheldonh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2387866Ssheldonh * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2487866Ssheldonh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2587866Ssheldonh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2687866Ssheldonh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2787866Ssheldonh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2887866Ssheldonh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2987866Ssheldonh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3087866Ssheldonh * SUCH DAMAGE.
3187866Ssheldonh *
32100490Sbp * $Id: nls.c,v 1.10 2002/07/22 08:33:59 bp Exp $
3387866Ssheldonh */
3487866Ssheldonh
35136699Sobrien#include <sys/cdefs.h>
36136699Sobrien__FBSDID("$FreeBSD$");
37136699Sobrien
3887866Ssheldonh#include <sys/types.h>
3987866Ssheldonh#include <sys/sysctl.h>
4087866Ssheldonh#include <ctype.h>
4187866Ssheldonh#include <errno.h>
4287866Ssheldonh#include <stdio.h>
43136699Sobrien#include <string.h>
4487866Ssheldonh#include <stdlib.h>
4587866Ssheldonh#include <locale.h>
4687866Ssheldonh#include <err.h>
4787866Ssheldonh#include <netsmb/smb_lib.h>
4887866Ssheldonh
49258125Sglebius#ifdef HAVE_ICONV
50258125Sglebius#include <iconv.h>
51258125Sglebius#endif
5287866Ssheldonh
5387866Ssheldonhu_char nls_lower[256];
5487866Ssheldonhu_char nls_upper[256];
5587866Ssheldonh
56258125Sglebius#ifdef HAVE_ICONV
5787866Ssheldonhstatic iconv_t nls_toext, nls_toloc;
58258125Sglebius#endif
5987866Ssheldonh
6087866Ssheldonhint
6187866Ssheldonhnls_setlocale(const char *name)
6287866Ssheldonh{
6387866Ssheldonh	int i;
6487866Ssheldonh
6587866Ssheldonh	if (setlocale(LC_CTYPE, name) == NULL) {
6687866Ssheldonh		warnx("can't set locale '%s'\n", name);
6787866Ssheldonh		return EINVAL;
6887866Ssheldonh	}
6987866Ssheldonh	for (i = 0; i < 256; i++) {
7087866Ssheldonh		nls_lower[i] = tolower(i);
7187866Ssheldonh		nls_upper[i] = toupper(i);
7287866Ssheldonh	}
7387866Ssheldonh	return 0;
7487866Ssheldonh}
7587866Ssheldonh
7687866Ssheldonhint
7787866Ssheldonhnls_setrecode(const char *local, const char *external)
7887866Ssheldonh{
79258125Sglebius#ifdef HAVE_ICONV
8087866Ssheldonh	iconv_t icd;
8187866Ssheldonh
8287866Ssheldonh	if (nls_toext)
83258125Sglebius		iconv_close(nls_toext);
8487866Ssheldonh	if (nls_toloc)
85258125Sglebius		iconv_close(nls_toloc);
8687866Ssheldonh	nls_toext = nls_toloc = (iconv_t)0;
87258125Sglebius	icd = iconv_open(external, local);
8887866Ssheldonh	if (icd == (iconv_t)-1)
8987866Ssheldonh		return errno;
9087866Ssheldonh	nls_toext = icd;
91258125Sglebius	icd = iconv_open(local, external);
9287866Ssheldonh	if (icd == (iconv_t)-1) {
93258125Sglebius		iconv_close(nls_toext);
9487866Ssheldonh		nls_toext = (iconv_t)0;
9587866Ssheldonh		return errno;
9687866Ssheldonh	}
9787866Ssheldonh	nls_toloc = icd;
9887866Ssheldonh	return 0;
99258125Sglebius#else
100258125Sglebius	return ENOENT;
10188282Ssheldonh#endif
10287866Ssheldonh}
10387866Ssheldonh
10487866Ssheldonhchar *
105282275Stijlnls_str_toloc(char *dst, char *src)
10687866Ssheldonh{
107258125Sglebius#ifdef HAVE_ICONV
10887866Ssheldonh	char *p = dst;
109136699Sobrien	size_t inlen, outlen;
11087866Ssheldonh
11187866Ssheldonh	if (nls_toloc == (iconv_t)0)
11287866Ssheldonh		return strcpy(dst, src);
11387866Ssheldonh	inlen = outlen = strlen(src);
114258125Sglebius	iconv(nls_toloc, NULL, NULL, &p, &outlen);
115258125Sglebius	while (iconv(nls_toloc, &src, &inlen, &p, &outlen) == -1) {
116100490Sbp		*p++ = *src++;
117100490Sbp		inlen--;
118100490Sbp		outlen--;
119100490Sbp	}
12087866Ssheldonh	*p = 0;
12187866Ssheldonh	return dst;
122258125Sglebius#else
123258125Sglebius	return strcpy(dst, src);
124258125Sglebius#endif
12587866Ssheldonh}
12687866Ssheldonh
12787866Ssheldonhchar *
128282275Stijlnls_str_toext(char *dst, char *src)
12987866Ssheldonh{
130258125Sglebius#ifdef HAVE_ICONV
13187866Ssheldonh	char *p = dst;
132136699Sobrien	size_t inlen, outlen;
13387866Ssheldonh
13487866Ssheldonh	if (nls_toext == (iconv_t)0)
13587866Ssheldonh		return strcpy(dst, src);
13687866Ssheldonh	inlen = outlen = strlen(src);
137258125Sglebius	iconv(nls_toext, NULL, NULL, &p, &outlen);
138258125Sglebius	while (iconv(nls_toext, &src, &inlen, &p, &outlen) == -1) {
139100490Sbp		*p++ = *src++;
140100490Sbp		inlen--;
141100490Sbp		outlen--;
142100490Sbp	}
14387866Ssheldonh	*p = 0;
14487866Ssheldonh	return dst;
145258125Sglebius#else
146258125Sglebius	return strcpy(dst, src);
147258125Sglebius#endif
14887866Ssheldonh}
14987866Ssheldonh
15087866Ssheldonhvoid *
151282275Stijlnls_mem_toloc(void *dst, void *src, int size)
15287866Ssheldonh{
153258125Sglebius#ifdef HAVE_ICONV
15487866Ssheldonh	char *p = dst;
155282275Stijl	char *s = src;
156136699Sobrien	size_t inlen, outlen;
15787866Ssheldonh
15887866Ssheldonh	if (size == 0)
15987866Ssheldonh		return NULL;
16087866Ssheldonh
16187866Ssheldonh	if (nls_toloc == (iconv_t)0)
16287866Ssheldonh		return memcpy(dst, src, size);
16387866Ssheldonh	inlen = outlen = size;
164258125Sglebius	iconv(nls_toloc, NULL, NULL, &p, &outlen);
165258125Sglebius	while (iconv(nls_toloc, &s, &inlen, &p, &outlen) == -1) {
166100490Sbp		*p++ = *s++;
167100490Sbp		inlen--;
168100490Sbp		outlen--;
169100490Sbp	}
17087866Ssheldonh	return dst;
171258125Sglebius#else
172258125Sglebius	return memcpy(dst, src, size);
173258125Sglebius#endif
17487866Ssheldonh}
17587866Ssheldonh
17687866Ssheldonhvoid *
177282275Stijlnls_mem_toext(void *dst, void *src, int size)
17887866Ssheldonh{
179258125Sglebius#ifdef HAVE_ICONV
18087866Ssheldonh	char *p = dst;
181282275Stijl	char *s = src;
182136699Sobrien	size_t inlen, outlen;
18387866Ssheldonh
18487866Ssheldonh	if (size == 0)
18587866Ssheldonh		return NULL;
18687866Ssheldonh
187258125Sglebius	if (nls_toext == (iconv_t)0)
18887866Ssheldonh		return memcpy(dst, src, size);
18987866Ssheldonh
19087866Ssheldonh	inlen = outlen = size;
191258125Sglebius	iconv(nls_toext, NULL, NULL, &p, &outlen);
192258125Sglebius	while (iconv(nls_toext, &s, &inlen, &p, &outlen) == -1) {
193100490Sbp		*p++ = *s++;
194100490Sbp		inlen--;
195100490Sbp		outlen--;
196100490Sbp	}
19787866Ssheldonh	return dst;
198258125Sglebius#else
199258125Sglebius	return memcpy(dst, src, size);
200258125Sglebius#endif
20187866Ssheldonh}
20287866Ssheldonh
20387866Ssheldonhchar *
20487866Ssheldonhnls_str_upper(char *dst, const char *src)
20587866Ssheldonh{
20687866Ssheldonh	char *p = dst;
20787866Ssheldonh
20887866Ssheldonh	while (*src)
20987866Ssheldonh		*dst++ = toupper(*src++);
21087866Ssheldonh	*dst = 0;
21187866Ssheldonh	return p;
21287866Ssheldonh}
21387866Ssheldonh
21487866Ssheldonhchar *
21587866Ssheldonhnls_str_lower(char *dst, const char *src)
21687866Ssheldonh{
21787866Ssheldonh	char *p = dst;
21887866Ssheldonh
21987866Ssheldonh	while (*src)
22087866Ssheldonh		*dst++ = tolower(*src++);
22187866Ssheldonh	*dst = 0;
22287866Ssheldonh	return p;
22387866Ssheldonh}
224