Skip to content

Latest commit

History

186 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

minishell

A minimal UNIX shell built in C as part of the 42 School curriculum.
It reproduces the core behaviour of bash, supporting interactive input, environment variable expansion, quoting rules, pipes, redirections, heredoc, and the standard set of built-in commands.

Authors:aragragu · ykasmi


Table of Contents


Requirements

DependencyNotes
cc (C compiler)Compiled with -Wall -Wextra -Werror
readlineProvides interactive line editing and history
macOS (recommended)Makefile paths default to Homebrew readline (~/.brew/opt/readline)

macOS users: The Makefile expects a user-local Homebrew installation at ~/.brew (i.e. /Users/$USER/.brew/opt/readline). If you installed Homebrew system-wide (the standard location is /opt/homebrew on Apple Silicon or /usr/local on Intel), update CFLAGS and LDFLAGS accordingly.
Linux users: Update CFLAGS and LDFLAGS in the Makefile to point to your system's readline installation (usually /usr).


Build

# Compile the binary
make
# Remove object files only
make clean
# Remove object files and the binary
make fclean
# Full rebuild
make re

The resulting binary is named minishell and placed in the repository root.


Running

./minishell

The shell does not accept file arguments – it runs in interactive mode only.


Features

Prompt

Displays an interactive prompt on every new line:

➜ (minishell)✗ 

Command History

Previous commands are accessible via the ↑ / ↓ arrow keys, powered by the GNU readline history library.

Environment Variable Expansion

SyntaxExpands to
$VARValue of the environment variable VAR
$?Exit status of the most recently executed command

Variable expansion is performed inside double-quoted strings and in unquoted words.

➜ (minishell)✗ echo$HOME
/Users/aragragu
➜ (minishell)✗ echo$?
0

Quoting

Quote typeBehaviour
'single quotes'Preserves the literal value of every character; no expansion takes place
"double quotes"Preserves literal values except for $VAR / $? expansion
➜ (minishell)✗ echo'$HOME'$HOME
➜ (minishell)✗ echo"$HOME"
/Users/aragragu

Pipes

Multiple commands can be chained with |. Each command's standard output is connected to the next command's standard input.

➜ (minishell)✗ ls -la | grep .c | wc -l

An arbitrary number of pipes is supported.

Redirections

OperatorDescription
< fileRedirect standard input from file
> fileRedirect standard output to file (truncate)
>> fileRedirect standard output to file (append)
<< DELIMHeredoc – read input until DELIM is encountered
➜ (minishell)✗ echo hello > out.txt
➜ (minishell)✗ cat < out.txt
➜ (minishell)✗ echo world >> out.txt

Heredoc

A heredoc reads lines from the terminal until the delimiter is matched:

➜ (minishell)✗ cat <<EOF> line one> line two $HOME> EOFline oneline two /Users/aragragu

Variable expansion ($VAR, $?) is performed inside the heredoc body.
Pressing Ctrl+C during heredoc input cancels it without executing the command.

Built-in Commands

These commands are executed directly by the shell without forking a child process:

CommandDescription
echo [-n] [args…]Print arguments to stdout; -n suppresses the trailing newline
cd [path]Change the current working directory; updates PWD and OLDPWD
pwdPrint the current working directory
export [name[=value]…]Set or declare environment variables
unset [name…]Remove environment variables
envPrint all exported environment variables
exit [n]Exit the shell with optional exit code n

Signals

SignalInteractive promptDuring command execution
Ctrl+C (SIGINT)Displays a new prompt on a new lineSends SIGINT to the foreground process group
Ctrl+\ (SIGQUIT)IgnoredSends SIGQUIT to the foreground process group (exits with code 131)
Ctrl+D (EOF)Exits the shell

Limitations

  • No logical operators&& and || are not implemented (the corresponding tokens are defined but not handled in the execution engine).
  • No subshell support – parenthesised expressions (cmd) are not implemented.
  • Interactive mode only – the shell cannot run a script file passed as an argument.
  • User-local Homebrew path – the Makefile hard-codes readline to ~/.brew/opt/readline (user-local Homebrew). Users with a standard Homebrew installation (/opt/homebrew or /usr/local) or on Linux must edit CFLAGS/LDFLAGS before compiling.
  • No job control – background execution (&), fg, bg, and jobs are not supported.
  • No wildcard globbing – patterns like *.c are passed literally to commands.

Project Structure

minishell/
├── Makefile # Build rules
├── minishell.h # Shared header: all structs, enums, and prototypes
│
├── parsing/ # Lexer, parser, and pre-execution processing
│ ├── main.c # Entry point – initialisation and the main read loop
│ ├── token.c … token4.c # Tokeniser: breaks raw input into a linked list of tokens
│ ├── expanding.c … expanding5.c # Variable expansion ($VAR, $?)
│ ├── redirections.c … redirections4.c # Redirection token handling
│ ├── syntax_error.c … syntax_error3.c # Syntax validation and error reporting
│ ├── cmd.c … cmd4.c # Builds the command list (t_cmd) from the token list
│ ├── signals.c # Signal handlers and exit-status management
│ ├── split.c # Custom string splitter
│ ├── libft.c … libft6.c # Re-implemented standard C library functions
│ └── ft_itoa.c # Integer-to-string conversion
│
├── execu/ # Execution engine and built-ins
│ ├── ft_excu.c / ft_excu2.c # Core execution logic (fork, exec, pipes)
│ ├── ft_redi.c # Applies redirections at execution time
│ ├── ft_cd.c # cd built-in
│ ├── ft_echo.c # echo built-in
│ ├── ft_env.c # env built-in
│ ├── ft_exit.c # exit built-in
│ ├── ft_export.c / ft_export_norm.c / ft_export_norm2.c # export built-in
│ ├── ft_pwd.c # pwd built-in
│ ├── ft_unset.c # unset built-in
│ └── ft_utils1.c … ft_utils8.c # Shared utility functions
│
└── ft_printf/ # Minimal custom printf implementation
├── ft_printf.c
└── ft_utils.c

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages