pipe-test

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

pager.c (2096B)


      1 #include "config.h"
      2 
      3 #include <sys/wait.h>
      4 
      5 #if HAVE_ERR
      6 #include <err.h>
      7 #endif
      8 #include <errno.h>
      9 #include <stdio.h>
     10 #include <stdlib.h>
     11 #include <unistd.h>
     12 #include <limits.h>
     13 #include <stdint.h>
     14 
     15 enum {
     16 	PIPE_READ,
     17 	PIPE_WRITE,
     18 };
     19 
     20 int
     21 main(int argc, char **argv)
     22 {
     23 	int fildes[2];
     24 	FILE *fpipew = NULL;
     25 	pid_t child;
     26 	uint32_t lines = 1024;
     27 	const char *errstr;
     28 	/*
     29 	 * F:	quit if one screen
     30 	 * X:	don't send some special instructions
     31 	 *	(e.g. clearing the terminal before starting).
     32 	 */
     33 	char *less_argv[] = { "less", "-FX", NULL };
     34 
     35 #if HAVE_PLEDGE
     36 	if (pledge("stdio proc exec", NULL) == -1)
     37 		err(1, "pledge");
     38 #endif
     39 	if (argc > 2) {
     40 		warnx("too many arguments: %s", argv[2]);
     41 		goto usage;
     42 	} else if (argc == 2) {
     43 		lines = strtonum(argv[1], 1, UINT_MAX, &errstr);
     44 		if (errstr != NULL)
     45 			errx(1, "number of lines is %s: %s", errstr, argv[1]);
     46 	}
     47 
     48 	if (pipe(fildes) == -1)
     49 		err(1, "pipe");
     50 
     51 	switch (child = fork()) {
     52 	case -1:
     53 		err(1, "fork");
     54 	case 0:
     55 #if HAVE_PLEDGE
     56 		if (pledge("stdio exec", NULL) == -1)
     57 			err(1, "pledge");
     58 #endif
     59 		/* Pager process doesn't write to pipe */
     60 		if (close(fildes[PIPE_WRITE]) == -1)
     61 			err(1, "close");
     62 		/* Make PIPE_READ of pipe pager's STDIN */
     63 		if (dup2(fildes[PIPE_READ], STDIN_FILENO) == -1)
     64 			err(1, "dup2");
     65 
     66 #if HAVE_PLEDGE
     67 		if (pledge("exec", NULL) == -1)
     68 			err(1, "pledge");
     69 #endif
     70 		execvp(less_argv[0], less_argv);
     71 		err(1, "execvp");
     72 		break;
     73 	default:
     74 #if HAVE_PLEDGE
     75 		if (pledge("stdio", NULL) == -1)
     76 			err(1, "pledge");
     77 #endif
     78 		if ((fpipew = fdopen(fildes[PIPE_WRITE], "w")) == NULL)
     79 			err(1, "fdopen");
     80 		/* Parent doesn't read from pipe */
     81 		if (close(fildes[PIPE_READ]) == -1)
     82 			err(1, "close");
     83 
     84 		for (uint32_t i = 1; i <= lines; i++)
     85 			fprintf(fpipew, "%d\n", i);
     86 
     87 		/* Flush the buffer and signal EOF to the pager process. */
     88 		if (fclose(fpipew) == EOF)
     89 			err(1, "fclose");
     90 
     91 		/* Pass a dummy status since we don't set behavior */
     92 		if (waitpid(child, &(pid_t){0}, 0) == -1)
     93 			err(1, "waitpid");
     94 		break;
     95 	}
     96 
     97 	return 0;
     98 
     99 usage:
    100 	fprintf(stderr, "usage: %s [num-lines]\n", getprogname());
    101 
    102 	return 1;
    103 }