A minimal Unix shell implementation in C with support for pipes, redirections, built-in commands, and command history.
-
External Commands: Execute any external command by forking child processes
-
Built-in Commands:
cd [dir]- Change directory (default: home directory)pwd- Print working directoryhelp- Display help message with all featureshistory- Show command history (last 256 commands)exit- Exit the shell
-
Piping: Chain multiple commands with
|- Example:
ls | grep .c | wc -l
- Example:
-
Input/Output Redirection:
<- Redirect input from file>- Redirect output to file (truncate)>>- Append output to file- Example:
echo "hello" > file.txt
-
Signal Handling: Ctrl+C does not kill the shell, only the current command
-
Command History: All commands are stored and accessible via the
historycommand
- GCC compiler
- Standard C library (libc)
- POSIX-compliant operating system (Linux, macOS, BSD)
cd /path/to/cshell
makeThis will compile all source files and create the cshell executable.
./cshellOr use the convenience target:
make runRemove compiled files:
make cleancshell> pwd
/Users/himanshujaiswal/Documents/cshell
cshell> cd ~
cshell> ls
cshell> cat file.txt | grep "search" | wc -l
cshell> echo "test" > output.txt
cshell> cat < input.txt
cshell> history
cshell> help
cshell> exitcshell/
├── main.c - Main event loop, signal handling, history management
├── parser.c - Input parsing, tokenization, command structure building
├── parser.h - Parser interface and structures
├── executor.c - Command execution, piping, fork/exec handling
├── executor.h - Executor interface
├── builtins.c - Built-in command implementations
├── builtins.h - Built-in command interface
├── Makefile - Build configuration
├── README.md - This file
└── CHANGELOG.md - Version history
- Tokenizes input by whitespace
- Handles pipes (
|) to identify command boundaries - Handles redirections (
<,>,>>) with associated filenames - Returns a pipeline structure with individual commands
- Handles single commands, built-in or external
- Creates pipes between commands in a pipeline
- Forks child processes for external commands using
fork()andexecvp() - Handles input/output redirections via file descriptors and
dup2() - Waits for all child processes to complete
cd: Useschdir()to change directoriespwd: Usesgetcwd()to get current directoryhelp: Displays usage informationhistory: Shows all stored commandsexit: Terminates the shell
- Initializes signal handler for SIGINT
- Maintains command history (max 256 entries)
- Reads user input and calls parser/executor
- Continues on signal interruption
- Piping only works with external commands (built-ins cannot be piped)
- No background process support (no
&operator) - No job control (no
fg,bg,jobscommands) - No environment variable expansion
- No quoting or escape sequences
- No aliases or command substitution
- Limited to 64 arguments per command
- Limited to 128 tokens per input line
- Uses only POSIX APIs and standard C library
- No external dependencies
- Handles process termination and cleanup properly
- Safe memory management with malloc/free
- Robust error handling and reporting
Public domain. Free to use and modify.