A fully-featured Unix shell written in C — Epitech project (TEK1)
- Overview
- Features
- Architecture
- Getting Started
- Built-in Commands
- Shell Features
- Project Structure
- Testing
- Makefile Targets
42sh is a POSIX-inspired Unix shell implemented from scratch in C. It supports command execution, piping, redirections, environment management, history, aliases, tab-completion, and more — all without relying on readline or any external shell library.
This project was developed as part of the Epitech TEK1 shell programming module.
| Category | Description |
|---|---|
| Command execution | Fork/exec with full PATH resolution |
| Pipelines | Multi-stage | pipelines |
| Redirections | >, >>, <, << (heredoc) |
| Logic operators | && and || short-circuit evaluation |
| Command separator | ; sequential execution |
| History | Arrow key navigation, !-event expansion, persistent ~/.42sh_history |
| Aliases | Define, list, remove, and auto-expand command aliases |
| Tab completion | Context-aware completion for commands and file paths with interactive menu |
| Variable expansion | $VAR, $?, $HOME, etc. |
| Backtick expansion | `cmd` substitution |
| Globbing | * wildcard expansion |
| Quotes | Single ' and double " quote handling |
| Dynamic prompt | Colored prompt showing last exit status and current directory |
| Raw mode | Terminal raw-mode line editor (no external library) |
| Signal handling | Graceful handling of SIGINT, SIGSEGV, SIGFPE |
The shell is structured around a classic lexer → parser → AST → executor pipeline:
Input line
│
▼
Lexer (src/parsing/lexer.c)
│ token list
▼
Parser / AST (src/parsing/tree.c)
│ ast_node_t tree
▼
Executor (src/execution/exec_ast.c)
├── Builtins (src/execution/handle_builtins.c)
├── Pipes (src/execution/exec_pipe.c)
└── Redirs (src/execution/exec_redir.c)
Pre-execution expansions (history events, backticks, variables, aliases, globs) are applied before the AST is executed.
- GCC or a compatible C compiler (
epiclangalias used in the Makefile) makelibncurses-dev(for terminal handling)libcriterion-dev(optional, for unit tests)gcovr(optional, for coverage)
# Clone the repository
git clone <your-repo-url>
cd 42sh
# Set up git hooks (recommended)
make setup
# Build the library and binary
makeThe binary 42sh will be generated in the project root.
# Interactive mode
./42sh
# Non-interactive / script mode
echo "ls -la" | ./42sh| Command | Description |
|---|---|
cd [path] |
Change directory; supports ~, - (previous dir), and CDPATH |
env |
Print all exported environment variables |
setenv VAR [value] |
Set (or display) an environment variable |
unsetenv VAR ... |
Remove one or more environment variables |
set |
List all variables (exported and local) |
unset VAR ... |
Remove local shell variables |
alias [name[=value]] |
Define or list aliases |
unalias name ... |
Remove aliases |
which cmd |
Show the resolved path of a command |
where cmd |
Show all locations of a command (builtins + PATH) |
repeat N cmd |
Execute a command N times |
exit |
Exit the shell |
- Up/Down arrow keys navigate command history.
!n— run the nth history event.!prefix— run the last command starting withprefix.!!— repeat the last command.- History is saved to
~/.42sh_historyon exit and loaded on start (up to 500 entries).
Press Tab to auto-complete:
- Commands — searches
PATHfor matching executables and built-ins. - Paths — completes file and directory names.
- When multiple matches exist, an interactive grid menu appears for selection.
[OK]~/projects/42sh $> _
[KO]~/projects/42sh $> _ # red when last command failed
[OK](green) or[KO](red) reflects the exit status of the last command.- Current directory is shown relative to
$HOMEusing~notation.
echo $HOME
echo $?
echo `whoami`ls *.c
cat src/**/*.c42sh/
├── main.c # Entry point
├── Makefile
├── include/
│ ├── my.h # All function prototypes
│ ├── struct_mysh.h # All type / struct definitions
│ └── macros.h # ANSI color macros
├── src/
│ ├── core/ # Main shell loop (mysh.c)
│ ├── parsing/ # Lexer, AST builder, quote/inhibitor handling
│ ├── execution/ # AST executor, pipes, redirections, globbing
│ ├── builtins/ # cd, setenv, alias, which, where, repeat, set…
│ ├── environment/ # Env linked-list management, variable expansion
│ ├── history/ # History storage, navigation, event expansion
│ ├── completion/ # Tab-completion engine and menu
│ ├── alias/ # Alias tools
│ ├── termios/ # Raw-mode terminal enable/disable
│ └── bonus/ # Dynamic prompt, greeting screen
└── lib/
└── my/ # Custom libc reimplementations (my_strlen, etc.)
Unit tests use the Criterion testing framework.
# Run tests + coverage summary
make tests_run
# Generate an HTML coverage report
make coverage| Target | Description |
|---|---|
make |
Build libmy.a and 42sh binary |
make clean |
Remove object files |
make fclean |
Remove objects, binary, and library |
make re |
Full rebuild (fclean + all) |
make tests_run |
Compile and run unit tests with coverage |
make coverage |
Generate HTML coverage report |
make setup |
Configure git hooks |
make help |
Display help menu |
- Mathis — Epitech TEK1 — 2025/2026
- Loan — Epitech TEK1 — 2025/2026
- Matthis — Epitech TEK1 — 2025/2026
- Safwan — Epitech TEK1 — 2025/2026
- Victor — Epitech TEK1 — 2025/2026