Virtual Terminal

Tools Used:
- Linux OS
- C Programming Language
- System Calls (e.g.,
readdir()
,mkdir()
,rmdir()
,stat()
) - Unix-based Libraries (
sys
/types.h
,dirent.h
,sys/stat.h
,unistd.h
) - GitHub for version control
Project Overview:
As part of the CS431 Operating Systems course at Regis University, I was tasked with implementing a custom shell, a simplified command-line interface that enables user interaction with the operating system. The shell provides support for a set of basic file operations, allowing users to execute commands such as ls
, cat
, rm
, mkdir
, and stat directly from the terminal. The key focus of this project was to handle these commands internally, without relying on system-level execution functions like exec()
or system()
.
Development Process:
I was provided with a basic shell framework that prompted users for input. My responsibility was to complete the implementation by coding additional file system operations. Each command required careful attention to error handling, ensuring that invalid commands or arguments were managed appropriately. The challenge was to ensure the shell performed the operations internally, using system calls and avoiding the use of advanced shell features like pipes, redirection, or environment variables.
Command Implementations:
- ls: This command lists the contents of a directory. I implemented logic to open a directory stream using
opendir()
and iterated over the directory entries usingreaddir()
, printing each entry to the terminal. The command supports directory path arguments but defaults to listing the current working directory when no argument is provided.
- cat: I implemented the cat command to print the contents of a specified file. Using low-level file I/O functions like
read()
andwrite()
, the program reads the contents of the file and outputs it to the terminal. Proper error handling was added to check for invalid or missing files.
- mkdir and rmdir: These commands were implemented using the mkdir() and rmdir() system calls, respectively. They allow users to create and remove directories. Error conditions such as attempting to remove non-empty directories or creating a directory that already exists are appropriately handled.
- rm: I implemented the rm command using the unlink() system call, which removes a specified file. Error checking ensures that attempts to delete non-existent files are managed gracefully.
- pwd: This command prints the current working directory to the terminal. The implementation made use of the
getcwd()
system call, which was partially pre-written in the provided code.
- stat: The stat command displays various file attributes, such as size, number of links, inode number, and modification times. Using the
stat()
system call, I was able to retrieve and display this information in a formatted manner, adding another layer of functionality to the shell.
Architecture and Design:
The project’s design adhered to a clear, modular structure where each command functioned as an independent operation. Error handling was integrated into every command to ensure robustness and resilience against invalid user input. This approach helped reinforce important concepts related to system-level programming and file operations in Unix-based systems.
By completing this assignment, I gained hands-on experience working with system calls, developing file operation utilities, and enhancing my understanding of how the operating system handles user-level commands internally. This project also highlighted the importance of proper error handling, modular design, and adhering to the principles of low-level programming.