Skip to content

Latest commit

 

History

History
183 lines (137 loc) · 4.81 KB

File metadata and controls

183 lines (137 loc) · 4.81 KB

Simple Shell (hsh)

Grade Language Norminette Badge Library Workflow Status Norminette Status GitHub release (latest by date including pre-releases) GitHub tag (latest SemVer) Visits Lines of code GitHub

A UNIX command interpreter written in C.

This project is a lightweight shell inspired by sh behavior and educational shell projects such as minishell. It supports command execution, builtins, PATH resolution, environment management, command chaining, aliases, variable expansion, and persistent history.

Table of Contents

  1. About
  2. Features
  3. Supported Builtins
  4. Project Structure
  5. How It Works
  6. Build
  7. Usage
  8. Examples
  9. Limitations
  10. Authors

About

hsh runs in:

  • Interactive mode (prompt shown as $ ).
  • Non-interactive mode (commands from a file or pipe).

At startup, it loads environment variables into an internal linked list and restores history from ~/.simple_shell_history.

Features

  • Execute external commands via fork() + execve().
  • Search executables in PATH.
  • Handle script input: ./hsh script_file.
  • Builtins for shell control and environment management.
  • Command chaining with:
    • cmd1 ; cmd2
    • cmd1 && cmd2
    • cmd1 || cmd2
  • Alias creation and lookup (alias name='value').
  • Variable replacement:
    • $? (last exit status)
    • $$ (current process id)
    • $NAME (environment variable)
  • Basic comment handling (# begins a comment when preceded by start/space).
  • Persistent history written on shell exit.

Supported Builtins

  • exit [status]
  • env
  • setenv NAME VALUE
  • unsetenv NAME
  • cd [dir]
  • history
  • alias [name[=value] ...]
  • help (placeholder output in current implementation)

Project Structure

The repository has been organized with top-level folders for growth and maintainability:

.
├── assets/                # Static assets (images, diagrams)
├── docs/                  # Extra documentation
├── include/               # Header files
├── src/                   # C source files
├── Makefile               # Build automation
└── README.md

How It Works

High-level command flow:

  1. Read a line from input.
  2. Remove comments and store history entry.
  3. Split chained commands (;, &&, ||).
  4. Tokenize into argv.
  5. Resolve aliases and variables.
  6. Execute builtin or resolve command path.
  7. Fork and execute external command.
  8. Collect status and continue loop.

Core files:

  • src/main.c: entry point, script file handling.
  • src/shell_loop.c: main loop, builtin dispatch, command execution.
  • src/parser.c: command detection and PATH resolution.
  • src/getLine.c: custom line reader and chain buffer logic.
  • src/vars.c: chaining checks, alias/variable replacement.
  • src/history.c: history read/write and numbering.
  • src/environ.c, src/getenv.c: environment list and env operations.

Build

Compile with make:

make

Equivalent manual compile command:

gcc -Wall -Werror -Wextra -pedantic -std=gnu89 -Iinclude src/*.c -o hsh

Clean build artifacts:

make clean

Usage

Run interactive shell:

./hsh

Run a script file:

./hsh path/to/script.sh

Run non-interactively from pipe:

echo "env" | ./hsh

Examples

Command chaining:

ls -la ; pwd

Conditional execution:

mkdir test && cd test || echo "mkdir failed"

Alias:

alias ll='ls -la'
ll

Variables:

echo $$
echo $?
echo $HOME

Limitations

  • No full quote parsing engine (single/double quote semantics are limited).
  • No pipes (|) between processes in the current implementation.
  • No redirections (>, <, >>) in the current implementation.
  • help builtin is not fully implemented.

Authors

See repository contributors for the current author list.