MiniShell is a compact, POSIX-style command-line shell implemented in C. It reproduces core shell behaviors such as process creation, job control, piping, redirection, and a small set of built-in commands.
MiniShell implements the core concepts of a Unix shell: read an input line, parse it into tokens, build an execution plan (commands, pipes, redirections), and run that plan while managing processes and I/O. The implementation follows common POSIX semantics for process creation and I/O handling.
- Read-eval loop: the program reads lines from
stdin, prompts for input, and dispatches parsing and execution for each line. - Tokenization: the lexer splits input into tokens on unquoted whitespace and recognizes quoted strings and special operators (
|,>,>>,<). - Parsing: tokens are arranged into commands and I/O actions. Pipelines are represented as ordered command stages with associated redirections.
- Execution: for each command or pipeline, the shell creates child processes using fork(), configures I/O with
pipe()and dup2(), then the child calls execve() to run external programs. The parent uses waitpid() to collect statuses. - Built-ins: internal commands such as
cd,echo,exit,env,export, andunsetare executed without spawning external processes when appropriate. - Signals: the shell handles interactive signals (SIGINT, SIGQUIT) to control foreground job behavior while keeping the shell process running.
Build and run the shell:
make
./myshellCommon usage examples:
# Run an external command
ls -la
# Pipe commands
ls | grep txt
# Redirect output
echo hello > out.txt
cat < out.txt
# Use a built-in
cd /tmp
env | grep PATH| Command | Behavior |
|---|---|
cd |
Change current directory |
echo |
Print arguments to stdout |
exit |
Exit the shell with optional status |
env |
Print environment variables |
export |
Set environment variables |
unset |
Remove environment variables |
- Process creation: fork() is used to spawn children; children call execve() to run programs. The parent calls waitpid() to wait for child termination and to obtain exit statuses.
- Pipelines: implemented using
pipe()pairs and carefuldup2()usage to connectSTDIN_FILENO/STDOUT_FILENObetween processes. - Redirections: handled by opening files with appropriate flags and
dup2()ing file descriptors into the child process beforeexecve(). - Signals: the shell manages SIGINT and SIGQUIT, forwarding signals to child processes as appropriate while preserving the interactive prompt.
Manual test recommendations:
- Build:
make - Run:
./myshell - Exercise built-ins, pipelines, and redirections as shown above.
Memory checks (Valgrind):
valgrind --leak-check=full ./myshellmain.c— entry and main loopparser.c,parser.h— tokenization and parsingexecutor.c,executor.h— execution, piping, redirectionbuiltins.c,builtins.h— built-in command logicsignals.c,signals.h— signal handling
Bug reports and pull requests are welcome. For clarity, include simple reproduction steps and expected behavior.
- Correctness: follow POSIX semantics for process creation, exit statuses, and I/O redirection where practical.
- Simplicity: implement a clear, readable code structure separating lexing, parsing, and execution.
- Robustness: avoid crashes on malformed input and handle common edge cases in parsing and I/O.
- Resource safety: manage file descriptors and heap allocations carefully to prevent leaks and descriptor leaks.
- Interactive command entry: run
./myshell, then typegrep -i TODO README.mdto search project TODOs. - Compound pipelines:
cat file.txt | tr ' ' '\n' | sort | uniq -cdemonstrates multi-stage pipeline handling. - File operations:
sort input.txt > sorted.txtshows output redirection;wc -l < sorted.txtshows input redirection.
- No advanced job control (no background job management with
&, nofg/bgbuilt-ins). - Limited shell expansions: no globbing (
*), no advanced parameter expansion, and no command substitution. - Minimal error messages compared to a full shell; some failure modes report only standard
errnotext.
- Add background job control and a basic job table.
- Implement wildcard expansion (globbing) and simple variable expansion.
- Add an automated test suite with expected input/output cases.