Compare commits

...

3 Commits

Author SHA1 Message Date
Nick Chambers 3c64572791 Make a more descriptive readme 2024-04-19 11:23:25 -05:00
Nick Chambers 5253932469 Demonstrate how to remap stdout 2024-04-19 11:20:22 -05:00
Nick Chambers 15aa29126b Add missing header include 2024-04-19 11:05:30 -05:00
3 changed files with 57 additions and 2 deletions

View File

@ -1,3 +1,13 @@
# shellfish
# Shellfish
Examples demonstrating how command-line shells implement features.
## About
Self-contained examples demonstrating how shells implement common features.
Every example can be built and run, however they are not meant to show how to
write production-ready software. They only show how the important functions
work, and not how to do things like handle and recover from errors.
## Recommended Order
1. [exec.c](exec.c)
2. [redirection.c](redirection.c)

1
exec.c
View File

@ -1,3 +1,4 @@
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>

44
redirection.c Normal file
View File

@ -0,0 +1,44 @@
#include <fcntl.h>
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
int main() {
// The program that will get run, and the file to write to. It is similar to
// the command-line:
// echo "Hello, world!" > ./hello.txt
char *const prog[] = { "echo", "Hello, world!", NULL };
const char *filename = "./hello.txt";
// Create a child process like normal. The parent process will wait for the
// child process, and the child process will execute its program with the
// standard output redirected to the file.
pid_t pid = fork();
if(pid == 0) {
// Mimicking the behavior of `>` in the shell, open a handle to the file
// `hello.txt` for writing. If the file doesn't exist, it will be created,
// and if it does exist, truncate the contents of the file.
int handle = open(filename, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR);
// Map the standard output of the child process to the open file handle.
// This means that whatever writes on the child's standard output stream
// will instead go to the file. The parent's standard output stream will
// remain unchanged.
dup2(handle, STDOUT_FILENO);
// Execute the program in the child as normal, now that the standard output
// stream has been redirected to the file.
execvp(prog[0], prog);
} else {
// Wait in the parent process for the child to finish running. Once it is
// finished, write the child's process and exit information to its own
// standard output stream, which was not changed by the child's `dup2`
// call.
int status = 0;
wait(&status);
printf("Process %d exited with status %d.\n", pid, status);
}
return 0;
}