[Prev][Next][Index][Thread]
Re: Bug in fgets?
On 1999-1-21 Levi <levi@top.monad.net> wrote:
> I'm using fgets to read up to 64 bytes from the stdin
> for a dos-esque command interpreter (a temporary thing
> for testing/debugging) and it works ok, exept for one
> thing, each charecter I type gets displayed twice.
Thanks for the bug report. Attached is a patch for
libc/stdio/fgets.c.
The problem was that the console driver (from posix/sys/console.c)
now has simple line-discipline code, but so did fgets. The fix
is to have fgets call read in the case of getting from stdin.
This will end up at read in console.c, which will handle echo,
backspace, kill, etc, then stop at a newline.
-- bart
--- libc/stdio/fgets.c 1998/11/03 21:13:34 1.7
+++ libc/stdio/fgets.c 1999/01/26 22:25:13 1.8
@@ -6,10 +6,6 @@
#include <stdio.h>
-/*
- * simple fgets implementation based on fgetc
- * XXX gross stdin special case to allow for cooking, echo, backspace, linekill.
- */
char *
fgets(char *str, int size, FILE *stream)
{
@@ -19,6 +15,22 @@
if (size <= 0)
return NULL;
+ /*
+ * Special case for stdin to call read for the whole size,
+ * since console read will stop at the newline and do line
+ * discipline stuff for us.
+ */
+ if (stream == stdin) {
+ int rc = read(fileno(stream), str, size);
+ if (rc > 0)
+ return str;
+ if (rc < 0)
+ stream->_flags |= __SERR;
+ else
+ stream->_flags |= __SEOF;
+ return NULL;
+ }
+
i = 0;
while (i < size) {
c = fgetc(stream);
@@ -26,30 +38,6 @@
if (i == 0)
return NULL;
break;
- }
- if (stream == stdin) {
- if (c == '\r')
- c = '\n';
- else if (c == '\b') {
- if (i > 0) {
- fputc(c, stream);
- fputc(' ', stream);
- fputc(c, stream);
- i--;
- }
- continue;
- }
- else if (c == '\025') { /* ^U -- kill line */
- while (i) {
- fputc('\b', stream);
- fputc(' ', stream);
- fputc('\b', stream);
- i--;
- }
- str[0] = '\0';
- continue;
- }
- fputc(c, stream);
}
str[i++] = c;
if (c == '\n')
References: