Citrus iconv support(4)

add iconv external I/F (iconv.h - iconv_open()/iconv()/iconv_close()) and
iconv(1) utility.
TODO:
  - bump libc minor.
  - add iconv data files.
  - create manpages: iconv_open(3)/iconv(3)/iconv_close(3)/iconv(1)/
    mkesdb(1)/mkcsmapper(1).
This commit is contained in:
tshiozak 2003-06-27 05:21:49 +00:00
parent 151e9a3180
commit ff5c3e6895
11 changed files with 477 additions and 9 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: mi,v 1.413 2003/06/26 09:25:58 wiz Exp $
# $NetBSD: mi,v 1.414 2003/06/27 05:21:49 tshiozak Exp $
. base-sys-root
./altroot base-sys-root
./bin base-sys-root
@ -251,6 +251,7 @@
./usr/bin/hexdump base-util-bin
./usr/bin/host base-netutil-bin
./usr/bin/hoststat base-mailwrapper-bin
./usr/bin/iconv base-util-bin
./usr/bin/id base-util-bin
# This is in `base-util-bin', not `base-rcs-bin' as it is used by pkgsrc
./usr/bin/ident base-util-bin

View File

@ -1,4 +1,4 @@
# $NetBSD: mi,v 1.585 2003/06/25 18:58:23 tshiozak Exp $
# $NetBSD: mi,v 1.586 2003/06/27 05:21:51 tshiozak Exp $
./usr/bin/addr2line comp-debug-bin
./usr/bin/ar comp-util-bin
./usr/bin/as comp-util-bin
@ -235,6 +235,7 @@
./usr/include/gssapi/gssapi.h comp-krb5-include
./usr/include/hesiod.h comp-c-include
./usr/include/histedit.h comp-c-include
./usr/include/iconv.h comp-c-include
./usr/include/ifaddrs.h comp-c-include
./usr/include/inttypes.h comp-c-include
./usr/include/iso646.h comp-c-include

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.109 2003/03/22 12:45:51 jdolecek Exp $
# $NetBSD: Makefile,v 1.110 2003/06/27 05:21:56 tshiozak Exp $
# @(#)Makefile 8.2 (Berkeley) 1/4/94
# Doing a make includes builds /usr/include
@ -9,7 +9,7 @@ NOOBJ= # defined
INCS= a.out.h ar.h assert.h bitstring.h bm.h cpio.h ctype.h db.h dirent.h \
disktab.h dlfcn.h err.h errno.h fmtmsg.h fnmatch.h fstab.h fts.h \
getopt.h glob.h grp.h ifaddrs.h \
getopt.h glob.h grp.h ifaddrs.h iconv.h \
inttypes.h iso646.h kvm.h langinfo.h libgen.h \
limits.h link.h link_aout.h link_elf.h locale.h \
login_cap.h lwp.h malloc.h math.h md2.h md4.h md5.h \

58
include/iconv.h Normal file
View File

