42sh is a custom shell implementation built as part of the 42 school curriculum. It aims to replicate and extend the functionality of standard POSIX shells while supporting advanced features such as job control, command substitution, and custom parsing.
- Command execution (builtins and external commands)
- Argument parsing with proper tokenization
- Full edition of command line
- History managment
- Expansions (described below)
- Control flows (for, if, until, while, case, function)
- Handling of environment variables
- Handling of exit statuses
- Pipes (
|
): Connect command outputs to inputs. - I/O Redirections (
<
,>
,>>
,2>
,&>
): Manage input and output streams. - Logical Operators (
&&
,||
): Conditional execution based on exit codes. - Subshells (
(...)
): Execute commands in a separate process. - Command Grouping (
{ ... }
): Execute multiple commands in the current shell.
- Variable Expansion (
$VAR
) (Advanced formats supported) - Positional Parameters (
$1
,$2
, etc.) - Arithmetic Expansion (
$((expr))
) - Command Substitution (
$(command)
) (No support for legacy`command`
syntax) - History Expansion (
!!
,!$
,!n
) - Pattern Matching (
*
,?
,[...]
, POSIX character classes) - Tilde Expansion (
~
,~user
) - Process Substitution (
<(command)
,>(command)
)
- Foreground and Background Execution (
&
,fg
,bg
) - Listing Jobs (
jobs
) - Signal Handling: Handles all signals properly
- Proper Process Group Management
alias
- Manage command aliasesbg
- Resume a job in the backgroundcd
- Change directoryecho
- Print to stdoutenv
- Display environment variablesexit
- Exit the shellexport
- Set environment variablesfc
- Fix command (history manipulation)fg
- Resume a job in the foregroundhash
- Manage command lookup hash tablejobs
- Display active jobspwd
- Print working directoryreturn
- Return from a functionset
- Set shell optionstest
- Evaluate expressionstype
- Display command typeunalias
- Remove command aliasesunset
- Unset environment variablesulimit
- Set or display resource limitswait
- Wait for background jobs to finish
42sh includes a custom readline library remake that supports:
- Full command-line editing
- Readline shortcuts (e.g.,
Ctrl+A
,Ctrl+E
, etc.) - Vi mode (
set -o vi
to enable full vi-like editing)
- The shell loads a configuration file (
~/.42shrc
) at startup. - Users can define aliases and customize their prompt in this file.
- Supports full prompt customization using all syntax elements described in the
Controlling the Prompt
section of Bash's manual (PS1
andPS2
customization).
- Fully supports POSIX control structures, including:
if
,while
,for
,until
,case
,switch
- Function definitions and execution
42sh uses a LALR(1) parser for parsing complex shell grammar. Since parser generators like Bison or Yacc were not allowed, the parser was implemented manually. The automaton was generated using jsmachines' project, and the C code was dynamically generated from the automaton using Python.
Additionally, we implemented our own tiny regex library to ease parsing. The API is:
regex_match(format, target)
Supported operators:
'^ ? + * [^a-z] $'
- Lexing & Parsing: The command line is tokenized and parsed into an AST.
- Expansion & Substitution: Variables, command substitution, and arithmetic expressions are expanded before execution.
- Execution Dispatch:
- Built-in commands are executed directly.
- External commands are forked and executed using
execve
.
- Job Control:
- Foreground and background processes are managed properly.
- Process groups and signals are handled to ensure correct job behavior.
- Redirections & Pipes:
- File descriptors are modified as needed before execution.
- Pipes are created dynamically between commands in a pipeline.
- Uses a custom garbage collector to handle memory allocations dynamically.
- Implements a growable arena allocator to efficiently manage memory usage.
- Avoids memory leaks through automatic deallocation of structures after execution.
- Includes a header library for generic vector creation, making it easier to manage dynamic arrays.
# Clone the repository
git clone https://github.com/BrimVeyn/42sh.git
cd 42sh
# Build the shell
make
# Run the shell
./42sh
# Run tests
make test # Runs more than 1100 tests to validate the functionalities described in this README
42sh includes a dedicated test suite that ensures correctness across all functionalities. The tester consists of:
- Backend: Implemented in Express.js
- Frontend: Built with React
- Testing Execution: When running
make test
, Docker Compose is used to:- Build and launch the test environment
- Run the tests using a multithreaded program
- Provide a link to visualize test outputs in a web browser
- LALR(1) Parser Generator
- GNU Bash Manual
- POSIX Specification
- Stanford CS143
- Crafting Interpreters
- YouTube: Bash Parsing Overview
- YouTube: Shell Job Control
- Efficient C Code Optimization
- Tiny Garbage Collector
- Job Control and Termios
- Beautiful Code - Princeton
- GNU Libc Job Control
MIT License
- Byan VAN PAEMEL
- Nathan BARDAVID