diff options
-rw-r--r-- | Makefile.am | 1 | ||||
-rw-r--r-- | config.h.in | 9 | ||||
-rw-r--r-- | plugin.c | 11 | ||||
-rw-r--r-- | plugin_iconv.c | 146 | ||||
-rw-r--r-- | plugins.m4 | 14 |
5 files changed, 180 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am index f835144..e6d6d18 100644 --- a/Makefile.am +++ b/Makefile.am @@ -103,6 +103,7 @@ plugin_dvb.c \ plugin_exec.c \ plugin_file.c \ plugin_i2c_sensors.c \ +plugin_iconv.c \ plugin_imon.c \ plugin_isdn.c \ plugin_kvv.c \ diff --git a/config.h.in b/config.h.in index 625293b..3145ff9 100644 --- a/config.h.in +++ b/config.h.in @@ -43,6 +43,9 @@ /* Define to 1 if you have the `gettimeofday' function. */ #undef HAVE_GETTIMEOFDAY +/* Define if you have the iconv() function. */ +#undef HAVE_ICONV + /* Define to 1 if you have the <inttypes.h> header file. */ #undef HAVE_INTTYPES_H @@ -226,6 +229,9 @@ /* Define to 1 if you have the <X11/Xutil.h> header file. */ #undef HAVE_X11_XUTIL_H +/* Define as const if the declaration of iconv() needs const. */ +#undef ICONV_CONST + /* Define to 1 if `lstat' dereferences a symlink specified with a trailing slash. */ #undef LSTAT_FOLLOWS_SLASHED_SYMLINK @@ -275,6 +281,9 @@ /* i2c sensors plugin */ #undef PLUGIN_I2C_SENSORS +/* iconv charset converter plugin */ +#undef PLUGIN_ICONV + /* imon plugin */ #undef PLUGIN_IMON @@ -1,4 +1,4 @@ -/* $Id: plugin.c,v 1.45 2006/08/13 18:14:03 harbaum Exp $ +/* $Id: plugin.c,v 1.46 2006/09/15 19:00:50 entropy Exp $ * * plugin handler for the Evaluator * @@ -23,6 +23,9 @@ * * * $Log: plugin.c,v $ + * Revision 1.46 2006/09/15 19:00:50 entropy + * iconv charset converter plugin + * * Revision 1.45 2006/08/13 18:14:03 harbaum * Added KVV plugin * @@ -318,6 +321,9 @@ int plugin_init(void) #ifdef PLUGIN_I2C_SENSORS plugin_init_i2c_sensors(); #endif +#ifdef PLUGIN_ICONV + plugin_init_iconv(); +#endif #ifdef PLUGIN_IMON plugin_init_imon(); #endif @@ -404,6 +410,9 @@ void plugin_exit(void) #ifdef PLUGIN_I2C_SENSORS plugin_exit_i2c_sensors(); #endif +#ifdef PLUGIN_ICONV + plugin_exit_iconv(); +#endif #ifdef PLUGIN_IMON plugin_exit_imon(); #endif diff --git a/plugin_iconv.c b/plugin_iconv.c new file mode 100644 index 0000000..b21d70b --- /dev/null +++ b/plugin_iconv.c @@ -0,0 +1,146 @@ +/* $Id: plugin_iconv.c,v 1.1 2006/09/15 19:00:50 entropy Exp $ + * + * iconv charset conversion plugin + * + * Copyright (C) 2006 Ernst Bachmann <e.bachmann@xebec.de> + * Copyright (C) 2006 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net> + * + * This file is part of LCD4Linux. + * + * LCD4Linux is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * LCD4Linux is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * $Log: plugin_iconv.c,v $ + * Revision 1.1 2006/09/15 19:00:50 entropy + * iconv charset converter plugin + * + * + */ + +/* + * exported functions: + * + * int plugin_init_iconv (void) + * int plugin_exit_iconv (void) + * + */ + + +#include "config.h" + +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <iconv.h> +#include <errno.h> + +/* these should always be included */ +#include "debug.h" +#include "plugin.h" + +#ifdef WITH_DMALLOC +#include <dmalloc.h> +#endif + + + +/* iconv function, convert charsets */ +/* valid "to" and "from" charsets can be listed by running "iconv -list" from a shell */ +/* utf16 & utf32 encodings won't work, as they contain null bytes, confusing strlen */ +static void my_iconv(RESULT * result, RESULT * charset_from, RESULT * charset_to, RESULT * arg) +{ + char *source; + size_t source_left; + char *dest; + char *dest_pos; + size_t dest_left; + iconv_t cd; + + source = R2S(arg); + source_left = strlen(source); + + /* use twice the memory needed in best case, but save lots of reallocs in worst case */ + /* increase to 4 if most conversions are to utf32 (quite unlikely) */ + /* also alloc a "safety byte" so we can always zero-terminate the string. */ + + dest_left = 2 * source_left; + dest = malloc(dest_left + 1); + dest_pos = dest; + + cd = iconv_open(R2S(charset_to), R2S(charset_from)); + if (cd != (iconv_t) (-1)) { + + do { + debug("plugin_iconv: calling iconv with %ld,[%s]/%ld,%ld", cd, source, source_left, dest_left); + if (iconv(cd, &source, &source_left, &dest_pos, &dest_left) == (size_t) (-1)) { + switch (errno) { + case EILSEQ: + /* illegal bytes in input sequence */ + /* try to fix by skipping a byte */ + info("plugin_iconv: illegal character in input string: %c", *source); + source_left--; + source++; + break; + case EINVAL: + /* input string ends during a multibyte sequence */ + /* try to fix by simply ignoring */ + info("plugin_iconv: illegal character at end of input"); + source_left = 0; + break; + case E2BIG: + /* not enough bytes in outbuf. */ + /* TODO: Realloc output buffer, probably doubling its size? */ + /* for now, just bail out. For lcd4linux 99% of all conversions will go to ascii or latin1 anyways */ + error + ("plugin_iconv: out of memory in destination buffer. Seems like Ernst was too lazy, complain to him!"); + source_left = 0; + break; + default: + error("plugin_iconv: strange errno state (%d) occured", errno); + source_left = 0; + } + } + } while (source_left > 0); /* don't check for == 0, could be negative in EILSEQ case */ + + /* terminate the string, we're sure to have that byte left, see above */ + *dest_pos = 0; + dest_pos++; + + iconv_close(cd); + } else { + error("plugin_iconv: could not open conversion descriptor. Check if your charsets are supported!"); + /* guaranteed to fit. */ + strcpy(dest, source); + } + + SetResult(&result, R_STRING, dest); + + free(dest); +} + + +/* plugin initialization */ +int plugin_init_iconv(void) +{ + + AddFunction("iconv", 3, my_iconv); + + return 0; +} + +void plugin_exit_iconv(void) +{ + /* nothing to clean */ +} @@ -56,6 +56,7 @@ for plugin in $plugins; do PLUGIN_EXEC="yes" PLUGIN_FILE="yes" PLUGIN_I2C_SENSORS="yes" + PLUGIN_ICONV="yes" PLUGIN_IMON="yes" PLUGIN_ISDN="yes" PLUGIN_KVV="yes" @@ -97,6 +98,9 @@ for plugin in $plugins; do i2c_sensors) PLUGIN_I2C_SENSORS=$val ;; + iconv) + PLUGIN_ICONV=$val + ;; imon) PLUGIN_IMON=$val ;; @@ -195,6 +199,16 @@ if test "$PLUGIN_I2C_SENSORS" = "yes"; then PLUGINS="$PLUGINS plugin_i2c_sensors.o" AC_DEFINE(PLUGIN_I2C_SENSORS,1,[i2c sensors plugin]) fi +if test "$PLUGIN_ICONV" = "yes"; then + AM_ICONV + if test "$am_cv_func_iconv" = "yes"; then + PLUGINS="$PLUGINS plugin_iconv.o" + PLUGINLIBS="$PLUGINLIBS $LIBICONV" + AC_DEFINE(PLUGIN_ICONV,1,[iconv charset converter plugin]) + else + AC_MSG_WARN(iconv not found: iconv plugin disabled) + fi +fi if test "$PLUGIN_IMON" = "yes"; then PLUGINS="$PLUGINS plugin_imon.o" AC_DEFINE(PLUGIN_IMON,1,[imon plugin]) |