Welcome to my Minishell project! This project is part of the curriculum at 42 School and consists in developing a simplified Unix shell. The goal is to recreate the behavior of Bash in its most essential features, while gaining deep understanding of processes, redirections, file descriptors, and shell grammar.
The main objectives of this project are to:
- Understand and implement Unix process management using
fork,execve,wait,pipe, etc. - Manage file descriptors and redirections (
<,>,>>,<<). - Create a tokenizer and parser to process command-line input (quotes, variables, etc.).
- Handle signals and interactive user input with behavior similar to Bash.
- Implement built-in shell commands with correct behavior.
- Bonus: Add support for logical operators, wildcards, and grouped commands.
- Prompt display: Shows a custom prompt when waiting for user input.
- Command execution: Supports absolute/relative paths and PATH search.
- Redirections: Handles
>,>>,<, and heredoc<<with delimiter. - Pipes: Executes commands in a pipeline (
cmd1 | cmd2 | cmd3). - Environment variables: Expands
$VAR,$?, and supportsexport,unset, etc. - Quotes management:
'and"handled per Bash rules. - Signal handling:
ctrl-C,ctrl-D,ctrl-\behave correctly in interactive mode. - Built-in commands: Includes all required shell built-ins.
- Abstract Syntax Tree: Internal command structure built using a full AST.
- Bonus logic: Handles
&&,||, parentheses, wildcards*, and grouped execution.
To compile the project, use the following commands:
make # Compiles the minishell executable make clean # Deletes the compiled object files make fclean # Deletes the object files and the executable make re # Fully recompiles the project ## Executing Minishell To start the shell, simply run: ```bash ./minishell``` Once running, you can use it like a basic Bash shell: ```bash minishell$ echo Hello World Hello World minishell$ export VAR=42 minishell$ echo $VAR 42 minishell$ ls -l | grep minishell > result.txt minishell$ cat << EOF > This is a line > Another one > EOF
If the command is invalid or the syntax is incorrect, the shell will display an Error message and return to the prompt without crashing.
The following built-in commands are implemented:
| Command | Description |
|---|---|
echo [-n] |
Prints arguments to stdout |
cd [path] |
Changes current directory |
pwd |
Prints the current directory |
export VAR=value |
Sets an environment variable |
unset VAR |
Removes an environment variable |
env |
Displays current environment variables |
exit [code] |
Exits the shell with an optional status |
These built-ins are handled internally by the shell, without calling external binaries. Each one mimics Bash behavior as closely as possible within the scope of the project.
When compiled using make bonus, the shell includes the following advanced features:
| Feature | Description |
|---|---|
&& / ` |
|
| Parentheses | Groups commands to define execution priority: `(cmd1 && cmd2) |
Wildcard * |
Expands to files in current working directory (e.g., ls *.c) |
Heredoc << |
Reads input until a defined delimiter is encountered (e.g., cat << EOF) |
These features are fully integrated with the parsing logic and are executed via an Abstract Syntax Tree, making the shell robust and scalable.
Minishell supports interactive keyboard input with behaviors matching Bash:
| Key | Behavior |
|---|---|
ctrl-C |
Interrupts the current command and displays a new prompt |
ctrl-D |
Exits the shell if the line is empty (EOF) |
ctrl-\ |
Ignored (no output, no quit signal) |
The prompt is redrawn cleanly after interrupts, and no core dump occurs when pressing ctrl-\.
A simple example with pipe, logical operator and command groups.
This project provided a deep dive into:
-
Unix system programming:
- Processes:
fork,execve,wait,waitpid - Signals:
sigaction,kill,SIGINT,SIGQUIT - File descriptors:
pipe,dup,dup2,open,close
- Processes:
-
Shell grammar parsing:
- Tokenizer for operators, quotes, variables
- Abstract Syntax Tree for logical operator priority
- Syntax validation for redirections and pipelines
-
Memory management:
- Strict adherence to freeing all heap memory
- No leaks tolerated (except from
readline, per subject)
-
Modularity & architecture:
- Clear separation of concerns (lexer, parser, executor)
- Use of custom
libft - Scalable AST-based command execution model
Thank you for taking the time to explore this project! I hope it serves as a useful and inspiring example for learning how shells work at a low level. πβ¨
Project made with the help of my teammate AK Dovlet