Skip to content

Robust Unix shell implementation with complete lexer-parser-executor pipeline. Features built-in commands, pipes, redirections, environment variables, wildcards, and signal handling.

License

Notifications You must be signed in to change notification settings

TheValiant/valiantshell

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

valiantshell

A robust, POSIX-compliant Unix shell implementation featuring a complete lexer-parser-executor pipeline architecture. Built to be resilient against edge cases and malformed input.

Overview

valiantshell is a fully-featured Unix shell written in C as part of the 42 School curriculum. The project reimplements core bash functionality with emphasis on robustness, memory safety, and proper signal handling. The shell handles complex command pipelines, redirections, environment variable expansion, and built-in commands while maintaining compatibility with standard shell behavior.

The architecture follows a clean separation of concerns with distinct modules for tokenization, parsing into an abstract syntax tree (AST), variable expansion, and execution. This design enables comprehensive error handling at each stage and makes the codebase maintainable and extensible.

Features

  • Command Execution: Execute external programs with PATH resolution and argument handling
  • Pipeline Support: Chain multiple commands with | pipes for data streaming
  • I/O Redirections: Full support for <, >, >>, and << (here-documents)
  • Environment Variables: Expansion of $VAR, $? (exit status), and quoted variables
  • Built-in Commands: Native implementation of echo, cd, pwd, export, unset, env, exit
  • Wildcard Expansion: Glob pattern matching with * for filename expansion
  • Signal Handling: Proper handling of Ctrl+C, Ctrl+D, and Ctrl+\ with context awareness
  • Quote Processing: Support for single quotes (literal) and double quotes (with expansion)
  • History: Command history with readline integration
  • Error Handling: Graceful handling of syntax errors, permission issues, and edge cases

Technical Highlights

  • Architecture: Four-stage pipeline: Lexer → Parser → Expander → Executor
  • Memory Safety: Zero memory leaks verified with Valgrind and AddressSanitizer
  • Robustness: Extensive fuzzing and edge case testing for stability
  • POSIX Compliance: Behavior matches bash for standard shell operations
  • Signal Safety: Async-signal-safe signal handlers with proper terminal control

Architecture

┌─────────────────────────────────────────────────────────────────┐
│                       Input (readline)                          │
│                   "ls -la | grep .c > out.txt"                  │
└─────────────────────────────────────────────────────────────────┘
                                │
                                ▼
┌─────────────────────────────────────────────────────────────────┐
│                          LEXER                                   │
│            Tokenization with quote and escape handling           │
│         ["ls", "-la", "|", "grep", ".c", ">", "out.txt"]        │
└─────────────────────────────────────────────────────────────────┘
                                │
                                ▼
┌─────────────────────────────────────────────────────────────────┐
│                          PARSER                                  │
│         Build Abstract Syntax Tree from token stream             │
│                                                                  │
│                           [PIPE]                                 │
│                          /      \                                │
│                    [CMD ls]   [REDIRECT >]                       │
│                       |            |                             │
│                   [-la]       [CMD grep]                         │
│                                   |                              │
│                               [.c]                               │
└─────────────────────────────────────────────────────────────────┘
                                │
                                ▼
┌─────────────────────────────────────────────────────────────────┐
│                        EXPANDER                                  │
│          Variable expansion, wildcard glob, quote removal        │
│              $HOME → /home/user, *.c → [file1.c, file2.c]       │
└─────────────────────────────────────────────────────────────────┘
                                │
                                ▼
┌─────────────────────────────────────────────────────────────────┐
│                        EXECUTOR                                  │
│     Fork processes, setup pipes/redirects, execute commands      │
│              Handle built-ins directly, externals via execve     │
└─────────────────────────────────────────────────────────────────┘

Built-in Commands

Command Description
echo Display text with -n flag support for no newline
cd Change directory with ~, -, and path support
pwd Print current working directory
export Set or display environment variables
unset Remove environment variables
env Display all environment variables
exit Exit the shell with optional exit code

Supported Operators

Operator Description
| Pipe output from left command to right command
< Redirect input from file
> Redirect output to file (overwrite)
>> Redirect output to file (append)
<< Here-document (read input until delimiter)
$VAR Environment variable expansion
$? Exit status of last command
* Wildcard glob pattern matching
'...' Single quotes (literal string, no expansion)
"..." Double quotes (allows $ expansion)

Requirements

  • Operating System: Linux, macOS
  • Compiler: GCC or Clang with C99 support
  • Libraries: readline, ncurses
  • Build Tools: GNU Make

Installing Dependencies

Ubuntu/Debian:

sudo apt-get install libreadline-dev libncurses-dev

macOS (Homebrew):

brew install readline

Installation and Usage

Building

git clone --recursive https://github.com/TheValiant/valiantshell.git
cd valiantshell
make

Running

./minishell

Example Session

$ ./minishell
valiantshell$ echo "Hello, World!"
Hello, World!
valiantshell$ export NAME=User
valiantshell$ echo "Welcome, $NAME"
Welcome, User
valiantshell$ ls -la | grep ".c" | wc -l
42
valiantshell$ cat << EOF > greeting.txt
> Hello from here-doc!
> EOF
valiantshell$ cat greeting.txt
Hello from here-doc!
valiantshell$ cd /tmp && pwd
/tmp
valiantshell$ exit

Supported Features vs Bash

Feature valiantshell bash
Pipes Supported Supported
Redirections (<, >, >>) Supported Supported
Here-documents (<<) Supported Supported
Environment variables Supported Supported
Exit status ($?) Supported Supported
Wildcards (*) Supported Supported
Single and double quotes Supported Supported
Built-in commands Supported Supported
Signal handling Supported Supported
Command history Supported Supported
Logical operators (&&, ||) Not implemented Supported
Subshells () Not implemented Supported
Background jobs (&) Not implemented Supported
Scripting Not implemented Supported

Testing

The shell has been extensively tested with:

  • Edge cases for quote handling and escape sequences
  • Memory leak detection with Valgrind
  • AddressSanitizer for memory safety
  • Fuzzing with various input generators
  • Comparison testing against bash behavior

Learning Outcomes

This project provided deep experience in:

  • Process management with fork, execve, pipe, dup2
  • File descriptor manipulation and I/O redirection
  • Signal handling in multi-process environments
  • Lexer and parser design for language processing
  • Memory management in long-running applications
  • Terminal control and readline integration

Project Structure

valiantshell/
├── src/
│   ├── main.c                  # Entry point
│   ├── minishell.h             # Main header
│   ├── builtins/               # Built-in command implementations
│   ├── destroyers/             # Memory cleanup functions
│   ├── execution/              # Command execution and piping
│   ├── exit_metadata/          # Exit status management
│   ├── expanders/              # Variable and wildcard expansion
│   ├── history/                # Command history handling
│   ├── initializers/           # Shell initialization
│   ├── input_fortification/    # Input validation
│   ├── parsing/                # Tokenizer and AST builder
│   ├── signals/                # Signal handlers
│   ├── string_tools/           # String utilities
│   └── syscall_wrappers/       # Safe syscall wrappers
├── libft/                      # Custom C library
├── Makefile
└── README.md

Acknowledgments

  • 42 School for the project specifications
  • GNU Bash documentation for reference behavior
  • The readline library maintainers

License

This project is available under the MIT License. See LICENSE for details.


Note: This project was completed as part of the 42 School curriculum, which emphasizes peer-to-peer learning and project-based education in software engineering.

About

Robust Unix shell implementation with complete lexer-parser-executor pipeline. Features built-in commands, pipes, redirections, environment variables, wildcards, and signal handling.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •