Skip to content

Latest commit

 

History

19 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

myShell — A Unix Shell in C

Part of Old-School-Projects Live site

A Unix-like command interpreter written from scratch in C: no parser generator, no readline, nothing beyond libc and ncurses. It folds shell operators into a binary execution tree, then walks that tree with fork, pipe, dup2 and execve.

Historical project, written in 2018 during the Epitech curriculum and preserved as it was. Documentation rewritten in 2026.

Interactive shell session

Architecture

input → line editing → tokenisation → operator tree → fd wiring → fork/execve → status

Parsing is not a lexer/parser/AST pipeline. Each node holds the raw text it still has to resolve; the builder scans for the first operator type present, in a fixed precedence order ((, ;, |, <<, <, >>, >, ||, &&), splits the string at its first occurrence, and recurses on both halves. Leaves are commands. So ls -l | grep .c > out.txt becomes:

flowchart TD
    P["pipe"] --> L["ls -l"]
    P --> R["redirect"]
    R --> RL["grep .c"]
    R --> RR["out.txt"]
Loading

control_pipe forks and crosses a pipe, then evaluates its right subtree — which is itself an operator, so control_right_chevron runs next and inherits that stdin. Operators compose because every handler asks whether its child is another operator and re-enters the dispatcher if so. Each one saves the descriptor it is about to overwrite and restores it afterwards, so a pipeline does not poison the next command in a sequence.

The interactive prompt clears ICANON and ECHO, so the shell sees raw bytes and redraws the line itself through termcap — arrow keys, Ctrl-L, Ctrl-U and history navigation are all handled by hand.

Directory Responsibility
sources/line_editing/ Raw terminal mode, keystrokes, history navigation
sources/parser_ll/ Operator-tree construction and dispatch
sources/operator/ One handler per operator — where forks and descriptors live
sources/execution/ PATH lookup, execve, termination diagnostics
sources/built_in/ Built-ins, running in-process so they can mutate shell state
sources/backticks/ Command substitution, by re-entering the evaluator
lib/my/ In-house libc subset: my_printf, get_next_line, string helpers

Features

Operators; | < << > >> && || and ( ) grouping, evaluated recursively.

ExecutionPATH lookup, exit-status propagation, and tcsh-style diagnostics for ~40 termination signals (Segmentation fault, Killed, (core dumped)).

Built-inscd, echo, env, setenv, unsetenv, alias, history, exit.

Interactive prompt — raw-mode terminal, cwd-aware prompt, arrow-key history, Ctrl-L/Ctrl-U.

Command substitution — backticks, captured by recursively re-entering the shell's evaluator with stdout redirected.

Aliases — loaded at startup from .myshrc in the working directory.

Tests — 151 Criterion unit tests covering the operator tree, environment manipulation, cd error paths and signal translation.

Build

Requires a Unix-like system, make, a C compiler and the ncurses development headers.

git clone https://github.com/AntoinePoisson/myShell.git
cd myShell
make
./mysh

make tests_run builds and runs the Criterion suite; make debug rebuilds with -g3 under valgrind.

The Makefile's CFLAGS contains --extra, which no current compiler accepts — -Wextra was the intent. Building the original sources therefore needs make CFLAGS="-I ./includes/ -Wall -Wextra -pedantic". Left as-is on purpose.

/bin/echo a | /usr/bin/tr a-z A-Z       # pipeline
/bin/echo text > out.txt                # redirection
/bin/cat < out.txt                      # input redirection
/usr/bin/true && /bin/echo success      # conditional execution
echo `/bin/echo substituted`            # backtick substitution
echo $?                                 # last exit status

Scope

This is a teaching implementation, not a POSIX shell. There is no variable expansion, no globbing and no job control; quoting is handled by echo rather than by the parser, and &&/|| group right where POSIX groups left. Built-ins invoked inside a pipeline run in the forked child, so their effect on shell state is lost.

Context

Individual project, written in 2018 during the Epitech curriculum and imported here in 2019. The source has intentionally not been modernised or refactored — its value is as a record of what was built, and the documentation exists to make that record legible.

License

MIT.

About

Unix shell written in C with binary-tree command parsing, pipes, redirections, logical operators, aliases, history and Criterion tests.

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Contributors

Languages