1155835Sume/*-
2155835Sume * Copyright (c) 2006 Hajimu UMEMOTO <ume@FreeBSD.org>
3155835Sume * All rights reserved.
4155835Sume *
5155835Sume * Redistribution and use in source and binary forms, with or without
6155835Sume * modification, are permitted provided that the following conditions
7155835Sume * are met:
8155835Sume * 1. Redistributions of source code must retain the above copyright
9155835Sume *    notice, this list of conditions and the following disclaimer.
10155835Sume * 2. Redistributions in binary form must reproduce the above copyright
11155835Sume *    notice, this list of conditions and the following disclaimer in the
12155835Sume *    documentation and/or other materials provided with the distribution.
13155835Sume *
14155835Sume * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15155835Sume * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16155835Sume * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17155835Sume * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18155835Sume * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19155835Sume * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20155835Sume * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21155835Sume * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22155835Sume * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23155835Sume * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24155835Sume * SUCH DAMAGE.
25155835Sume *
26155835Sume * $FreeBSD$
27155835Sume */
28155835Sume
29155835Sume#include <dlfcn.h>
30155835Sume#include <stddef.h>
31155835Sume
32155835Sume#include "iconv.h"
33155835Sume
34155835Sume#undef iconv_open
35155835Sume#undef iconv
36155835Sume#undef iconv_close
37155835Sume
38155835Sume#define ICONVLIB	"libiconv.so"
39295147Sume#define ICONV_ENGINE	"libiconv"
40295147Sume#define ICONV_OPEN	"libiconv_open"
41295147Sume#define ICONV_CLOSE	"libiconv_close"
42155835Sume
43155835Sumetypedef iconv_t iconv_open_t(const char *, const char *);
44155835Sume
45155835Sumedl_iconv_t *dl_iconv;
46155835Sumedl_iconv_close_t *dl_iconv_close;
47155835Sume
48155835Sumestatic int initialized;
49155835Sumestatic void *iconvlib;
50155835Sumestatic iconv_open_t *iconv_open;
51155835Sume
52155835Sumeiconv_t
53155835Sumedl_iconv_open(const char *tocode, const char *fromcode)
54155835Sume{
55155835Sume	if (initialized) {
56155835Sume		if (iconvlib == NULL)
57155835Sume			return (iconv_t)-1;
58155835Sume	} else {
59155835Sume		initialized = 1;
60155835Sume		iconvlib = dlopen(ICONVLIB, RTLD_LAZY | RTLD_GLOBAL);
61155835Sume		if (iconvlib == NULL)
62155835Sume			return (iconv_t)-1;
63155835Sume		iconv_open = (iconv_open_t *)dlfunc(iconvlib, ICONV_OPEN);
64198189Sume		if (iconv_open == NULL)
65198189Sume			goto dlfunc_err;
66155835Sume		dl_iconv = (dl_iconv_t *)dlfunc(iconvlib, ICONV_ENGINE);
67198189Sume		if (dl_iconv == NULL)
68198189Sume			goto dlfunc_err;
69155835Sume		dl_iconv_close = (dl_iconv_close_t *)dlfunc(iconvlib,
70155835Sume		    ICONV_CLOSE);
71198189Sume		if (dl_iconv_close == NULL)
72198189Sume			goto dlfunc_err;
73155835Sume	}
74155835Sume	return iconv_open(tocode, fromcode);
75198189Sume
76198189Sumedlfunc_err:
77198189Sume	dlclose(iconvlib);
78198189Sume	iconvlib = NULL;
79198189Sume	return (iconv_t)-1;
80155835Sume}
81