Re: tin problem: Error: From: line missing.

Urs Janßen <[email protected]> Fri, 4 Jan 2013 17:34:20 +0100
Newsgroups gmane.network.tin.devel
Message-ID <[email protected]>
--M9NhX3UHpAaciwkO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Fri, Jan 04, 2013 at 06:37:53PM +0700, Victor Sudakov wrote:
> > > It may be a FreeBSD-specific bug
> > as it seems to be locale related it might be a somewhat broken isacii() or
> > the like.
> It also seems to work with LANG=ru_RU.UTF-8. Only KOI8-R is somehow
> problematic.

Looks like I traced it down:

if the locale charset is the same as the network charset (in your case both
were KOI8-R) tin tries to convert the string in the local charset to the
network charset (waste of cpu cycles, but sould work!). But FreeBSDs
iconv(3) seems to have a problem with that, the mapage states:

[...]
| After calling iconv(), the values pointed to by src,
| srcleft, dst, and dstleft are updated as follows:
[...]
|     *dst      Pointer to the byte just after the last character stored.
[...]

but this is not the case, right befor the conversion
(misc.c:buffer_to_network()):

(gdb) print inbuf
$2 = 0x80163d200 "From: Urs Janssen <[email protected]>"
(gdb) print &outbuf
$3 = (char **) 0x7fffffffa5e0
(gdb) print outbuf
$4 = 0x80144d6c0 "G"

right after the conversin:
(gdb) print *&outbuf
$11 = 0x80144d6c0 "From: Urs Janssen <[email protected]>l"
(gdb) print **&outbuf
$17 = 70 'F'

but it should point right behind the '>' to the tailing gargabe ('l').

(gdb) next
2560                    **&outbuf = '\0';

now the entire converted string get's erased instead of being propperly
terminated at the end.

-> From (and everything else) is empty.

attached is a patch which prevents tin from trying to convert local to
network charset if both are the same. this should solve your problem (but
the real bug seems to be in FreeBSDs iconv(3)).

The binarie /home/urs/tin should behave like the one in
/usr/local/bin/ and can be copied to any location. the already patched
source is in /home/urs/tin-2.1.3.tar.gz if you like to recompile on your
own.

Thanks for the access to the machine,
urs
-- 
"Only whimps use tape backup: _real_ men just upload their important stuff
 on ftp, and let the rest of the world mirror it ;)" - Linus

--M9NhX3UHpAaciwkO
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment; filename="charset.diff"

diff -Nurp --exclude='.bzr*' tin-2.1.2/src/misc.c tin-2.1.3/src/misc.c
--- tin-2.1.2/src/misc.c	2012-12-24 11:22:01.000000000 +0100
+++ tin-2.1.3/src/misc.c	2013-01-04 16:26:35.923587224 +0100
@@ -2521,46 +2521,48 @@ buffer_to_network(
 	size_t inbytesleft, outbytesleft;
 	t_bool conv_success = TRUE;
 
-	if ((cd = iconv_open(txt_mime_charsets[mmnwcharset], tinrc.mm_local_charset)) != (iconv_t) (-1)) {
-		inbytesleft = strlen(line);
-		inbuf = (char *) line;
-		outbytesleft = 1 + inbytesleft * 4;
-		osize = outbytesleft;
-		obuf = my_malloc(osize + 1);
-		outbuf = (char *) obuf;
-
-		do {
-			errno = 0;
-			result = iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
-			if (result == (size_t) (-1)) {
-				switch (errno) {
-					case EILSEQ:
-						/* TODO: only one '?' for each multibyte sequence ? */
-						**&outbuf = '?';
-						outbuf++;
-						inbuf++;
-						inbytesleft--;
-						conv_success = FALSE;
-						break;
-
-					case E2BIG:
-						obuf = my_realloc(obuf, osize * 2);
-						outbuf = (char *) (obuf + osize - outbytesleft);
-						outbytesleft += osize;
-						osize <<= 1; /* double size */
-						break;
-
-					default:	/* EINVAL */
-						inbytesleft = 0;
-						conv_success = FALSE;
+	if (strcasecmp(txt_mime_charsets[mmnwcharset], tinrc.mm_local_charset)) {
+		if ((cd = iconv_open(txt_mime_charsets[mmnwcharset], tinrc.mm_local_charset)) != (iconv_t) (-1)) {
+			inbytesleft = strlen(line);
+			inbuf = (char *) line;
+			outbytesleft = 1 + inbytesleft * 4;
+			osize = outbytesleft;
+			obuf = my_malloc(osize + 1);
+			outbuf = (char *) obuf;
+
+			do {
+				errno = 0;
+				result = iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
+				if (result == (size_t) (-1)) {
+					switch (errno) {
+						case EILSEQ:
+							/* TODO: only one '?' for each multibyte sequence ? */
+							**&outbuf = '?';
+							outbuf++;
+							inbuf++;
+							inbytesleft--;
+							conv_success = FALSE;
+							break;
+
+						case E2BIG:
+							obuf = my_realloc(obuf, osize * 2);
+							outbuf = (char *) (obuf + osize - outbytesleft);
+							outbytesleft += osize;
+							osize <<= 1; /* double size */
+							break;
+
+						default:	/* EINVAL */
+							inbytesleft = 0;
+							conv_success = FALSE;
+					}
 				}
-			}
-		} while (inbytesleft > 0);
+			} while (inbytesleft > 0);
 
-		**&outbuf = '\0';
-		strcpy(line, obuf); /* FIXME: here we assume that line is big enough to hold obuf */
-		free(obuf);
-		iconv_close(cd);
+			**&outbuf = '\0';
+			strcpy(line, obuf); /* FIXME: here we assume that line is big enough to hold obuf */
+			free(obuf);
+			iconv_close(cd);
+		}
 	}
 	return conv_success;
 }
diff -Nurp --exclude='.bzr*' tin-2.1.2/src/post.c tin-2.1.3/src/post.c
--- tin-2.1.2/src/post.c	2012-12-24 11:22:02.000000000 +0100
+++ tin-2.1.3/src/post.c	2013-01-04 16:29:26.658530322 +0100
@@ -876,7 +876,7 @@ check_article_to_be_posted(
 		}
 #ifdef CHARSET_CONVERSION
 		/* are all characters in article contained in network_charset? */
-		if (strcmp(tinrc.mm_local_charset, txt_mime_charsets[mmnwcharset]) && !charset_conversion_fails) { /* local_charset != network_charset */
+		if (strcasecmp(tinrc.mm_local_charset, txt_mime_charsets[mmnwcharset]) && !charset_conversion_fails) { /* local_charset != network_charset */
 			cp = my_malloc(strlen(line) * 4 + 1);
 			strcpy(cp, line);
 			charset_conversion_fails = !buffer_to_network(cp, mmnwcharset);
@@ -1243,7 +1243,7 @@ check_article_to_be_posted(
 
 #ifdef CHARSET_CONVERSION
 		/* are all characters in article contained in network_charset? */
-		if (strcmp(tinrc.mm_local_charset, txt_mime_charsets[mmnwcharset]) && !charset_conversion_fails) { /* local_charset != network_charset */
+		if (strcasecmp(tinrc.mm_local_charset, txt_mime_charsets[mmnwcharset]) && !charset_conversion_fails) { /* local_charset != network_charset */
 			cp = my_malloc(strlen(line) * 4 + 1);
 			strcpy(cp, line);
 			charset_conversion_fails = !buffer_to_network(cp, mmnwcharset);

--M9NhX3UHpAaciwkO--