pipe-test

A simple program that pipes to less in C
git clone git://git.sgregoratto.me/pipe-test
Log | Files | Refs | README

commit 1a40e1af6901ce298fd535e83aab280c006e5b09
parent c16d905214842970bda55ab3fabac6a5a3d59af4
Author: Stephen Gregoratto <dev@sgregoratto.me>
Date:   Tue, 29 Oct 2019 15:55:32 +1100

add pledge(2), simplify code

- The READ/WRITE_END preprocessor variables are replaced in favor of
  global enums.
- lines is a unsigned 32-bit int because why not.
- Drop the -R flag for less as there's no colour output.
- Open PIPE_WRITE as a FILE * instead of making it STDIN_FILENO.
  Saves us from calling dup2(2), close(2) and flushing the buffer.
- Liberal use of pledge(2).

Diffstat:
Mpager.c | 64+++++++++++++++++++++++++++++++++++++++-------------------------
1 file changed, 39 insertions(+), 25 deletions(-)

diff --git a/pager.c b/pager.c @@ -12,25 +12,30 @@ #include <limits.h> #include <stdint.h> -#define READ_END 0 -#define WRITE_END 1 +enum { + PIPE_READ, + PIPE_WRITE, +}; int main(int argc, char **argv) { int fildes[2]; - int exec_status; - uint32_t lines = 1024; + FILE *fpipew = NULL; pid_t child; + uint32_t lines = 1024; const char *errstr; /* - * F -> quit-if-one-screen - * R -> preserve color formatting - * X -> don't send some special instructions eg. to clear - * terminal screen before starting + * F: quit if one screen + * X: don't send some special instructions + * (e.g. clearing the terminal before starting). */ - char *less_argv[] = { "less", "-FRX", NULL}; + char *less_argv[] = { "less", "-FX", NULL }; +#if HAVE_PLEDGE + if (pledge("stdio proc exec", NULL) == -1) + err(1, "pledge"); +#endif if (argc > 2) { warnx("too many arguments: %s", argv[2]); goto usage; @@ -47,33 +52,42 @@ main(int argc, char **argv) case -1: err(1, "fork"); case 0: +#if HAVE_PLEDGE + if (pledge("stdio exec", NULL) == -1) + err(1, "pledge"); +#endif /* Pager process doesn't write to pipe */ - if (close(fildes[WRITE_END]) == -1) + if (close(fildes[PIPE_WRITE]) == -1) err(1, "close"); - /* Make READ_END of pipe pager's STDIN */ - if (dup2(fildes[READ_END], STDIN_FILENO) == -1) + /* Make PIPE_READ of pipe pager's STDIN */ + if (dup2(fildes[PIPE_READ], STDIN_FILENO) == -1) err(1, "dup2"); - - exec_status = execvp(less_argv[0], less_argv); - err(1, "execvp returned %d", exec_status); +#if HAVE_PLEDGE + if (pledge("exec", NULL) == -1) + err(1, "pledge"); +#endif + execvp(less_argv[0], less_argv); + err(1, "execvp"); break; default: - /* stdout is now fildes[WRITE_END] */ - if (dup2(fildes[WRITE_END], STDOUT_FILENO) == -1) - err(1, "dup2"); - /* parent doesn't read from pipe */ - if (close(fildes[READ_END]) == -1) +#if HAVE_PLEDGE + if (pledge("stdio", NULL) == -1) + err(1, "pledge"); +#endif + if ((fpipew = fdopen(fildes[PIPE_WRITE], "w")) == NULL) + err(1, "fdopen"); + /* Parent doesn't read from pipe */ + if (close(fildes[PIPE_READ]) == -1) err(1, "close"); for (uint32_t i = 0; i <= lines; i++) - printf("%04d\n", i); + fprintf(fpipew, "%04d\n", i); - /* Signal EOF to the pager process. fclose closes STDOUT_FILENO */ - if (fclose(stdout) == EOF) + /* Flush the buffer and signal EOF to the pager process. */ + if (fclose(fpipew) == EOF) err(1, "fclose"); - if (close(fildes[WRITE_END]) == -1) - err(1, "close"); + /* Pass a dummy status since we don't set behavior */ if (waitpid(child, &(pid_t){0}, 0) == -1) err(1, "waitpid"); break;