This custom shell is designed to support a variety of functionalities including command execution, piping, redirection, background and foreground process management, and more. The shell allows you to execute built-in commands as well as external commands with various options for redirection and background execution.
- Command Execution: Execute external commands and built-in commands.
- Piping: Support for piping between commands using
|. - Redirection: Input and output redirection with
<,>, and>>. - Background Jobs: Execute commands in the background using
&. - Foreground Jobs: Bring background jobs to the foreground using
fg. - Process Management: List and manage processes.
- Custom Commands: Includes custom commands like
hop,reveal,proclore,seek,log,iMan,activities,ping, andneonate.
hop: Changes the working directory. Usage:hop <path>reveal: Displays information about the system or environment. Usage:reveal <options>proclore: Lists current processes. Usage:procloreseek: Searches for a pattern in files or directories. Usage:seek <pattern>log: Handles log files. Usage:log <options>iMan: Displays information about the manual. Usage:iMan <options>activities: Lists recent activities. Usage:activitiesping: Pings a specified target. Usage:ping <target>neonate: Creates a new neonate process. Usage:neonate -n <time>
You can execute any external command using the shell. External commands are executed using the execvp system call.
- Starting the Shell: Compile the shell and run the executable.
- Executing Commands: Type commands directly into the shell prompt.
- Piping Commands: Use
|to pipe output from one command to another. - Redirecting Output: Use
>to redirect output to a file and>>to append to a file. - Redirecting Input: Use
<to redirect input from a file. - Background Execution: Append
&to a command to run it in the background. - Foreground Execution: Use
fg <pid>to bring a background process to the foreground.
-
Purpose: Displays a shell prompt with the username, hostname, and current working directory, using color formatting.
-
Parameters:
char* home: User’s home directory for abbreviation.
-
Logic:
- Retrieve User/Host Info:
- Uses
getpwuid()for username andgethostname()for hostname.
- Uses
- Handle CWD:
- Retrieves the current directory using
getcwd(). - If inside
home, abbreviates path with~, else shows the full path.
- Retrieves the current directory using
- Display Prompt:
- Uses ANSI color codes to style the username (blue), hostname (green), and directory (cyan).
- Error Handling:
- Prints errors if fetching username, hostname, or CWD fails.
- Retrieve User/Host Info:
-
Color Reset: After each segment, terminal colors are reset using the
RESETmacro.
-
Purpose: Changes the current working directory based on input arguments.
-
Parameters:
char* argum: The command input, e.g.,hopor a directory path.char* home: User’s home directory for~expansion.char* pevcwd: Previous working directory, used for-option.
-
Logic:
- Default to Home:
- If
argumis"hop", changes to the home directory and prints the path.
- If
- Process Arguments:
- Splits
argumusingstrtok_r(). - Handles special cases:
"-": Switches to the previous directory."~": Switches to the home directory.- Otherwise, changes to the provided path.
- Splits
- Update Previous Directory:
- Stores the current working directory in
pevcwdbefore changing to the new path.
- Stores the current working directory in
- Error Handling:
- Prints an error if directory change (
chdir()) fails. - Prints the current directory on successful change.
- Prints an error if directory change (
- Default to Home:
-
Return: Returns the updated previous working directory (
pevcwd).
- Purpose: Lists files in a directory with optional hidden file filtering.
- Parameters:
int hidden_flag: If set, includes hidden files.const char* dir_path: Path of the directory to list.char* home: User’s home directory for~expansion.char* prevcd: Previous working directory for-option.
- Logic:
- Resolves
-and~to proper paths. - Filters hidden files based on
hidden_flag. - Prints directory contents with color-coding: Blue (directories), Green (executables), White (regular files).
- Resolves
- Purpose: Prints detailed file info (permissions, owner, size, etc.).
- Parameters:
const char* name: File name.const struct stat* sb: File status info (metadata).
- Purpose: Lists all files with detailed info, using
print_file_info(). - Parameters: Same as
list.
- Purpose: Parses and executes the list command, supporting flags like
-a(show hidden) and-l(long format). - Parameters:
char* cmd: The full command input (e.g.,ls -al).char* home,char* prevcd: Same aslist.
- Purpose: Logs executed commands, avoiding duplicates.
- Parameters:
char* cmd: Command to log.const char* log_file: Log file path.
- Purpose: Writes a command to the log file, maintaining a fixed log size.
- Parameters: Same as
logcmd.
- Purpose: Clears the log file.
- Parameters:
const char* log_file: Log file path.
- Purpose: Manages log commands like viewing and purging.
- Parameters:
char* cmd_token: The log command.const char* log_file: Log file path.
- Purpose: Retrieves and executes a command from the log by number.
- Parameters:
int number: The command index.const char* log_file: Log file path.
- Returns: The command string at the specified log index.
- Purpose: Retrieves and displays information about a process by its PID.
- Parameters:
pid_t pid: The process ID to query.
- Logic:
- Process Status: Reads from
/proc/[pid]/statusto extract:- Process state.
- Process group ID (
Tgid). - Virtual memory size (
VmSize).
- Executable Path: Reads the symbolic link from
/proc/[pid]/exeto display the path of the executable. - Error Handling: Prints an error if the process does not exist or if it fails to read the executable path.
- Process Status: Reads from
- Purpose: Parses a command to print process information for a given or current PID.
- Parameters:
char* cmd: Command input that optionally includes a PID.
- Logic:
- Extracts the PID from the command, defaults to the current process ID if no PID is provided.
- Calls
get_process_info()to display process details.
- Purpose: Prints the file or directory name with a color based on its type (directory or file).
- Parameters:
char *path: Path or name of the file/directory.int is_dir: Flag to indicate if the path is a directory (prints blue) or a file (prints green).
- Purpose: Compares a file name with a target file, accounting for possible extensions.
- Parameters:
char *a: The base name to check.char *target: The target file name.
- Logic:
- If the base name contains an extension, it checks for an exact match.
- If the base name doesn't have an extension, it checks if the base name matches the beginning of the target name with a
.added.
- Purpose: Recursively searches through directories to find files or directories matching the target name.
- Parameters:
char *base_path: The starting directory path.char *target: The name of the file or directory to search for.int search_files: Whether to search for files.int search_dirs: Whether to search for directories.int *found_count: Tracks the number of matches found.char *invoke: The current working directory.char *found_path: Stores the first found path.
- Purpose: Parses the input command and initiates a search for a file or directory within the target directory.
- Parameters:
char *command_string: The command input that includes options (-d,-f,-e), target file or directory, and search directory.
- Flags:
-d: Search for directories only.-f: Search for files only.-e: Execute the found file or change directory to the found directory.
- Purpose: Adds a process to the process management system.
- Parameters:
pid_t pid: The process ID of the process.const char *command: The command associated with the process.
- Purpose: Checks the status of all tracked processes, updating whether they are running, stopped, or terminated.
- Logic:
- Uses
waitpidto check for process status changes and updates the internal process list accordingly. - Handles processes that have exited or have been stopped/continued.
- Uses
- Purpose: Helper function for sorting processes based on their command names.
- Parameters:
- Two
Processstructures to be compared.
- Two
- Purpose: Brings a process to the foreground and resumes it if it was stopped.
- Parameters:
pid_t pid: The process ID to bring to the foreground.
- Logic:
- Sets the terminal's foreground process group to the specified process.
- Sends the
SIGCONTsignal to resume the process if it was stopped.
- Purpose: Displays a list of all running and stopped processes, sorted by command name.
- Logic:
- Calls
update_process_statusto ensure process statuses are up-to-date. - Sorts the process list using
qsortandcompare_processes. - Displays each process, its PID, command, and whether it's stopped or running.
- Calls
- Purpose: Sends a signal to a process.
- Parameters:
int pid: The process ID to which the signal will be sent.int sig: The signal number to send (e.g.,SIGKILL,SIGTERM).
- Logic:
- Uses the
killsystem call to send a signal to the process. - If the process doesn't exist or an error occurs, it prints an error message.
- Otherwise, it prints a success message indicating that the signal was sent.
- Uses the
- Purpose: Parses a command string and sends a signal to a process.
- Parameters:
char *cmd: The command string, which includes the process ID and signal.
- Logic:
- The command string is split using
strtokto extract the PID and signal number. - The
pingfunction is called with these extracted values.
- The command string is split using
- Purpose: Handles signals sent to the process.
- Parameters:
int sig: The signal number (e.g.,SIGUSR1).
- Logic:
- If the signal is
SIGUSR1, it sets therunningflag to 0, which can be used to terminate the loop in the child process.
- If the signal is
- Purpose: Retrieves the most recent PID from the system.
- Logic:
- Reads the
/proc/sys/kernel/pid_maxfile to get the most recent PID. - If successful, returns the PID. Otherwise, returns -1.
- Reads the
- Purpose: Captures a single character input from the user without echoing it to the screen.
- Logic:
- Uses
tcgetattrandtcsetattrto modify terminal settings, disabling canonical mode and echo. - Returns the captured character.
- Uses
- Purpose: Continuously prints the most recent process ID at specified intervals until the user presses the 'x' key.
- Parameters:
const char *time_arg: The time interval (in seconds) between prints.
- Logic:
- Parses the time argument, ensuring it's a valid positive integer.
- Uses
forkto create a child process:- Child Process:
- Continuously fetches and prints the most recent PID every
intervalseconds until it receives aSIGUSR1signal.
- Continuously fetches and prints the most recent PID every
- Parent Process:
- Waits for user input. If the 'x' key is pressed, the parent sends a
SIGUSR1signal to the child process, terminating it.
- Waits for user input. If the 'x' key is pressed, the parent sends a
- Child Process:
- If the
forkfails, prints an error message.
Sends an HTTP GET request to a given URL and prints the text content of the response while ignoring HTML tags, scripts, and styles.
const char *hostname: The hostname of the server to connect to.const char *path: The path of the resource on the server.
-
Prepare Address Info:
- Initializes
hintsforgetaddrinfoto handle both IPv4 and IPv6 addresses and TCP stream sockets.
- Initializes
-
Get Address Information:
- Calls
getaddrinfoto resolve the hostname into an address structure.
- Calls
-
Create Socket:
- Creates a socket using the resolved address information.
-
Connect to Server:
- Connects the socket to the server's address.
-
Prepare and Send HTTP GET Request:
- Constructs an HTTP GET request string.
- Sends the request using the socket.
-
Receive and Process Response:
- Receives the response in chunks.
- Parses the response to extract and print text content, ignoring HTML tags, scripts, and styles.
-
Close Socket:
- Closes the socket after receiving the response.
- Prints error messages if
getaddrinfo,socket,connect, orsendfail. - Prints an error message if receiving the response fails.
Constructs a URL path based on a command argument and fetches data from the URL using the fetch_data_from_url function.
char* cmd: The command string containing the argument for the URL path.
-
Parse Command String:
- Splits the command string into tokens using
strtok. - Extracts the argument for the URL path.
- Splits the command string into tokens using
-
Construct URL Path:
- Uses
snprintfto create the URL path with the given argument.
- Uses
-
Fetch Data:
- Calls
fetch_data_from_urlwith the hostname (man.he.net) and the constructed path.
- Calls
If cmd is "manpage topic", it will construct the path /?topic=topic§ion=all and fetch data from man.he.net using this path.
Purpose: Handles the SIGINT signal (usually generated by pressing Ctrl+C).
Functionality:
- Sets the global flag
ctrl_c_pressed. - Sends SIGINT to the foreground process if it exists.
- Prints a new line if no foreground process is running.
Purpose: Handles the SIGTSTP signal (usually generated by pressing Ctrl+Z).
Functionality:
- Sets the global flag
ctrl_z_pressed. - Sends SIGTSTP to the foreground process if it exists.
Purpose: Handles the SIGCHLD signal, which is sent to a process when a child process terminates or stops.
Functionality:
- Reaps all terminated child processes.
- Prints status messages based on the termination status:
- Exit Status: Prints when a background process exits normally.
- Signal Termination: Prints when a background process is terminated by a signal.
- Stopped: Prints when a process is stopped; adds the process to the background processes list.
Purpose: Checks if a command is valid by verifying if it is a known command or if it exists in the system's PATH.
Parameters:
const char *command: The command to check.
Returns:
1if the command is valid.0otherwise.
Purpose: Extracts the part of a string before the first whitespace.
Parameters:
const char *str: The input string.char *result: Buffer to store the result.
Functionality:
- Copies the substring before the first whitespace into the result buffer.
- If no whitespace is found, copies the entire string.
Purpose: Trims leading and trailing whitespace from a string.
Parameters:
char *str: The string to trim.
Functionality:
- Removes leading and trailing spaces from the string.
- Modifies the original string in place.
Purpose: Counts occurrences of a specific character in a string.
Parameters:
const char *str: The input string.char ch: The character to count.
Returns:
- The number of occurrences of the specified character.
-
Global Variables:
volatile sig_atomic_t ctrl_c_pressed: Flag set when Ctrl+C is pressed.volatile sig_atomic_t ctrl_z_pressed: Flag set when Ctrl+Z is pressed.pid_t foreground_pid: Stores the PID of the foreground process.
-
Signal Handling:
- Ensure proper handling of child processes and background tasks by implementing appropriate functions to manage process states and interactions.