@ -0,0 +1,58 @@
/* $NetBSD: iconv.h,v 1.1 2003/06/27 05:21:56 tshiozak Exp $ */
/*-
* Copyright (c)2003 Citrus Project,
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#ifndef _ICONV_H_
#define _ICONV_H_
#include <sys/cdefs.h>
#include <machine/ansi.h>
#ifdef _BSD_SIZE_T_
typedef _BSD_SIZE_T_ size_t;
#undef _BSD_SIZE_T_
#endif
typedef void *iconv_t;
__BEGIN_DECLS
iconv_t iconv_open __P((const char *, const char *));
size_t iconv __P((iconv_t, const char **, size_t *, char **,
size_t *));
int iconv_close __P((iconv_t));
/*
* non-portable interfaces for iconv
*/
int __iconv_get_list __P((char ***, size_t *));
void __iconv_free_list __P((char **, size_t));
size_t __iconv __P((iconv_t, const char **, size_t *, char **,
size_t *, __uint32_t, size_t *));
#define __ICONV_F_HIDE_INVALID 0x0001
__END_DECLS
#endif

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.110 2003/04/14 05:21:50 salo Exp $
# $NetBSD: Makefile,v 1.111 2003/06/27 05:21:52 tshiozak Exp $
# @(#)Makefile 8.2 (Berkeley) 2/3/94
#
# All library objects contain sccsid strings by default; they may be
@ -71,12 +71,13 @@ INCSDIR= /usr/include
.endif
.include "${.CURDIR}/db/Makefile.inc"
.include "${.CURDIR}/citrus/Makefile.inc"
.include "${.CURDIR}/compat-43/Makefile.inc"
.include "${.CURDIR}/dlfcn/Makefile.inc"
.include "${.CURDIR}/gen/Makefile.inc"
.include "${.CURDIR}/gmon/Makefile.inc"
.include "${.CURDIR}/hash/Makefile.inc"
.include "${.CURDIR}/citrus/Makefile.inc"
.include "${.CURDIR}/iconv/Makefile.inc"
.include "${.CURDIR}/locale/Makefile.inc"
.include "${.CURDIR}/md/Makefile.inc"
.include "${.CURDIR}/net/Makefile.inc"

View File

@ -0,0 +1,9 @@
# $NetBSD: Makefile.inc,v 1.1 2003/06/27 05:21:53 tshiozak Exp $
.PATH: ${ARCHDIR}/iconv ${.CURDIR}/iconv
SRCS+= iconv.c
.if ${CITRUS} == "yes"
CPPFLAGS+= -DCITRUS_ICONV
.endif

184
lib/libc/iconv/iconv.c Normal file
View File

