Skip to content
Zoryan7Public

About

Minishell is a command-line interpreter written in C, designed to reproduce the behavior and features of Bash (posix). The goal of the project is to understand how a shell works internally by implementing command parsing, process creation, pipes, redirections, signal handling and environment management.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

This project has been created as part of the 42 curriculum by arouland and ymoumene.

Minishell

Description

Minishell is a command-line interpreter written in C and inspired by Bash. The goal of the project is to understand how a shell works internally by implementing command parsing, process creation, pipes, redirections, signal handling and environment management.

The program displays an interactive prompt, reads and interprets the user's commands, then executes built-ins or external programs. It supports quoted arguments, environment-variable expansion, command history, pipelines and the usual input and output redirections.

The bonus part adds logical operators, grouped commands and wildcard expansion.

Features

  • Interactive prompt and command history using GNU Readline.
  • Execution of commands found through PATH.
  • Execution through absolute and relative paths.
  • Single and double quote handling.
  • Expansion of environment variables such as $USER.
  • Expansion of the last command status through $?.
  • Pipelines using |.
  • Input redirection using <.
  • Output redirection using >.
  • Output redirection in append mode using >>.
  • Here-documents using <<.
  • Context-dependent handling of Ctrl-C, Ctrl-D and Ctrl-\.
  • Multiline input for unfinished quotes, operators and parentheses.

Built-in commands

  • echo with the -n option.
  • cd with a relative or absolute path.
  • pwd without options.
  • export without options.
  • unset without options.
  • env without options or arguments.
  • exit with an optional numeric argument and without options.

Bonus features

  • Logical AND with &&.
  • Logical OR with ||.
  • Grouped commands and subshells using ( and ).
  • Wildcard expansion using * in the current directory.

Requirements

  • Linux, macOS or another Unix-like environment.
  • A C compiler available as cc.
  • make.
  • GNU Readline and its development headers.

The Makefile compiles the project with -Wall -Wextra -Werror.

On Debian or Ubuntu, Readline can be installed with:

sudo apt install libreadline-dev

On macOS with Homebrew:

brew install readline

Instructions

Compilation

From the repository root:

make

This creates the minishell executable.

The Makefile also provides a bonus target, which creates minishell_bonus from the complete source set:

make bonus

Useful Makefile targets are:

make clean   # Remove object files
make fclean  # Remove object files, libraries and executables
make re      # Clean and rebuild the project

Execution

Launch the shell without arguments:

./minishell

The interactive prompt is then displayed:

minishell$

Run exit or press Ctrl-D on an empty prompt to leave the shell.

Usage examples

Built-ins and variable expansion

minishell$ pwd
minishell$ export PROJECT=minishell
minishell$ echo "Current project: $PROJECT"
minishell$ echo '$PROJECT is not expanded inside single quotes'
minishell$ unset PROJECT

Pipes and redirections

minishell$ printf "one\ntwo\nthree\n" | grep t | wc -l
minishell$ echo "first line" > output.txt
minishell$ echo "second line" >> output.txt
minishell$ cat < output.txt

Here-document

minishell$ cat << EOF
> Hello $USER
> EOF

Quoting the delimiter disables variable expansion inside the here-document:

minishell$ cat << 'EOF'
> $USER is kept as written
> EOF

Bonus syntax

minishell$ false || echo "the first command failed"
minishell$ true && echo "the first command succeeded"
minishell$ (echo first && echo second) | wc -l
minishell$ cd srcs/exec && echo *.c

Testing the shell

Commands can be compared with Bash to verify output and exit statuses:

# Run in Bash
bash
echo "$USER" | wc -c
echo $?

# Leave Bash, launch Minishell and repeat the same commands
exit
./minishell
echo "$USER" | wc -c
echo $?

The shell also accepts commands through standard input, which is useful for small smoke tests:

printf '%s\n' 'echo hello' 'pwd | wc -c' 'exit' | ./minishell

Useful cases to test include:

  • Empty input and whitespace-only input.
  • Quoted and unquoted environment variables.
  • Commands that exist and commands that do not exist.
  • Several consecutive pipes.
  • Redirections before and after command arguments.
  • Multiple here-documents.
  • Built-ins inside and outside pipelines.
  • Ctrl-C, Ctrl-D and Ctrl-\ at the prompt and during a command.
  • Logical operators, subshells and wildcard expansion.

Technical choices

  • Lexer and parser: the input is split into typed tokens before syntax validation. The parser then builds a linked list of command nodes containing arguments, redirections and the operator leading to the next command.

  • Execution: pipelines are created with pipe, fork and dup2. External commands are launched with execve. Built-ins that modify the shell state are executed in the parent process when they are not part of a pipeline.

  • Environment: environment variables are stored in a linked list so that export, unset and cd can update the shell state during execution. The special ? entry stores the latest exit status for $? expansion.

  • Signals: the prompt, child processes and here-documents use different signal configurations to reproduce Bash-like interactive behaviour.

  • Resource management: dynamically allocated memory and tracked file descriptors are registered in dedicated garbage-collector lists and released between commands or before a child process exits.

Project structure

.
├── includes
│   ├── libft
│   │   ├── ft_printf
│   │   ├── libft.h
│   │   └── Makefile
│   └── minishell.h
├── srcs
│   ├── built_in
│   ├── env
│   ├── exec
│   │   └── heredoc
│   ├── expand
│   │   └── wildcards
│   ├── free
│   ├── main_utils
│   ├── parsing
│   │   ├── check_syntax
│   │   └── lexer
│   ├── signals
│   └── main.c
├── Makefile
└── README.md
  • srcs/parsing/: tokenization, syntax validation and command construction.
  • srcs/expand/: quote removal, variable expansion and wildcard matching.
  • srcs/exec/: processes, pipelines, redirections and here-documents.
  • srcs/built_in/: implementation of the seven required built-ins.
  • srcs/env/: creation and modification of the shell environment.
  • srcs/signals/: signal handlers for each execution context.
  • srcs/free/: memory and file-descriptor cleanup.
  • includes/libft/: our recreation of standard c functions (42 requirements).

Resources

Use of artificial intelligence

Artificial intelligence was used as a support tool during the project for:

  • clarifying shell parsing, process and signal-handling concepts;
  • the creation of manual test cases;
  • reviewing and improving the project documentation.

About

Minishell is a command-line interpreter written in C, designed to reproduce the behavior and features of Bash (posix). The goal of the project is to understand how a shell works internally by implementing command parsing, process creation, pipes, redirections, signal handling and environment management.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages