Last active
October 29, 2019 10:29
-
-
Save samrat/94aa8d7fe63e6c2f2525123b6c45f494 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <unistd.h> | |
#include <stdio.h> | |
#include <sys/wait.h> | |
#include <errno.h> | |
#include <stdlib.h> | |
/* Usage: | |
$ clang -o pager main.c | |
$ ./pager 200 | |
*/ | |
#define READ_END 0 | |
#define WRITE_END 1 | |
void perror_die(char* msg) { | |
perror(msg); | |
exit(EXIT_FAILURE); | |
} | |
void print_n_lines(int n) { | |
for (int i = 0; i < n; i++) { | |
printf("%d\n", i); | |
} | |
} | |
int main(int argc, char *argv[]) { | |
int fds[2]; | |
if (pipe(fds) == -1) { | |
perror_die("pipe"); | |
} | |
int child_pid = fork(); | |
switch (child_pid) { | |
case -1: { | |
/* fork failed */ | |
perror_die("fork"); | |
break; | |
} | |
case 0: { /* Child(pager) */ | |
/* Pager process doesn't write to pipe */ | |
close(fds[WRITE_END]); | |
/* Make READ_END of pipe pager's STDIN */ | |
dup2(fds[READ_END], STDIN_FILENO); | |
/* F -> quit-if-one-screen */ | |
/* R -> preserve color formatting */ | |
/* X -> don't send some special instructions eg. to clear terminal screen before starting */ | |
char *less_argv[] = {"less", "-FRX", NULL}; | |
int exec_status = execvp(less_argv[0], less_argv); | |
fprintf(stderr, | |
"execvp failed with status: %d and errno: %d\n", exec_status, errno); | |
break; | |
} | |
default: { /* Parent */ | |
/* STDOUT is now fds[WRITE_END] */ | |
dup2(fds[WRITE_END], STDOUT_FILENO); | |
/* parent doesn't read from pipe */ | |
close(fds[READ_END]); | |
/* "Business" logic which determines what to actually print */ | |
int num_lines = 1024; | |
if (argc > 1) { | |
num_lines = atoi(argv[1]); | |
} | |
print_n_lines(num_lines); | |
fflush(stdout); | |
/* Signal EOF to the pager process */ | |
close(STDOUT_FILENO); | |
int stat_loc; | |
waitpid(child_pid, &stat_loc, 0); | |
break; | |
} | |
} | |
} |
Actually, for this purpose it's better to call fdopen()
for fds[1]
, use that for fprintf and call fclose at the end.
I experimented with this here.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks, fixed.