This README provides an overview of the Minishell project for 42 School Hive Helsinki, detailing its objectives and offering guidance. The goal of the project is to implement a simplified shell (command interpreter) in C, following the 42 Norm and POSIX standards. It should handle typical Unix commands, redirections, and pipe operations.
Here is a short demonstration of the Minishell in action:
- Introduction
- Project Structure
- Installation and Compilation
- Running the Program
- Minishell Features
- Examples
- Debugging and Error Handling
- Conclusion
Minishell is a project at Hive Helsinki aiming to enhance your understanding of:
- Process creation and management (
fork,exec,wait). - File descriptors and their redirection.
- Pipes, enabling inter-process communication.
- Signal handling (
SIGINT,SIGQUIT, etc.). - Structural coding and modular design.
The general purpose is to provide a simplified shell that allows users to execute commands, leverage built-in commands, and use many Bash-like functionalities.
Minishell can be divided into several major components:
- Parser – Parses the user’s input (commands, arguments, pipes, redirections, etc.).
- Executor – Executes parsed commands (forks new processes and calls
execve). - Redirections – Manages
<,>,>>, and<<(heredoc) redirections. - Built-in Commands – Implements certain shell internal commands (e.g.,
cd,echo,env,exit). - Signal Handling – Handles signals such as Ctrl-C, Ctrl-\ in both parent and child processes.
- Helper Functions – Includes memory management, error printing, file open/read/close utilities, etc.
Below is a general example of how to build the project.
- Ensure you have gcc or another C compiler installed, as well as make.
- Download or clone the project source code.
- Change directory into the project folder:
cd minishell - Run:
make:
This will compile the necessary .c files and produce an executable (e.g., minishell).
make
Once successfully compiled, launch Minishell by running:
./minishellYou should see a prompt minishell%. Try typing the same commands you would in Bash:
minishell% echo "Hello Minishell!"
Hello Minishell!
minishell% cd ..
minishell% ls -l
To exit, use the exit command or press Ctrl-D
- Minishell searches for the command path in the
$PATHenvironment variable, or checks if it is a built-in command. - If found, Minishell forks a new process and calls
execve. - If the command is not found, an error message is printed.
>Redirects output to the specified file (overwrites the file).>>Appends output to the end of the specified file.<Reads input from the specified file.<<(heredoc) Reads input from user input until the specified delimiter is reached, then writes that input into a pipe for the command to read.
|Connects multiple commands on a single command line. The output of one command becomes the input of the next.- Minishell creates a pipe for each
|, adjusting the stdin/stdout in each child process accordingly.
echoPrints the provided arguments.cdChanges the current working directory.pwdPrints the current working directory path.exportSets environment variables.unsetRemoves environment variables.envDisplays the current environment variables.exitExits Minishell.
- SIGINT (Ctrl-C): Interrupts the current process or returns Minishell to a new prompt.
- SIGQUIT (Ctrl-): May terminate the currently running process or remain silent, depending on your implementation.
- It is important to distinguish whether you are in the parent or child process to manage signals correctly.
$?– Variable that stores the exit status of the last executed command.- Quote parsing – Handling strings in single and double quotes.
minishell% echo "Hello World"
Hello Worldminishell% ls > filelist.txt
minishell% cat filelist.txt
... (content of the ls command)minishell% ls -l | grep minishell
drwxr-xr-x 5 user user 160 Dec 20 10:44 minishellminishell% cat << EOF
> Some text
> more text
> EOF
Some text
more textminishell% pwd
/home/user/projects/minishell
minishell% cd ..
minishell% pwd
/home/user/projects- Debug prints: If you'd like to compile Minishell in debug mode, you can define debug prints in your header files to display additional logs (such as parser states and token details).
- Error messages: It's crucial to detect cases where commands or files are missing, or the user provided incomplete arguments (for example,
cdwithout a path). Make sure you return clear messages (e.g.,minishell: command not found: ...). - Memory leaks: A suppression file (
readline.supp) is provided so Valgrind ignores anyreadline-specific leaks. This lets you focus on managing your Minishell’s resources. Below is an example command for running Valgrind with the suppression file:
valgrind -v --suppressions=readline.supp --leak-check=full --show-leak-kinds=all ./minishellThe Minishell project turned out to be much larger and more demanding than I initially anticipated. Working with process management, pipes, and redirections gave me a far deeper understanding of how a command-line interpreter operates under the hood. In particular, the multi-stage parsing logic and signal handling required careful planning and intensive testing.
Although it took a considerable amount of time and effort, it was a highly rewarding learning experience. I now feel more confident handling processes, file descriptors, and structuring. I believe these skills will be valuable for future projects and challenges.
