Student 1:
- CID: 02327531
- Name: Yichan Kim
Student 2:
- CID: Sumukh Adiraju
- Name: 02563601
This project implements a custom shell in C that provides a command-line interface fundamentally similar to standard Unix shells. The shell was built incrementally, adding features section by section as outlined in the project roadmap.
Description: Implemented basic command execution without redirection or pipes. The shell can execute standard Unix commands by forking child processes and using execvp() to load binaries from the system PATH.
Key Functions:
launch_program(): Handles command execution, including special handling for the "exit" commandchild(): Usesexecvp()to replace the child process with the specified command programme
Status: Fully functional. All test commands from the project brief execute successfully, including whoami, pwd, ls, cat, grep, sort, wc, cp, touch, chmod, less, and exit.
Description: Added support for input (<) and output (>, >>) redirection operators. Commands can read from files or write output to files.
Key Functions:
command_with_redirection(): Detects redirection operators in command linesfind_redirection(): Identifies redirection operator/filename pairs and determines mode (input, append, truncate)launch_program_with_redirection(): Handles command execution with file descriptor redirectionchild_with_redirection(): Helper function that usesdup2()to redirect stdin/stdout before executing commands
Status: Fully functional. Supports single redirection operator per command (as per requirements). All redirection test cases work correctly, including:
- Output redirection:
ls > file.txt,sort > file.txt - Append mode:
cal -y >> file.txt - Input redirection:
grep pattern < file.txt
Limitation: Only single redirection operator per command is supported (no sort < input.txt > output.txt in the same command, as per section requirements).
Description: Implemented the cd built-in command with directory navigation and dynamic prompt updates showing the current working directory.
Key Functions:
is_cd(): Detects if a command is acdcommand (handles edge cases like "cdcd")init_lwd(): Initialises the last working directory bufferrun_cd(): Executes directory changes usingchdir()system callconstruct_shell_prompt(): Updated to display current working directory in format[/current/path s3]$
Status: Fully functional. Supports:
cd(goes to home directory via$HOME)cd /path/to/directorycd -(switches to previous directory)cd ..(goes to parent directory)cd .(stays in current directory)- Error handling for invalid paths and too many arguments
Note: Support for cd ~ was not implemented (as noted in project brief).
Description: Implemented pipeline execution using the pipe (|) operator for inter-process communication, allowing multiple commands to be chained together.
Key Functions:
command_with_pipes(): Detects pipe operators in command linestokenize_pipeline(): Splits command line into individual commands separated by pipes, with parentheses-aware parsinglaunch_pipeline(): Executes pipeline of commands, creating pipes between consecutive stageschild_with_pipes(): Helper function that redirects stdin/stdout through pipeschild_with_pipes_and_redirection(): Combined helper for pipelines ending with output redirection
Status: Fully functional. Supports:
- Multi-stage pipelines:
cmd1 | cmd2 | cmd3 | cmd4 - Pipelines with redirection:
cat file | sort | tac > output.txt - Parentheses-aware parsing (ignores pipes inside subshells)
- Proper pipe cleanup and process management
Bug Fix: Fixed issue where pipelines ending with output redirection were passing redirection operators as arguments to commands. Now properly handles cat file | sort > output.txt.
Description: Implemented support for executing multiple commands sequentially using the semicolon (;) operator. Commands execute independently, with failures not stopping subsequent commands.
Key Functions:
command_with_batch(): Detects semicolon operators in command linestokenize_batched_commands(): Splits command line into individual commands separated by semicolons, with parentheses-aware parsinglaunch_batched_commands(): Executes commands sequentially, routing each to appropriate handler (basic, redirection, pipes, cd, subshells)
Status: Fully functional. Supports:
- Sequential command execution:
cmd1 ; cmd2 ; cmd3 - Mixed command types in batches:
echo "Start" ; ls > file.txt ; cat file.txt ; rm file.txt - Parentheses-aware parsing (ignores semicolons inside subshells)
- Proper error handling and cleanup between commands
Description: Implemented subshell execution using parentheses () for isolated command execution. Subshells run in separate child processes, so directory changes and other state modifications don't affect the parent shell.
Key Functions:
command_with_subshell(): Detects parentheses in command linesextract_subshell_commands(): Extracts command string between parentheses, handling whitespace trimminglaunch_subshell(): Forks child process and executes shell binary with subshell commands- Subshell argument handler in
s3main.c: Processes commands when shell is invoked with arguments
Status: Fully functional. Supports:
- Standalone subshells:
(cd txt ; ls) - Subshells in batches:
echo "Start" ; (cd txt ; ls) ; echo "End" - Subshells in pipelines:
(cd txt ; cat file.txt) | head -n 5 - Complex combinations:
(cd txt ; cat file.txt | sort) | head -n 3 - Process isolation verified:
pwd ; (cd txt ; pwd) ; pwdconfirms parent directory unchanged
Implementation Details:
- Subshells work by having the shell execute itself (
./s3) with the subshell command as an argument - Each subshell runs in a separate forked process
- I/O redirection properly handled in pipelines containing subshells
Description: Implemented nested subshells through recursive execution. The shell supports arbitrary levels of nesting (e.g., (((echo "hi"))))). When a subshell is launched, it executes the shell binary again with the subshell command as an argument. If that command contains nested parentheses, the shell recursively processes them, naturally supporting any nesting depth.
Key Functions:
extract_subshell_commands(): Extracts top-level parentheses content, tracking depth to find matching pairslaunch_subshell(): Executes shell recursively with subshell command- Subshell argument handler in
s3main.c: Processes commands when shell is invoked with arguments, detecting and handling nested subshells recursively
Status: Fully functional. Supports:
- Arbitrary nesting levels:
(((echo "hi")))) - Nested subshells in batches:
echo "Outer" ; (echo "lvl 1" ; (echo "lvl 2" ; pwd) ; echo "back to lvl 1") ; echo "back to outer subshell" - Nested subshells in pipelines:
(cat file1 ; (sort file2 | head -5)) | wc -l - Complex combinations with all features
Implementation Approach: Uses recursive execution rather than explicit stack-based parsing. When a subshell is launched, it spawns a new shell instance that processes the command. If that command contains nested parentheses, the new shell instance detects and processes them, creating a natural recursive solution that supports unlimited nesting depth.
Description: Added support for removing surrounding quotes from command arguments. This handles cases like echo "Hi" where the quotes should be stripped before passing to the command.
Implementation: Modified parse_command() to detect and remove surrounding single or double quotes from tokens using memmove().
Status: Fully functional. Commands like echo "Hello World" and echo 'Hello World' properly strip quotes before execution.
Description: Enhanced parsing functions to ignore pipes '|' and semicolons ';' that appear inside parentheses. This allows proper handling of subshells within pipelines and batched commands.
Implementation: Updated tokenize_pipeline() and tokenize_batched_commands() to track parentheses depth and skip operators when inside parentheses. This meant scrapping the original strtok_r approach to split a raw line into two individual commands
Status: Fully functional.
Description: Fixed bug where pipelines ending with output redirection (e.g., cat file | sort > output.txt) were passing redirection operators as arguments to commands instead of redirecting output.
Implementation: Added child_with_pipes_and_redirection() helper function and modified launch_pipeline() to detect and handle redirection in the last command of a pipeline.
Status: Fully functional.
Description: Added comprehensive error handling throughout the codebase, including:
- Unbalanced parentheses detection
- Empty command detection in pipelines and batches
- Invalid redirection syntax handling
- File descriptor cleanup on errors
Status: Fully functional.
- Single redirection operator per command (as per Section 2 requirements)
cd ~not supported (not written in project brief)
- Linux/Unix environment (Ubuntu/WSL tested)
- GCC compiler
- Standard C libraries
gcc *.c -o s3
chmod +x s3./s3The shell will start with a prompt showing the current working directory.