SHELL Creation Assignment Help
In this assignment, you will create a shell that allows a user to run programs in the foreground and allows the user to store variables that are remembered by the shell.
To run a program, the user will simply type in the name of the program. Assume our prompt is "bw: " and the program we are running is "program1", it would look like the following:
bw: program1
To create a variable, the user types in the variable name followed by an = and then the value wrapped in quotes. Below are some examples:
bw: x = "24"
bw: name = "Yellow Jacket"
If the user wants to see a variable, they can use a built-in command that your shell provides support for called echo which takes a single argument which is the variable name:
bw: echo name
Yellow Jacket
You should use structs to store the variables. Please note that you can have an array of structs that would allow you to create something similar to a table.
Your shell only needs to support up to 10 variables with a max length of 50 characters per variable. Each variable can be stored as characters and does not need to be converted to a type such as an int or float. You do not need to handle an error condition such as a user entering another variable when the table is full. But, you should show an error if a variable does not exist. Below is an example:
bw: echo another name
Error: Variable 'another name' does not exist
The shell prompt that you show is up to you.
The test programs for this assignment are up to you. In order to test the job's functionality, I would create programs that sleep or use an alarm after an extended amount of time.
Solution:
Main:
#include < stdio.h>
#include < string.h>
#include < unistd.h>
#include < sys wait.h="">
#include < stdlib.h>
/**
* compile using gcc main.c -o shell
* Define a structure type to store variables
*
* **/
typedef struct vars{
char name[32];
char value[50];
} vars_t;
int main(int argc, char* argv[]){
vars_t vars_array[10];
int count = 0;
char name[32]; // Declare an array with length 32 to store variable name
char value[50]; // Declare an array with length 50 to store variable value
vars_t var;
/**
*
* Create an infinite loop to read input from user
*
* **/
while (1)
{
char command[82]; // Declare an array with length 82 to store command = name + value
printf("sh$ : "); // shell prompt
fgets(command,82,stdin); // get input from user
command[strcspn(command, "\n")] = 0; // replace \n with \x00
if (strstr(command,"=") != NULL) // look for = in the command
{
strncpy(name,strtok(command," = "),32); // use strtok to tokenize the string with delimitar first part of the token is name
strtok(NULL,"\""); // we need to tokenize with ' " ' since variable value are inside the ` " `
strncpy(value,strtok(NULL,"\""),50);
if (strlen(name) < 32 || strlen(value) < 50) // check length of variable name and value
{
if (count < 10) // we will store only 10 variables
{
strncpy(var.name,name,32); // store to our local variable we use stncpy to make sure there is no bufferoverflow
strncpy(var.value,value,50);
vars_array[count] = var;
count++;
}
}
}
else if (strstr(command, "echo") != NULL) // check for echo in the command
{
size_t i = 0;
char test = 1;
strtok(command," "); // we will tokenize command using space " " first token is echo and
char var_name[32]; // second token is the variable name
strncpy(var_name,strtok(NULL," "),32);
for (; i < count; i++)
{
if (!strcmp(var_name,vars_array[i].name)) // we will loop through variables arrays and look for
{ // requested variable
printf("%s\n",vars_array[i].value);
test = 0;
break;
}
}
if (i == count && test)
{
printf("Error: Variable '%s' does not exist\n", var_name); // if we can't find the variable print error
}
}
else{
pid_t pid = fork(); // create a child process
int status = 0;
char cmd[256] = "./"; // we will be running program from cwd
strcat(cmd,command); // concat program name and dir
if (pid != 0){ // check parent process or child process
waitpid(pid, &status, 0); // wait for the parent process
}
else{
char *argv[] = {cmd,NULL}; // setting up necessary arguments to call execve
char *env[] = {NULL};
execve(cmd, argv, env); // call to execve
exit(0); // make sure not to get fork bomb
}
}
}
}
Sleep:
#include < unistd.h>
#include < stdio.h>
/**
* compile using gcc sleep.c -o sleep
* to check if our shell is running the program in foreground mode and waiting for the child process
*
* **/
int main(int argc, char **argv){
printf("I am sleeping \n");
sleep(5);
_exit(0);
}