Minishell is a 42 project focused on building a minimal Bash-like shell. This shell interprets and executes commands with support for piping, redirections, and environment variable expansion. The project also includes built-in commands and advanced features as bonuses.
- Mandatory:
- 🔄 Redirections:
>
,>>
,<
- 🔗 Piping:
|
- ⚙️ Command execution using
fork(2)
andexecve(2)
- 🚦 Signal handling:
SIGINT
,SIGQUIT
,EOF
- 🛠️ Built-in commands:
- 🗣️
echo
(with-n
) - 📂
cd
(relative or absolute paths) - 🧭
pwd
(no options) - 📤
export
(no options) - 🚫
unset
(no options) - 🌐
env
(no arguments) - 🔚
exit
(no options)
- 🗣️
- 💲 Environment variable expansion:
$VAR_NAME
- 🔄 Redirections:
- C Compiler (e.g.,
gcc
) - Readline Library (v8+)
- Makefile for compilation
- Unix-based system (Linux or macOS)
Run the following command:
make
Start the shell by executing:
./minishell
The project is divided into three main phases:
The tokenizer breaks down the user input into manageable components (tokens).
- Read the input string.
- Tokenize the input into a list/queue/stack of structured tokens ready for parsing.
The parser verifies syntax and builds an Abstract Syntax Tree (AST) that represents the hierarchical structure of the command.
$> WORD1 | WORD2 > WORD3
The resulting tree might look like this:
( PIPE )
/ \
( WORD1 ) ( OUTPUT_REDIRECTION )
[ WORD2 ] [ WORD3 ]
- The AST's structure depends on your execution strategy. You can adapt it to simplify I/O redirection or argument handling.
- ❌ Syntax errors are handled here. If the input is invalid, an error is returned, and execution stops.
The interpreter traverses the AST and executes the commands.
- Perform a post-order depth-first traversal of the AST.
- At each node:
- Execute commands using
fork(2)
andexecve(2)
. - Handle built-in commands internally if applicable.
- Process I/O redirections or pipes based on the node's type.
- Execute commands using
For the AST:
( REDIRECT_OUTPUT )
/ \
( PIPE ) ( WORD3 )
/ \
( WORD1 ) ( WORD2 )
The traversal and processing/interpreting follow this process:
- Traverse
WORD1
and process it. - Pipe its output to
WORD2
. - Redirect the result of
WORD2
toWORD3
.
void traverse(ASTNode *node)
{
if (node == NULL)
return;
traverse(node->left);
traverse(node->right);
process_node(node);
}
⚠️ Error Handling: The shell ensures syntactic correctness during parsing. Runtime errors (e.g., invalid commands) are handled during execution.- 🛠️ Customization: You are free to structure the AST and handle I/O redirections in ways that suit your implementation style. We opted for a different organisation of the AST in our Minishell than the one you see because we relied on some neat tricks for processing I/O operations. However, keep in mind that most AST configurations are valid, and it's your processor that determines how you construct the AST. Be smart, as some configurations are easier to deal with than others!
This project provides an excellent opportunity to explore Unix system calls, process management, and parsing algorithms. Have fun building your shell!