Simple Shell
Simple Shell
A UNIX Command Interpreter in C
Overview
Simple Shell is a custom UNIX command interpreter written in C. This project was developed as a personal challenge to deepen my understanding of system programming concepts including process creation, command parsing, and environment manipulation. The shell replicates core functionalities of popular UNIX shells by handling user input, executing commands, and providing several built-in features.
Features
Core Functionality
-
Prompt & Input Handling:
- Displays a custom prompt and waits for user input.
- Supports reading command lines (ending with a new line) interactively and via file input (non-interactive mode).
-
Command Parsing & Execution:
- Implements a custom
getlinefunction using buffered input with static variables, minimizing system calls. - Tokenizes input without using
strtok, ensuring flexibility and control. - Handles command lines with arguments and supports the PATH environment variable for command lookup.
- Executes commands using the
execvesystem call;forkis only invoked if the command exists.
- Implements a custom
Built-in Commands
-
exit- Terminates the shell.
- Supports both no-argument usage and an optional numeric argument to set the exit status.
-
env- Displays the current environment variables.
-
cd- Changes the current working directory.
-
setenv&unsetenvsetenv VARIABLE VALUE: Creates or updates an environment variable.unsetenv VARIABLE: Removes an environment variable.- Both commands include error handling, with error messages printed to stderr upon failure.
-
alias- Implements command aliasing for ease of use.
Advanced Shell Features
-
Command Separators & Logical Operators:
- Handles command separators (e.g.,
;) to execute multiple commands sequentially. - Supports logical operators (
&&and||) to allow conditional command execution.
- Handles command separators (e.g.,
-
Variable Replacement:
- Replaces shell variables with their corresponding values before execution.
-
Comment Handling:
- Ignores any text following a
#symbol, allowing for inline comments.
- Ignores any text following a
-
File Input Mode:
- Accepts a file as a command line argument, executing each line as a command.
Technical Details
-
Error Handling:
- Provides clear error messages when commands are not found or when execution fails.
- Gracefully handles EOF (Ctrl+D) to exit the shell without causing crashes.
-
Memory Management:
- Carefully manages dynamic memory allocation and deallocation to avoid memory leaks.
-
Coding Standards:
- All source code adheres to strict style guidelines (Betty style).
- Compiled using GCC with the following flags:
gcc -Wall -Werror -Wextra -pedantic -std=gnu89 *.c -o hsh
Repository Structure
simple_shell/
├── .gitignore # Specifies files and directories to ignore
├── AUTHORS # Lists the contributors
├── README.md # This documentation file
├── execute.c # Contains the command execution logic
├── exit_test # Test file for exit functionality
├── hsh # Compiled shell executable
├── interpret.c # Main interpreter functions
├── main.h # Header file with function prototypes and macros
├── more_strings.c # Additional string manipulation functions
├── parse.c # Input parsing and tokenization
├── putchar.c # Basic output functions
├── shell.c # Core shell loop and logic
├── strings.c # Custom string handling routines
└── words.c # Functions to split input into words/tokens
Usage
Compilation
To compile the shell, navigate to the project directory and run:
gcc -Wall -Werror -Wextra -pedantic -std=gnu89 *.c -o hsh
Running the Shell
Interactive Mode
Start the shell and enter commands at the prompt:
$ ./hsh
($) /bin/ls
main.c shell.c hsh README.md
($) exit
$
Non-Interactive Mode
Pipe commands from a file or echo command into the shell:
$ echo "/bin/ls" | ./hsh
main.c shell.c hsh README.md
$
Or execute a file containing commands:
$ cat commands.txt
/bin/ls
$ cat commands.txt | ./hsh
main.c shell.c hsh README.md
$
Learning Outcomes
Working on Simple Shell has strengthened my understanding of:
- UNIX process management, including
fork,execve, andwait. - Low-level I/O operations and buffering techniques.
- Environment variable manipulation and custom command parsing.
- Implementing advanced shell features such as command separators, logical operators, and aliasing.
- Writing clean, maintainable code under strict coding standards.
Final Thoughts
Developing this shell has been an enriching experience that pushed me to master core concepts of systems programming and sharpen my problem-solving skills. The project serves as a testament to my proficiency in C and my dedication to producing robust, high-quality software.