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:proclore
seek
: 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:activities
ping
: 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
RESET
macro.
-
Purpose: Changes the current working directory based on input arguments.
-
Parameters:
char* argum
: The command input, e.g.,hop
or a directory path.char* home
: User’s home directory for~
expansion.char* pevcwd
: Previous working directory, used for-
option.
-
Logic:
- Default to Home:
- If
argum
is"hop"
, changes to the home directory and prints the path.
- If
- Process Arguments:
- Splits
argum
usingstrtok_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
pevcwd
before 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]/status
to extract:- Process state.
- Process group ID (
Tgid
). - Virtual memory size (
VmSize
).
- Executable Path: Reads the symbolic link from
/proc/[pid]/exe
to 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
waitpid
to 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
Process
structures 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
SIGCONT
signal 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_status
to ensure process statuses are up-to-date. - Sorts the process list using
qsort
andcompare_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
kill
system 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
strtok
to extract the PID and signal number. - The
ping
function 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 therunning
flag 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_max
file 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
tcgetattr
andtcsetattr
to 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
fork
to create a child process:- Child Process:
- Continuously fetches and prints the most recent PID every
interval
seconds until it receives aSIGUSR1
signal.
- 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
SIGUSR1
signal to the child process, terminating it.
- Waits for user input. If the 'x' key is pressed, the parent sends a
- Child Process:
- If the
fork
fails, 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
hints
forgetaddrinfo
to handle both IPv4 and IPv6 addresses and TCP stream sockets.
- Initializes
-
Get Address Information:
- Calls
getaddrinfo
to 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
, orsend
fail. - 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
snprintf
to create the URL path with the given argument.
- Uses
-
Fetch Data:
- Calls
fetch_data_from_url
with 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:
1
if the command is valid.0
otherwise.
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.