Fix interactive behaviour of iconv program.
diff --git a/ChangeLog b/ChangeLog
index 694548c..3b15f4b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2011-07-03 Bruno Haible <bruno@clisp.org>
+
+ Fix interactive behaviour of iconv program.
+ * Makefile.devel (GNULIB_MODULES): Add safe-read.
+ * src/iconv.c: Include safe-read.h.
+ (convert): Take the infile as a file descriptor, not as a FILE stream.
+ Use safe_read() instead of fread().
+ (main): Update.
+ Reported by Xavier Pucel <xpucel@hotmail.com>.
+
2011-05-02 Bruno Haible <bruno@clisp.org>
Update after gnulib changed.
diff --git a/Makefile.devel b/Makefile.devel
index f33451e..8f6399c 100644
--- a/Makefile.devel
+++ b/Makefile.devel
@@ -73,6 +73,7 @@
memmove \
progname \
relocatable-prog \
+ safe-read \
sigpipe \
stdio \
stdlib \
diff --git a/NEWS b/NEWS
index 91abcc0..30df72a 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,5 @@
+* The 'iconv' program now produces its output as soon as it can. It no longer
+ unnecessarily waits for more input.
* Updated the BIG5-HKSCS converter. The old BIG5-HKSCS converter is renamed to
BIG5-HKSCS:2004. A new converter BIG5-HKSCS:2008 is added. BIG5-HKSCS is now
an alias for BIG5-HKSCS:2008.
diff --git a/src/iconv.c b/src/iconv.c
index 4bd4121..cfb88cc 100644
--- a/src/iconv.c
+++ b/src/iconv.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2009 Free Software Foundation, Inc.
+/* Copyright (C) 2000-2009, 2011 Free Software Foundation, Inc.
This file is part of the GNU LIBICONV Library.
This program is free software: you can redistribute it and/or modify
@@ -38,6 +38,7 @@
#include "binary-io.h"
#include "progname.h"
#include "relocatable.h"
+#include "safe-read.h"
#include "xalloc.h"
#include "uniwidth.h"
#include "uniwidth/cjk.h"
@@ -667,23 +668,25 @@
/* Convert the input given in infile. */
-static int convert (iconv_t cd, FILE* infile, const char* infilename)
+static int convert (iconv_t cd, int infile, const char* infilename)
{
char inbuf[4096+4096];
size_t inbufrest = 0;
+ int infile_error = 0;
char initial_outbuf[4096];
char *outbuf = initial_outbuf;
size_t outbufsize = sizeof(initial_outbuf);
int status = 0;
#if O_BINARY
- SET_BINARY(fileno(infile));
+ SET_BINARY(infile);
#endif
line = 1; column = 0;
iconv(cd,NULL,NULL,NULL,NULL);
for (;;) {
- size_t inbufsize = fread(inbuf+4096,1,4096,infile);
- if (inbufsize == 0) {
+ size_t inbufsize = safe_read(infile,inbuf+4096,4096);
+ if (inbufsize == 0 || inbufsize == SAFE_READ_ERROR) {
+ infile_error = (inbufsize == SAFE_READ_ERROR ? errno : 0);
if (inbufrest == 0)
break;
else {
@@ -809,11 +812,11 @@
} else
break;
}
- if (ferror(infile)) {
+ if (infile_error) {
fflush(stdout);
if (column > 0)
putc('\n',stderr);
- error(0,0,
+ error(0,infile_error,
/* TRANSLATORS: An error message.
The placeholder expands to the input file name. */
_("%s: I/O error"),
@@ -1076,7 +1079,7 @@
hooks.data = NULL;
iconvctl(cd, ICONV_SET_HOOKS, &hooks);
if (i == argc)
- status = convert(cd,stdin,
+ status = convert(cd,fileno(stdin),
/* TRANSLATORS: A filename substitute denoting standard input. */
_("(stdin)"));
else {
@@ -1094,7 +1097,7 @@
infilename);
status = 1;
} else {
- status |= convert(cd,infile,infilename);
+ status |= convert(cd,fileno(infile),infilename);
fclose(infile);
}
}