Skip to content

Instantly share code, notes, and snippets.

@imjching

imjching/pipe.c Secret

Created October 10, 2018 19:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save imjching/61b4f07abaf3a079d704a24c4a7406b8 to your computer and use it in GitHub Desktop.
Save imjching/61b4f07abaf3a079d704a24c4a7406b8 to your computer and use it in GitHub Desktop.
Implementing `ls -la | sort`.
// Heavily modified from https://brandonwamboldt.ca/how-linux-pipes-work-under-the-hood-1518/.
#include <stdio.h>
#include <unistd.h> // STDOUT_FILENO
#include <sys/types.h> // wait()
#include <sys/wait.h> // wait()
#define READ_END 0
#define WRITE_END 1
#define FORK_CHILD 0
#define FORK_PARENT 1
// ls -la | sort
int main(int argc, char **argv) {
// Create a pipe in parent
int pipefd[2];
if (pipe(pipefd) == -1) {
printf("parent: failed to create pipe\n");
return 1;
}
// We need to fork two processes, one for ls, and another one for sort
int pid_ls = fork();
if (pid_ls == -1) {
printf("parent: could not fork process to run ls\n");
return 1;
}
if (pid_ls == FORK_CHILD) { // Child
printf("child: running ls\n");
// http://man7.org/linux/man-pages/man3/stdin.3.html
// Merge stdout of ls to write end of pipe.
if (dup2(pipefd[WRITE_END], STDOUT_FILENO) == -1) {
printf("child: failed to call dup2 for ls\n");
return 1;
}
close(pipefd[READ_END]);
close(pipefd[WRITE_END]);
// Replace the current process with ls.
// execve() does not return on success, and the text, data, bss, and stack
// of the calling process are overwritten by that of the program loaded.
// Ref: https://linux.die.net/man/2/execve
char *ls_argv[] = {"/bin/ls", "-la", NULL};
execve("/bin/ls", ls_argv, NULL);
// We will only return here if execve failed.
printf("child: ls failed\n");
return -1;
}
// Parent (FORK_PARENT)
// Continue forking
int pid_sort = fork();
if (pid_sort == -1) {
printf("parent: could not fork process to run sort\n");
return 1;
}
if (pid_sort == FORK_CHILD) { // Child
printf("child: running sort\n");
// http://man7.org/linux/man-pages/man3/stdin.3.html
// Merge stdin of sort to read end of pipe.
if (dup2(pipefd[READ_END], STDIN_FILENO) == -1) {
printf("child: failed to call dup2 for sort\n");
return 1;
}
close(pipefd[READ_END]);
close(pipefd[WRITE_END]);
// Replace the current process with sort.
// execve() does not return on success, and the text, data, bss, and stack
// of the calling process are overwritten by that of the program loaded.
// Ref: https://linux.die.net/man/2/execve
char *sort_argv[] = {"/usr/bin/sort", NULL};
execve("/usr/bin/sort", sort_argv, NULL);
// We will only return here if execve failed.
printf("child: sort failed\n");
return -1;
}
close(pipefd[READ_END]);
close(pipefd[WRITE_END]);
printf("parent: wait for children\n");
while (wait(NULL) > 0);
printf("parent: done!\n");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment