8
\$\begingroup\$

I have written a pager in C that is supposed to be used in systems where curses is not installed (or broken). It can also be used as a system-wide pager, it works with man pages (only on BSD, though). I want to spot any portability or output problems, as there may be some due to the dependence on buffered input:

#include <stdio.h>
#include <stdlib.h>

/*
 * A very SIMPLE pager that does not require curses. If your curses library
 * is broken, this is practically the only portable one you can easily get.
 * Written by Daniel Roskams, in the public domain
 */

int
main(
    int argc,
    char *argv[])
{
    FILE *fp;
    int ch;

    if (argc < 2) {
        fp = stdin;
    } else if ((fp = fopen(argv[1], "r")) == NULL) {
        perror(argv[1]);
        return EXIT_FAILURE;
    }

    while ((ch = fgetc(fp)) != EOF) {
        if (ch == '\n') {
            getchar();
        } else {
            putchar(ch);
        }
    }

    if (ferror(fp)) {
        perror(argv[1]);
        return EXIT_FAILURE;
    }

    fclose(fp);
    return EXIT_SUCCESS;
}

I don't think there are any code problems themselves, since it compiles with the -Weverything flag with clang.

\$\endgroup\$
2
  • 2
    \$\begingroup\$ I'm not sure I would call displaying one line at a time a "pager", unless you have a two-line display. \$\endgroup\$ Commented Dec 8, 2015 at 1:36
  • \$\begingroup\$ Follow-up question \$\endgroup\$ Commented Dec 8, 2015 at 4:09

1 Answer 1

12
\$\begingroup\$

Bug

You're code has a bug-ish. When using this, if instead of hitting enter when asked to enter a character you enter some other letter and then you press enter, then next newline will be skipped and you will have two lines merged into one:

Fooa
BarHello, World!
Spama
Eggs

where the text file was:

Foo
Bar
Hello, World!
Spam
Eggs

To be honest, I'm not quite sure which line this is occurring on, but I think it has something to do with the getchar() call; when I pressed a, the next line was printed out.

Bug #2

Using the same file as above but this time passing it through STDIN like so:

./a.out < Foo

I got this as a result:

 Fooarello, World!pamggs

I didn't touch the keyboard at all; it just flew through the file. I don't think this is intended.

However, this time, I think I know why. It's this line:

getchar();

When the end of a line is reached, then this is called. However, since the file you are reading is from stdin and getchar() also reads from stdin, then this call is going to remove the next character from the file.

See the input again, but with the characters removed by getchar:

FoobarHello, World!spameggs

The bolded characters are the characters that appeared after each newline.

\$\endgroup\$
1
  • \$\begingroup\$ @AnonymousShadow You have posted a follow-up question, so I assume that you found this answer to be helpful. I suggest that you mark it as an accepted answer. \$\endgroup\$ Commented Dec 8, 2015 at 4:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.