Minishell
[42-Cursus] Minishell is a minimalist shell implementation written in C, designed to mimic basic functionalities of a Unix shell like Bash.
Install / Use
/learn @OliverKingz/MinishellREADME

[42-Cursus] Minishell is a minimalist shell implementation written in C, designed to mimic basic functionalities of a Unix shell like Bash. This project focuses on understanding processes, file descriptors, and shell operations such as command execution, redirections, pipes, and signal handling.
<div align="center">
Keywords
- Shell
- Process Management
- File Descriptors
- Redirections
- Pipes
- Signal Handling
- Built-in Commands
- Environment Variables
Index
- Overview
- Features
- Requirements
- Flowchart
- How to Run
- Parser Example
- Summarized Tests
- Detailed Tests
- What I Learned
- Authors
- Acknowledgments
Overview
Minishell is a simplified Unix shell implementation created as part of the 42 Cursus curriculum. The project aims to deepen understanding of core operating system concepts such as process management, file descriptors, and shell operations. Minishell supports basic shell functionalities like command execution, input/output redirection, pipes, and environment variable management. It also handles signals like ctrl-C, ctrl-D, and ctrl-\ similar to Bash.
The project is written in C and adheres to strict coding standards, ensuring no memory leaks and robust error handling. Minishell is a great way to explore the inner workings of a shell and gain hands-on experience with low-level system programming.
Features
- Command Execution: Executes commands based on the
PATHvariable or using relative/absolute paths. - Input/Output Redirection: Supports
<,>,<<, and>>for input/output redirection. - Pipes: Implements pipes (
|) to connect the output of one command to the input of another. - Environment Variables: Expands environment variables (e.g.,
$HOME) and$?for the exit status of the last command. - Signal Handling: Handles
ctrl-C,ctrl-D, andctrl-\as in Bash. - Built-in Commands: Implements built-ins like
echo,cd,pwd,export,unset,env, andexit. - Quoting: Handles single (
') and double (") quotes to prevent interpretation of metacaracters.
Bonus Features (Not implemented)
- Logical Operators: Supports
&&and||with parentheses for priority. - Wildcards: Implements
*wildcard for the current directory.
Requirements
- The project must be written in C and follow the 42 Norm.
- No memory leaks are allowed.
- The shell must handle signals correctly and manage file descriptors properly.
- The Makefile must compile the project with
-Wall,-Werror, and-Wextraflags. - The shell must support the mandatory features listed in the subject.
Flowchart
Below is the flowchart representing the architecture and flow of the Minishell project.
Note: This flowchart is an approximation and may not represent the exact implementation details.
graph TB
direction TB
subgraph "User Interface"
Input["Input Handler
(main, input, shell)"]:::black
end
subgraph "Processing Input"
Lexer["Lexer
(lexer)"]:::green
Expansion["Expansion
(expansion_security, expansion_utils, expansion_var)"]:::green
Parser["Parser
(parser_tokenize, parser_utils, token_list, token_utils)"]:::green
end
subgraph "Execution"
subgraph "Redirection Handling"
Redirection["Input & Output
(redirections)"]:::turquoise
Heredocs["Heredocs
(heredoc, heredoc2)"]:::turquoise
end
subgraph "Command Handling"
Builtin["Builtin Commands
(builtin, bi_cd, bi_echo, bi_env, bi_exit, bi_export, bi_pwd, bi_unset)"]:::blue
External["External Commands"]:::blue
end
Command["Command Structure
(cmd, cmd_exit)"]:::dark_blue
Executor["Executor
(execution)"]:::black
end
subgraph "Foundational Utilities"
Utility["Utilities
(utils, utils2, type_check)"]:::orange
Libft["Libft
(ft_*)"]:::orange
Debug["Debug prints
(prints)"]:::orange
end
subgraph "System Interactions"
Env["Environment
(env, env_list, env_var)"]:::red
Signal["Signal Handler
(signal)"]:::red
end
Env --> Input & Expansion & Command & Heredocs
Signal --> Input & Heredocs & Executor
Input -->|"input line"| Lexer
Lexer -->|"validated input"| Expansion
Expansion -->|"expanded vars"| Parser & Heredocs
Parser -->|"tokenized input"| Heredocs & Redirection
Heredocs --> Redirection
Heredocs -->|"prepared heredocs"| Builtin & External & Command
Redirection -->|"prepared redirections"| Builtin & External & Command
Builtin -->|"built-in execution"| Command
External -->|"external execution"| Command
Command -->|"execution context"| Executor
Executor -->|"wait for input after execution"| Input
classDef white fill:#ffffff,stroke:#000000,stroke-width:1px,color:#000000;
classDef black fill:#000000,stroke:#ffffff,stroke-width:1px,color:#ffffff;
classDef green fill:#80ff80,stroke:#008000,stroke-width:1px,color:#004d00;
classDef blue fill:#80bfff,stroke:#004080,stroke-width:1px,color:#00264d;
classDef dark_blue fill:#ffffff,stroke:#004080,stroke-width:1px,color:#00264d;
classDef turquoise fill:#80ffff,stroke:#008080,stroke-width:1px,color:#004d4d;
classDef orange fill:#ffcc80,stroke:#ff8000,stroke-width:1px,color:#663300;
classDef red fill:#ff8080,stroke:#800000,stroke-width:1px,color:#4d0000;
How to Run
-
Clone this repository:
git clone [repository-url] cd minishell -
Compile the project:
make -
Run the shell:
./minishell
Parser Example
Input:
cat < in | grep "Hi bye" | grep 'H' > out | cat >> final_out -e
Tokenizer result and classification:
"cat": command"<": redir_in"in": file_path"|": op_pipe"grep": command"Hi bye": argument"|": op_pipe"grep": command"H": argument">": redir_out"out": file_path"|": op_pipe"cat": command">>": redir_append"final_out": file_path"-e": argument
Recomendations for Testing and Summarized Tests
time: Usetimeto measure how long commands take to execute in Minishell, especially with commands likesleep. This helps confirm correct handling of concurrency and pipes.env: Runenvinside Minishell to verify that environment variables (likePATH) are correctly inherited and available to child processes.env -i: Launch Minishell with an empty environment usingenv -i ./minishellto test its behavior when no environment variables are set.echo $?: After running commands, useecho $?to check if Minishell correctly sets and updates the exit status.which ls: Usewhichwithin Minishell to confirm that the shell can locate executables using the currentPATH.cp /usr/bin/ls .: Copy a binary likelsto the current directory and run it from Minishell to test support for relative and absolute paths.unset PATHorexport PATH="": Remove or clear thePATHvariable in Minishell to ensure it handles missingPATHgracefully (e.g., only absolute/relative paths work).valgrind --trace-children=yes --track-fds=yes: Run Minishell under Valgrind with these flags to check for memory leaks and proper file descriptor management, including child processes.strace: Usestraceto debug Minishell’s system calls and signal handling.strace -f ./minishell: Track all child processes created byfork().strace -e trace=execve ./minishell: Filter and display only command execution (execve) calls.strace -c ./minishell: Get a summary of all system calls and time spent on each.
| Input Command | Description |
| ------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
| ""ec''ho"" "Welcome to our 'minishell', I am $USER" | Prints 'Welcome to our 'minishell', I am <USER>' with mixed quotes.
