MYSH — Advanced Unix Shell (C)
Summary MYSH is a compact, POSIX-style Unix command-line shell implemented in C. It implements a practical set of shell features (tokenization, pipelines, red…
Summary
MYSH is a compact, POSIX-style Unix command-line shell implemented in C. It implements a practical set of shell features (tokenization, pipelines, redirection, job control and builtins) with a focus on correct process-group and I/O handling for reliable foreground/background execution. The shell is designed for educational and production-style demonstrations of systems programming concepts: parsing, fork/exec, signals, process groups and file descriptor management.
Key features
- Command parsing with tokenization and basic quoting support.
- Pipelines (multi-stage) using the pipe operator
|. - Redirection support:
<,>,>>, numeric fd redirection (e.g.2>file) and fd duplication (e.g.2>&1). - Job control: background jobs with
&, job table,jobs,bg,fgand SIGCHLD reaping. - Builtins implemented:
cd,pwd,exit,echo,alias,unalias,type,help,export,set,unset,history, and job-control builtins. - Executor implements fork/exec with process-group management and correct foreground/background semantics.
Design & architecture
MYSH follows a classic shell architecture with clear separation of concerns:
- REPL / read-line to collect logical lines (supports multi-line quotes).
- Tokenizer & parser to produce a small AST (linked list of pipeline stages).
- Executor that sets up pipes, spawns processes, manages process groups (pgid), applies redirections and handles builtin/child execution semantics.
- Job subsystem tracks background jobs, their pids, and states; SIGCHLD is handled and reaped safely in the main loop.
Runtime flow (high level)
- Read input line from user (logical line handling).
- Tokenize honoring quoted strings and escapes.
- Build pipeline AST nodes (each stage records argv and redirections).
- Execute: allocate pipes, fork per stage, setpgid, dup2 redirs, and exec external binaries or run builtin child routines. Parent waits for foreground jobs or registers background jobs.
- SIGCHLD handler marks reaping; main loop collects statuses and updates the job table.
Core data model
Key structs used internally (conceptual):
command_t— argv[], infile/outfile, append flag, background flag, next pointer for pipeline stages.job_t— job id, process group id, cmdline (human-readable), pids[], state (RUNNING/STOPPED/DONE), exit code and bookkeeping fields.
Builtins & user behavior
MYSH implements common shell builtins. Builtins which modify shell state (like cd and export) run in the parent when invoked as a single-stage command; other builtins can run in forked children as pipeline stages. Redirections work with builtins by temporarily applying redirections in the parent when necessary.
Quick demo examples
# basics echo hello # pipeline /usr/bin/printf "a\nb\nc\n" | /usr/bin/grep b | /usr/bin/wc -l # redirection echo redir_test > /tmp/mysh_test1 # background job and job control sleep 10 & jobs fg %1
Build & run
# build make # run interactive ./bin/mysh # run scripted printf 'echo hello' | ./bin/mysh
Notes & roadmap
- Current implementation provides a robust baseline for job control and redirection semantics; edge-cases for complex nested quoting remain to be hardened.
- Planned improvements: variable/word expansion, persistent history & line editing, here-documents, and improved terminal control (tcsetpgrp) for more accurate job/foreground handling.
Documentation & validated examples are available in the project technical doc (build, usage examples and code excerpts).