A minimal Unix shell implementation created as part of the 42 school curriculum. This project recreates a simplified version of bash, implementing core shell functionalities including command execution, piping, redirections, and built-in commands.
- About
- Features
- Installation
- Usage
- Built-in Commands
- Project Structure
- Technical Details
- Contributors
Minishell is a 42 school project that challenges students to create their own shell. The goal is to understand how a shell works by implementing one from scratch, dealing with processes, file descriptors, signals, and memory management while adhering to strict coding standards (Norminette).
This project provides hands-on experience with:
- Process creation and management
- Inter-process communication (pipes)
- File descriptor manipulation
- Signal handling
- Memory management
- Parsing and tokenization
- Interactive prompt with customizable display
- Command execution with absolute and relative paths
- Environment variable expansion (
$VAR,$?) - Exit status tracking
- Command history (using readline)
- Quote handling (single
'and double"quotes)
<- Input redirection>- Output redirection (truncate)>>- Output redirection (append)<<- Heredoc (read until delimiter)
- Multiple pipes support:
cmd1 | cmd2 | cmd3 - Proper file descriptor handling
Ctrl+C- Interrupt current commandCtrl+D- Exit shell (EOF)Ctrl+\- Quit signal (ignored in interactive mode)
- GCC or Clang compiler
- Make
- Readline library
On Ubuntu/Debian:
sudo apt-get install libreadline-devOn macOS:
brew install readline- Clone the repository:
git clone https://github.com/codam-minishell-team/minsh.git
cd minsh- Compile the project:
make- Run the shell:
./minishellmake- Compile the projectmake clean- Remove object filesmake fclean- Remove object files and executablemake re- Recompile the project
Simply run the executable:
./minishellYou'll be greeted with a prompt showing your username and hostname:
user@hostname:~$
Run simple commands:
minishell$ ls -la
minishell$ echo "Hello, World!"
minishell$ pwdUse pipes:
minishell$ ls -l | grep minishell | wc -l
minishell$ cat file.txt | grep pattern | sort | uniqRedirections:
minishell$ echo "test" > output.txt
minishell$ cat < input.txt
minishell$ ls -l >> logfile.txtHeredoc:
minishell$ cat << EOF
> line 1
> line 2
> EOFEnvironment variables:
minishell$ echo $HOME
minishell$ echo $?
minishell$ export MY_VAR=hello
minishell$ echo $MY_VARQuotes:
minishell$ echo 'single quotes: $HOME is not expanded'
minishell$ echo "double quotes: $HOME is expanded"Minishell implements the following built-in commands:
echo [-n] [string ...]Display a line of text. The -n option omits the trailing newline.
cd [directory]Change the current directory. If no argument is provided, changes to the home directory.
pwdPrint the current working directory.
export [NAME[=VALUE] ...]Set or display environment variables.
unset [NAME ...]Remove environment variables.
envDisplay all environment variables.
exit [n]Exit the shell with optional exit status n.
This project follows a structured directory layout to maintain clarity and organization. Below is a breakdown of each directory and its purpose:
βββ build intermediate build files (e.g., *.o) created by make
βββ docs project documentation
βββ includes header files
βββ libs third-party libraries
βββ scripts scripts for setup and other tasks
βββ sources C source files
βββ tests contains test files
βββ .gitignore specifies files and directories to be ignored by git
βββ Makefile build instructions for the project
βββ README.md project overview and documentation
- build: Stores intermediate build files, typically object files (
*.o), generated during the build process. - docs: Contains project documentation, including design documents, guides, or API references.
- includes: Holds header files (
*.h), defining interfaces and shared declarations. - libs: Contains third-party libraries that the project depends on.
- scripts: Includes utility scripts for setup, automation, or other project-related tasks.
- sources: Source code files, primarily C files (
*.c). This is where the application's logic resides. - tests: Test files for validating project functionality.
- .gitignore: Defines files and folders that should be ignored by Git to keep the repository clean.
- Makefile: Provides build commands and automates compilation steps.
- README.md: Offers an overview of the project, including setup instructions, usage, and contribution guidelines.
Feel free to explore the directories for more details on each component of the project.
The shell uses a multi-stage parsing approach:
- Scanner - Performs lexical analysis
- Tokenizer - Converts input into tokens
- Evaluator - Processes quotes, variables, and special characters
- Syntax Tree Builder - Constructs command pipeline structure
- All dynamically allocated memory is properly freed
- Valgrind-clean implementation (no memory leaks)
- Custom cleanup functions for complex data structures
Signals are handled differently based on execution context:
- Interactive mode
- Command execution
- Heredoc input
- Custom implementation of
getenv,setenv, andunsetenv - Environment variable expansion in double quotes
- Exit status accessible via
$?
Roman Zvir - GitHub Valeriia Krasnianska β GitHub School 42 Project
Note: This project is part of the 42 school curriculum and is intended for educational purposes. It implements a subset of bash functionality and may not include all features of a production shell.