@ -0,0 +1,184 @@
/* $NetBSD: iconv.c,v 1.1 2003/06/27 05:21:53 tshiozak Exp $ */
/*-
* Copyright (c)2003 Citrus Project,
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
__RCSID("$NetBSD: iconv.c,v 1.1 2003/06/27 05:21:53 tshiozak Exp $");
#endif /* LIBC_SCCS and not lint */
#include "namespace.h"
#include <assert.h>
#include <errno.h>
#include <paths.h>
#include <iconv.h>
#ifdef CITRUS_ICONV
#include <sys/types.h>
#include <citrus/citrus_types.h>
#include <citrus/citrus_module.h>
#include <citrus/citrus_esdb.h>
#include <citrus/citrus_iconv.h>
#define ISBADF(_h_) (!(_h_) || (_h_) == (iconv_t)-1)
#ifdef __weak_alias
__weak_alias(iconv, _iconv)
__weak_alias(iconv_open, _iconv_open)
__weak_alias(iconv_close, _iconv_close)
#endif
iconv_t
_iconv_open(const char *out, const char *in)
{
int ret;
struct _citrus_iconv *handle;
ret = _citrus_iconv_open(&handle, _PATH_ICONV, in, out);
if (ret) {
errno = ret;
return ((iconv_t)-1);
}
return ((iconv_t)handle);
}
int
_iconv_close(iconv_t handle)
{
if (ISBADF(handle)) {
errno = EBADF;
return (-1);
}
_citrus_iconv_close((struct _citrus_iconv *)handle);
return (0);
}
size_t
_iconv(iconv_t handle, const char **in, size_t *szin, char **out, size_t *szout)
{
int err;
size_t ret;
if (ISBADF(handle)) {
errno = EBADF;
return ((size_t)-1);
}
err = _citrus_iconv_convert(
(struct _citrus_iconv *)handle, in, szin, out, szout, 0, &ret);
if (err) {
errno = err;
ret = (size_t)-1;
}
return (ret);
}
size_t
__iconv(iconv_t handle, const char **in, size_t *szin, char **out,
size_t *szout, u_int32_t flags, size_t *invalids)
{
int err;
size_t ret;
if (ISBADF(handle)) {
errno = EBADF;
return ((size_t)-1);
}
err = _citrus_iconv_convert(
(struct _citrus_iconv *)handle, in, szin, out, szout,
flags, &ret);
if (invalids)
*invalids = ret;
if (err) {
errno = err;
ret = (size_t)-1;
}
return (ret);
}
int
__iconv_get_list(char ***rlist, size_t *rsz)
{
int ret;
ret = _citrus_esdb_get_list(rlist, rsz);
if (ret) {
errno = ret;
return -1;
}
return 0;
}
void
__iconv_free_list(char **list, size_t sz)
{
_citrus_esdb_free_list(list, sz);
}
#else
iconv_t
/*ARGSUSED*/
_iconv_open(const char *in, const char *out)
{
errno = EINVAL;
return ((iconv_t)-1);
}
int
/*ARGSUSED*/
_iconv_close(iconv_t handle)
{
errno = EBADF;
return (-1);
}
size_t
/*ARGSUSED*/
_iconv(iconv_t handle, const char **in, size_t *szin, char **out, size_t *szout)
{
errno = EBADF;
return ((size_t)-1);
}
int
/*ARGSUSED*/
__iconv_get_list(char ***rlist, size_t *rsz)
{
errno = EINVAL;
return -1;
}
void
/*ARGSUSED*/
__iconv_free_list(char **list, size_t sz)
{
}
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: namespace.h,v 1.78 2003/05/28 20:22:55 christos Exp $ */
/* $NetBSD: namespace.h,v 1.79 2003/06/27 05:21:54 tshiozak Exp $ */
/*-
* Copyright (c) 1997-2002 The NetBSD Foundation, Inc.
@ -282,6 +282,9 @@
#define hesiod_init _hesiod_init
#define hesiod_resolve _hesiod_resolve
#define hesiod_to_bind _hesiod_to_bind
#define iconv _iconv
#define iconv_open _iconv_open
#define iconv_close _iconv_close
#define if_freenameindex _if_freenameindex
#define if_indextoname _if_indextoname
#define if_nameindex _if_nameindex

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.134 2003/06/26 06:30:12 tshiozak Exp $
# $NetBSD: Makefile,v 1.135 2003/06/27 05:21:54 tshiozak Exp $
# from: @(#)Makefile 8.3 (Berkeley) 1/7/94
.include <bsd.own.mk>
@ -10,7 +10,7 @@ SUBDIR= apply apropos asa at audio banner basename biff \
db dirname du eject elf2aout elf2ecoff env error expand \
false fdformat fgen file find finger fmt fold fpr \
from fsplit fstat ftp gcore gencat getconf getopt gprof \
head hexdump id indent innetgr ipcrm ipcs join jot \
head hexdump iconv id indent innetgr ipcrm ipcs join jot \
kdump ktrace ktruss lam last lastcomm ldd leave less \
lex locate lock logger login logname look lorder m4 \
machine mail make man menuc mesg midiplay mixerctl mkcsmapper \

9
usr.bin/iconv/Makefile Normal file
View File

@ -0,0 +1,9 @@
# $NetBSD: Makefile,v 1.1 2003/06/27 05:21:55 tshiozak Exp $
WARNS?= 2
PROG= iconv
SRCS= iconv.c
CPPFLAGS+= -I. -I${.CURDIR} -I${NETBSDSRCDIR}/lib/libc
MKMAN= no
.include <bsd.prog.mk>

202
usr.bin/iconv/iconv.c Normal file
View File

@ -0,0 +1,202 @@
/* $NetBSD: iconv.c,v 1.1 2003/06/27 05:21:55 tshiozak Exp $ */
/*-
* Copyright (c)2003 Citrus Project,
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
__RCSID("$NetBSD: iconv.c,v 1.1 2003/06/27 05:21:55 tshiozak Exp $");
#endif /* LIBC_SCCS and not lint */
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iconv.h>
#include <unistd.h>
#include <err.h>
static void
usage(void)
{
fprintf(stderr,
"usage:\n"
"\t%s [-cs] -f <from> -t <to> [file ...]\n"
"\t%s -l\n",
getprogname(), getprogname());
exit(1);
}
static void
show_codesets(void)
{
char **list;
size_t sz, i;
if (__iconv_get_list(&list, &sz))
err(EXIT_FAILURE, "__iconv_get_list()");
for (i=0; i<sz; i++) {
printf("%s\n", list[i]);
}
__iconv_free_list(list, sz);
}
#define INBUFSIZE 1024
#define OUTBUFSIZE (INBUFSIZE*2)
static void
do_conv(const char *fn, FILE *fp, const char *from, const char *to, int silent,
int hide_invalid)
{
char inbuf[INBUFSIZE], outbuf[OUTBUFSIZE], *out;
const char *in;
size_t inbytes, outbytes, ret, invalids;
iconv_t cd;
u_int32_t flags = 0;
if (hide_invalid)
flags |= __ICONV_F_HIDE_INVALID;
cd = iconv_open(to, from);
if (cd == (iconv_t)-1)
err(EXIT_FAILURE, "iconv_open()");
invalids = 0;
while ((inbytes = fread(inbuf, 1, INBUFSIZE, fp)) > 0) {
in = inbuf;
while (inbytes>0) {
out = outbuf;
outbytes = OUTBUFSIZE;
ret = __iconv(cd, &in, &inbytes, &out, &outbytes,
flags, &invalids);
if (ret==(size_t)-1 && errno != E2BIG) {
/*
* XXX: iconv(3) is bad interface.
* invalid character count is lost here.
* instead, we just provide __iconv function.
*/
if (errno != EINVAL || in == inbuf)
err(EXIT_FAILURE, "iconv()");
/* incomplete input character */
memmove(inbuf, in, inbytes);
ret = fread(inbuf+inbytes, 1,
INBUFSIZE-inbytes, fp);
if (ret == 0) {
if (feof(fp))
errx(EXIT_FAILURE,
"iconv(): %s",
strerror(EINVAL));
else
err(EXIT_FAILURE, "fread()");
}
in = inbuf;
inbytes += ret;
}
if (outbytes < OUTBUFSIZE)
fwrite(outbuf, 1, OUTBUFSIZE-outbytes, stdout);
}
}
/* reset the shift state of the output buffer */
outbytes = OUTBUFSIZE;
out = outbuf;
ret = iconv(cd, NULL, NULL, &out, &outbytes);
if (ret == -1)
err(EXIT_FAILURE, "iconv()");
if (outbytes < OUTBUFSIZE)
fwrite(outbuf, 1, OUTBUFSIZE-outbytes, stdout);
if (invalids > 0 && !silent)
warnx("warning: invalid characters: %d", invalids);
iconv_close(cd);
}
int
main(int argc, char **argv)
{
int ch, i;
extern char *optarg;
extern int optind;
int opt_l = 0, opt_s = 0, opt_c = 0;
char *opt_f = NULL, *opt_t = NULL;
FILE *fp;
while ((ch=getopt(argc, argv, "cslf:t:")) != EOF) {
switch (ch) {
case 'c':
opt_c = 1;
break;
case 's':
opt_s = 1;
break;
case 'l':
/* list */
opt_l = 1;
break;
case 'f':
/* from */
opt_f = strdup(optarg);
break;
case 't':
/* to */
opt_t = strdup(optarg);
break;
default:
usage();
}
}
argc-=optind;
argv+=optind;
if (opt_l) {
if (argc>0 || opt_s || opt_f != NULL || opt_t != NULL) {
warnx("%s: -l should be specified solely.",
getprogname());
usage();
}
show_codesets();
} else {
if (opt_f == NULL || opt_t == NULL)
usage();
if (argc == 0)
do_conv("<stdin>", stdin, opt_f, opt_t, opt_s, opt_c);
else {
for (i=0; i<argc; i++) {
fp = fopen(argv[i], "r");
if (fp == NULL)
errx(EXIT_FAILURE, "%s: %s:%s",
getprogname(), argv[i],
strerror(errno));
do_conv(argv[i], fp, opt_f, opt_t, opt_s,
opt_c);
fclose(fp);
}
}
}
return EXIT_SUCCESS;
}