--- Begin Message ---
Package: gnuvd
Version: 1.0.3-1
Followup-For: Bug #368736
Well, here's a patch. I forgot how nasty C could be :(
diff -urw gnuvd-1.0.3/src/main.c gnuvd-pdw/src/main.c
--- gnuvd-1.0.3/src/main.c 2005-11-05 15:44:30.000000000 +0100
+++ gnuvd-pdw/src/main.c 2006-06-02 15:29:55.000000000 +0200
@@ -21,10 +21,18 @@
#include <config.h>
#endif /*HAVE_CONFIG*/
+#define _GNU_SOURCE /*for vasprintf*/
+
#include <ctype.h>
+#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
+#include <iconv.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <locale.h>
+#include <langinfo.h>
#include "gnuvd.h"
@@ -37,6 +45,8 @@
/* internal functions */
static void show_results (Buffer *results, int keep_entities);
static char get_special_char (char *str);
+static int iconv_str (iconv_t cd, char **output, char *input);
+static void fprintf_iconv (FILE *f, iconv_t cd, const char *fmt, ...);
static void help ();
int
@@ -44,10 +54,13 @@
{
int keep_entities = 0;
char *word = NULL;
+ iconv_t cd;
VDQuery *vd_query = NULL;
VDError vd_ex;
+ setlocale(LC_CTYPE, "");
+
while (1) {
int c = getopt (argc, argv, "kh");
@@ -73,10 +86,17 @@
break;
}
+ cd = iconv_open("ISO-8859-1", nl_langinfo(CODESET));
+ if (cd != (iconv_t)(-1)) {
+ iconv_str(cd, &word, argv[optind]);
+ iconv_close(cd);
+ }
+ if (!word)
+ /* let's hope for the best */
word = argv[optind];
- vd_ex = VD_ERR_OK;
/* prepare query */
+ vd_ex = VD_ERR_OK;
vd_query = vd_query_new (word, &vd_ex);
if (!vd_query) {
if (vd_ex != VD_ERR_OK)
@@ -116,9 +136,18 @@
char s_kars[S_KARS_MAX + 2];
int skip_spc = 1;
int stress_pos;
+ iconv_t cd;
FILE *out = stdout;
+ cd = iconv_open(nl_langinfo(CODESET), "ISO-8859-1");
+ if (cd == (iconv_t)(-1)) {
+ fprintf(stderr,
+ "Can't convert from ISO-8859-1 to your locale's charset. "
+ "Complain to your\noperating system vendor.");
+ exit(1);
+ }
+
/* output to PAGER or to STDOUT? */
if (isatty(fileno(stdin)) && isatty(fileno(stdout))) {
char *pager = getenv("PAGER");
@@ -129,7 +158,6 @@
}
}
-
/* strip superfluous space after */
for (i = buffer_end (buffer) - 1; i >= buffer_begin(buffer) + 3; --i)
if ((buffer_at (buffer, i-3) == 'D') &&
@@ -144,7 +172,7 @@
/* Keep <=> */
if (buffer_end(buffer) - j > 3) {
if ((strncmp (buffer_data_pos(buffer,j), "<=>", 3) == 0)) {
- fprintf (out, "<=>");
+ fprintf_iconv (out, cd, "<=>");
j+= 2;
continue;
}
@@ -161,7 +189,7 @@
/* SMALL -> */
if (buffer_end(buffer) - j > 7) {
if ((strncmp (buffer_data_pos(buffer,j),"<SMALL>", 7) == 0)) {
- fprintf (out, " (");
+ fprintf_iconv (out, cd, " (");
j += 6;
continue;
}
@@ -170,7 +198,7 @@
/* /SMALL -> */
if (buffer_end(buffer) - j > 8) {
if ((strncmp (buffer_data_pos(buffer,j),"</SMALL>", 8) == 0)) {
- fprintf (out, ")");
+ fprintf_iconv (out, cd, ")");
j += 7;
continue;
}
@@ -181,7 +209,7 @@
if (buffer_end(buffer) - j > 8 && strncmp(buffer_data_pos(buffer,j),
"<DD><B>", 7) == 0) {
j += 6;
- fprintf (out, "\n");
+ fprintf_iconv (out, cd, "\n");
continue;
}
@@ -202,7 +230,7 @@
m_pos = buffer_find_offset (buffer,j,"·",6);
if (stress_pos!=buffer_end(buffer) && stress_pos < dd_pos && stress_pos < m_pos) {
- fprintf (out, "`");
+ fprintf_iconv (out, cd, "`");
j += (strncmp(buffer_data_pos(buffer,j),"<BIG>", 5) == 0) ? 4 : 5;
continue;
}
@@ -228,7 +256,7 @@
k = get_special_char (s_kars);
if (k)
- fprintf (out, "%c", k);
+ fprintf_iconv (out, cd, "%c", k);
}
continue;
}
@@ -240,9 +268,16 @@
else
skip_spc = 0;
}
- fprintf (out, "%c", buffer_at(buffer,j));
+
+ /* convert DOS-style CR/LF line-endings to Unix-style LF */
+ if (buffer_at(buffer,j) == 13)
+ continue;
+
+ fprintf_iconv (out, cd, "%c", buffer_at(buffer,j));
}
+ iconv_close(cd);
+
/* if we were outputing to PAGER, close it */
if (out != stdout) {
fflush (out);
@@ -364,6 +399,77 @@
return '?';
}
+static int
+iconv_str (iconv_t cd, char **output, char *input)
+{
+ size_t inleft;
+ size_t outsize, outleft;
+ size_t result;
+ char *outbuf;
+
+ if (!input)
+ return -1;
+
+ outsize = outleft = 16;
+ *output = outbuf = malloc(outsize);
+ if (!*output)
+ return -1;
+
+ inleft = strlen(input) + 1;
+ while (inleft > 0) {
+ result = iconv(cd, &input, &inleft, &outbuf, &outleft);
+ if (result == (size_t)(-1)) {
+ /* iconv might error out because the output buffer is
+ * full, or because there's something wrong with the
+ * input (an incomplete multibyte character, for
+ * example). We only deal with the first case.
+ */
+ if (errno == E2BIG) {
+ char *new;
+ outleft += outsize;
+ outsize *= 2;
+ new = realloc(*output, outsize);
+ if (!new)
+ goto fail;
+ *output = new;
+ outbuf = *output + outsize - outleft;
+ } else
+ goto fail;
+ }
+ }
+
+ return outsize - outleft;
+
+fail:
+ /* Something went wrong. Reset iconv and free the output buffer */
+ iconv(cd, 0, 0, 0, 0);
+ free(*output);
+ *output = 0;
+ return -1;
+}
+
+static void
+fprintf_iconv (FILE *f, iconv_t cd, const char *fmt, ...)
+{
+ va_list va;
+ char *str, *converted;
+ int result;
+
+ va_start(va, fmt);
+ result = vasprintf(&str, fmt, va);
+ if (result < 0)
+ return; /*out of memory...*/
+ va_end(va);
+
+ result = iconv_str(cd, &converted, str);
+ free(str);
+ if (result < 0)
+ return; /*out or memory, or something even nastier...*/
+
+ fputs(converted, f);
+ free(converted);
+}
+
static void
help()
--- End Message ---