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,"&#183;",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()

Reply via email to