-
Notifications
You must be signed in to change notification settings - Fork 1
Under Construction
Internal commands:
exit
: well .. this exits the shell
cd
: changes directory
export
: adds a variable in the environment variable list. example: export var_name
print
: prints value of a variable on stdout. example: print var_name
the-sh provides a minimal Support for variables. As an example, the-sh supports exporting variables.
X = "some_value"
export X
A very minimal support for IO redirection is available.
echo "hello" > a.txt
Of course, all the external programs (example, ls, vim .. etc) installed in your workstation can be invoked through the shell.
There are 2 modes of running the-sh.
- Command line (user enters commands interactively, and the commands get executed)
- Using scripts (user writes a file containing a set of commands)
In the first case, the program runs in an infinite loop. Here is a sequence of events
-
User enters command as a string (space separated)
-
A parser parses the input string and prepares a linked list of
struct arg
where each element of the structure contains the name of a argument. For example: the stringls -l -a
would be parsed and a linked list of length 2 would be prepared.The head of the linked list would represent that command.
struct arg
{
struct arg* next;
char* string;
};
typedef struct arg* Command
- The command is executed by making a call to the function :
void execute(Command cmd)
. the-sh has two types of commands: internal command and external command. - For executing internal commands, no forking is needed. The only internal commands the-sh supports are exit, cd, export, print. These commands are exeuted by invoking UNIX library functions; as an example,
cd
is implemented using the function chdir() . - For executing external commands, the-sh forks a child process and converts that child into a new program using exec family of functions.
- While executing a command, the-sh first checks whether it is an internal command or not. It does so by comparing the first argument of the command with all the possible internal commands (cd, exit, export, print). This is implemented using functions of the form
int is_command (Command cmd)
. For example,is_cd(Command cmd)
checks whether the first argument of cmd is equal to"cd"
.is_print(Command cmd)
checks whether the first argument of cmd is equal to"print"
etc. All these functions return1
in case the answer is false, and returns0
if answer is true; these functions also executes the corresponding functionality.The parent function where all these functions are called is the "int is_internal(Command cmd)" function. - Suppose the command is not internal, ie,
is_internal(cmd)
returns1
, then the command is assumed to be external, and the functionis_external()
is called. In this function, a child process is spawned and the executale of the program represented by the external command (if it exists) is loaded in the child, (usingexec()
). If the external program exists,is_external()
executes it and returns0
. If it does not exist,is_external()
returns 1. As an example,ls
is an external command whose binary image exists in/bin
folder. the-sh searches all entries in thePATH
environment variable to locate executables
Note that is_external(cmd)
and is_internal(cmd)
functions are called in the function execute(cmd)
.
The functions is_resolve()
, and is_redirect()
are called inside the function is_external()
. is_resolve()
simply replaces all occurences of $var
with the actual value of the var
(variable). is_resolve()
does not make any change to the actual command; Instead, it first copies the entire Command (the linked list) into a new linked list and modifies the new Command.
is_redirect()
function checks for occurences of symbols '|'
or '>'
or '<'
. is_redirect()
takes as input 3 integer pointers. These three integers corresspond to
- File descriptor of stdout
- File descriptor of stdin
- Number of '|' symbols.
If there are no occurrences of '>'
or '<'
, the vaues 0
,1
are stored in stdin
and stdout
respectively. After this function is called inside is_external()
, we know the stdout
, stdin
of the new process to be spawned. We also know whether we need to spawn multiple processes in case the '|'
symbol appears in the command.