1 /* $NetBSD: iconv.c,v 1.11 2009/03/03 16:22:33 explorer Exp $ */ 2 3 /*- 4 * Copyright (c)2003 Citrus Project, 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 #if defined(LIBC_SCCS) && !defined(lint) 31 __RCSID("$NetBSD: iconv.c,v 1.11 2009/03/03 16:22:33 explorer Exp $"); 32 #endif /* LIBC_SCCS and not lint */ 33 34 #include "namespace.h" 35 #include <assert.h> 36 #include <errno.h> 37 #include <paths.h> 38 #include <sys/queue.h> 39 40 #include <iconv.h> 41 42 #ifdef __weak_alias 43 __weak_alias(iconv, _iconv) 44 __weak_alias(iconv_open, _iconv_open) 45 __weak_alias(iconv_close, _iconv_close) 46 #endif 47 48 #ifdef HAVE_CITRUS 49 #include <sys/types.h> 50 #include <string.h> 51 #include <stdlib.h> 52 #include "citrus_types.h" 53 #include "citrus_module.h" 54 #include "citrus_esdb.h" 55 #include "citrus_hash.h" 56 #include "citrus_iconv.h" 57 58 #define ISBADF(_h_) (!(_h_) || (_h_) == (iconv_t)-1) 59 60 iconv_t 61 iconv_open(const char *out, const char *in) 62 { 63 int ret; 64 struct _citrus_iconv *handle; 65 char *out_truncated; 66 char *p; 67 68 /* 69 * Remove anything following a //, as these are options (like 70 * //ignore, //translate, etc) and we just don't handle them. 71 * This is for compatibilty wiht software that uses thees 72 * blindly. 73 */ 74 out_truncated = strdup(out); 75 if (out_truncated == NULL) { 76 errno = ENOMEM; 77 return ((iconv_t)-1); 78 } 79 80 p = out_truncated; 81 while (*p != 0) { 82 if (p[0] == '/' && p[1] == '/') { 83 *p = '\0'; 84 break; 85 } 86 p++; 87 } 88 89 ret = _citrus_iconv_open(&handle, _PATH_ICONV, in, out_truncated); 90 free(out_truncated); 91 if (ret) { 92 errno = ret == ENOENT? EINVAL : ret; 93 return ((iconv_t)-1); 94 } 95 96 return ((iconv_t)(void *)handle); 97 } 98 99 int 100 iconv_close(iconv_t handle) 101 { 102 if (ISBADF(handle)) { 103 errno = EBADF; 104 return (-1); 105 } 106 107 _citrus_iconv_close((struct _citrus_iconv *)(void *)handle); 108 109 return (0); 110 } 111 112 size_t 113 iconv(iconv_t handle, const char **in, size_t *szin, char **out, size_t *szout) 114 { 115 int err; 116 size_t ret; 117 118 if (ISBADF(handle)) { 119 errno = EBADF; 120 return ((size_t)-1); 121 } 122 123 err = _citrus_iconv_convert( 124 (struct _citrus_iconv *)(void *)handle, in, szin, out, szout, 125 0, &ret); 126 if (err) { 127 errno = err; 128 ret = (size_t)-1; 129 } 130 131 return (ret); 132 } 133 134 size_t 135 __iconv(iconv_t handle, const char **in, size_t *szin, char **out, 136 size_t *szout, u_int32_t flags, size_t *invalids) 137 { 138 int err; 139 size_t ret; 140 141 if (ISBADF(handle)) { 142 errno = EBADF; 143 return ((size_t)-1); 144 } 145 146 err = _citrus_iconv_convert( 147 (struct _citrus_iconv *)(void *)handle, in, szin, out, szout, 148 flags, &ret); 149 if (invalids) 150 *invalids = ret; 151 if (err) { 152 errno = err; 153 ret = (size_t)-1; 154 } 155 156 return (ret); 157 } 158 159 int 160 __iconv_get_list(char ***rlist, size_t *rsz) 161 { 162 int ret; 163 164 ret = _citrus_esdb_get_list(rlist, rsz); 165 if (ret) { 166 errno = ret; 167 return -1; 168 } 169 170 return 0; 171 } 172 173 void 174 __iconv_free_list(char **list, size_t sz) 175 { 176 _citrus_esdb_free_list(list, sz); 177 } 178 179 #else 180 iconv_t 181 /*ARGSUSED*/ 182 iconv_open(const char *in, const char *out) 183 { 184 errno = EINVAL; 185 return ((iconv_t)-1); 186 } 187 int 188 /*ARGSUSED*/ 189 iconv_close(iconv_t handle) 190 { 191 errno = EBADF; 192 return (-1); 193 } 194 size_t 195 /*ARGSUSED*/ 196 iconv(iconv_t handle, const char **in, size_t *szin, char **out, size_t *szout) 197 { 198 errno = EBADF; 199 return ((size_t)-1); 200 } 201 int 202 /*ARGSUSED*/ 203 __iconv_get_list(char ***rlist, size_t *rsz) 204 { 205 errno = EINVAL; 206 return -1; 207 } 208 void 209 /*ARGSUSED*/ 210 __iconv_free_list(char **list, size_t sz) 211 { 212 } 213 #endif 214