Skip to content
Anaykumar Joshi edited this page Jan 11, 2014 · 1 revision

Features

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.

Internal Implementation

There are 2 modes of running the-sh.

  1. Command line (user enters commands interactively, and the commands get executed)
  2. 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 string ls -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 return 1 in case the answer is false, and returns 0 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) returns 1, then the command is assumed to be external, and the function is_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, (using exec()). If the external program exists, is_external() executes it and returns 0. 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 the PATH 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

  1. File descriptor of stdout
  2. File descriptor of stdin
  3. 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.

Clone this wiki locally