The following code is a simple shell program that tries to emulate an actual shell and is written in C.
On running the makefile, the executable, resh
will be created in the current directory and running it will produce start the execution of the shell.
For Asthetic reasons, my code has been colored to differentiate between input, working output, errors and the prompt
The Code has been divided into the following files for Part 2:
header.h
main.c
shell_basics.c
command_processing.c
parse.c
linked_lists.c
ls.c
pinfo.c
rawmode.c
technical_functions.c
briping.c
replay.c
- Header file for the shell program
- Contains all required header files and function prototypes
- contains the main function
- contains the shell functions that are required for processing and operation of the shell
shell_setup()
is run to set the global variables and other constants that are required in the programshell_prompt()
is run to print the shell prompt along with the relative pathshell()
is the actual function in which everything will run via a while loopchild_terminate()
is called by signal when the child dies bysignal()
and then reaps the childfg_to_bg_handler()
handles the Ctrl+Z functionctrl_C_handler()
handles the Ctrl+C function
- contains the functions to choose which command to run, as well as the code for each user defined function
command_process()
chooses which function to run based on the input string. Also has the added functionality of reassigning input and output based on file redirectioncd_command()
runs the cd command usingchdir()
echo_command()
runs the echo command usingprintf()
pwd_command()
runs the pwd command usingcwd()
repeat_command()
runs the echo command by parsing and combining and callingcommand_process()
through a for loopbg_command()
runs the command given usingexecvp()
in the background after using afork()
fg_command()
runs the command given usingexecvp()
in the foreground after using afork()
andwait()
jobs_command()
runs the command jobs and lists the background processes with the help of the linked listmake_fg_command()
takes the job number and uses it to get the pid of the process and make it a foreground processmake_bg_command()
sends a SIGCONT signal to a background process based on job number to make it change states from stopped to runningsig_command()
uses thekill()
function to send a signal given in terminal to the process chosen by the user
- contains the functions for the parsing the input so they can be easily processed
parse()
takes in a string, a delimiter string and an integer pointer. parse will then return a pointer to an array of strings where the string has been parsed and store the number of strings in the integer pointer. Input string is not modifiedfreemem()
can be called to free the memory that was allocated inparse()
to be memory efficient
- contains the linked list related functions used in history and storing background process names
add_bgp_node()
stores a newly created background process's name and pid in stackget_process_name()
retrieves the background process's node from the stack using pidremove_process()
deletes the node relating to the pid givenadd_his_node()
stores the command entered as a node in a dequeuehistory_command()
prints the commands in the dequeue with a limit of the number given or the length of the dequeuehistory_storage()
writes the existing queue to a file so that it can be retrieved in another sessionhistory_retrieval()
reads the file of previous commands so the old history is retained
ls_command()
will go through all the elements in a directory and print it based on the flags assigned or just if a file, it will just print it based on the flagslist_form()
will print a file/directory given to it in the list format
- contains the pinfo command code
pinfo_command()
will access the process files and print the process details based on the pid given to it
- contains files that enable bufferless inputs to enable up arrow detection
enableRawMode()
enables bufferless inputdisableRawMode()
disables bufferless input so other printf statements work properlydie()
prints the error related to enabling and disabling bufferless input- All of this is thanks to Kannav's code which was sent in Moodle
- contains functions that serve a specific purpose and are used in the code
remove_spaces()
removes the spaces in the input string so that no problem occurs while parsingcombination()
is the opposite ofparse()
as it turns an array of strings into a whole string again. Used in repeat due to the nature of executioninput_line()
returns the input that is also affected by the up arrow which requires special cases due to the input being bufferless. Also takes care of the Ctrl+D characterbackspace()
removes a character from the input stored in the input as well as from the screen as needed to emulate a normal backspacerel_path()
edits the string given to it so that it is turned into the relative path to the home directory if requiredquitter()
makes read a non-blocking function inorder and prints the meminfo dirty to the terminal
- Contains the code to handle the pipe input-output flow. Name inspired by coffee brewing instrument for the outdoors
bripe()
takes in a string and then executes each pipe in it while handling the input and output file descriptors so flow is maintained
- Contains code that implements the bonus question replay
action_replay()
usessleep()
to run the command specicified by the user after every time interval specified by the user for a time period also specified by the user