diff --git a/Makefile b/Makefile index 68efd20..c7dd463 100644 --- a/Makefile +++ b/Makefile @@ -102,11 +102,15 @@ mm: build/bin/mm build/bin/mm: src/mm.c build $(CC) $(CFLAGS) -o $@ src/mm.c - .PHONY: npc npc: build/bin/npc build/bin/npc: src/npc.c build - $(CC) $(CFLAGAS) -o $@ src/npc.c + $(CC) $(CFLAGS) -o $@ src/npc.c + +.PHONY: pg +pg: build/bin/pg +build/bin/pg: src/pg.c build + $(CC) $(CFLAGS) -o $@ src/pg.c .PHONY: rpn rpn: build/bin/rpn diff --git a/docs/pg.1 b/docs/pg.1 new file mode 100644 index 0000000..e0f1f99 --- /dev/null +++ b/docs/pg.1 @@ -0,0 +1,24 @@ +.TH P 1 + +.SH NAME + +pg \(en paginate + +.SH DESCRIPTION + +Pg prints standard input to standard output, pausing every 22 lines and waiting +for a line feed from the tty before continuing. + +.SH DIAGNOSTICS + +Pg returns an unsuccessful exit code if the tty couldn't be opened or if pg was +invoked incorrectly (with any arguments). + +.SH RATIONALE + +Plan 9 from Bell Labs had p(1), a similar "cooked"-mode paginator (as opposed +to "raw" mode, which a vast majority of paginators use). + +.SH SEE ALSO + +more(1) diff --git a/src/pg.c b/src/pg.c new file mode 100644 index 0000000..5cb02a1 --- /dev/null +++ b/src/pg.c @@ -0,0 +1,56 @@ +#include +#include +#include + +#if !defined EX_USAGE || !defined EX_SOFTWARE +# include +#endif + +/* Done while looking at plan9ports' src/cmd/p.c. + * Taken from plan9 are the interface (minus p(1)'s shell escaping and the + * ability to page multiple files) and the practice of reading /dev/tty to get + * keyboard input without going through stdin. Also, a newline is now printed + * before querying the keyboard. */ + +static size_t l = 22; /* plan9 default */ + +static char *program_name = "p"; + +static int print_lines(FILE *f, size_t l){ + int c; + + while((c = getc(f)) != EOF) + if((c = putc(c, stdout)) == EOF || (l -= (c == '\n')) == 0) + break; + + return c; +} + +int main(int argc, char *argv[]){ + unsigned char cmd[99+1]; + char *p; + FILE *t; + + if(argc == 0) + argv = &program_name; + + if(argc > 1){ + fprintf(stderr, "Usage: %s\n", argv[0]); + return EX_USAGE; + } + + if((t = fopen("/dev/tty", "rb")) == NULL){ + fprintf(stderr, "%s: Could not open /dev/tty\n", argv[0]); + return EX_SOFTWARE; + } + + while(print_lines(stdin, l) != EOF){ + fgets(cmd, (sizeof cmd) / (sizeof *cmd), t); + for(p = cmd; *p != '\0' && strchr(" \t", *p) != NULL; ++p); + if(feof(t) || (*p | 32) == 'q') + break; + } + +exit: fclose(t); + return 0; +}