Question
Question 1: check the code below and answer the questions: #include #include #include #include #include #include #include // Function: void parse(char *line, char **argv) //
Question 1: check the code below and answer the questions:
#include
// Function: void parse(char *line, char **argv) // Purpose : This function takes in a null terminated string pointed to by //
void parse(char *line, char **argv) { // We will assume that the input string is NULL terminated. If it // is not, this code WILL break. The rewriting of whitespace characters // and the updating of pointers in argv are interleaved. Basically // we do a while loop that will go until we run out of characters in // the string (the outer while loop that goes until '\0'). Inside // that loop, we interleave between rewriting white space (space, tab, // and newline) with nulls ('\0') AND just skipping over non-whitespace. // Note that whenever we encounter a non-whitespace character, we record // that address in the array of address at argv and increment it. When // we run out of tokens in the string, we make the last entry in the array // at argv NULL. This marks the end of pointers to tokens. Easy, right? while (*line != '\0') // outer loop. keep going until the whole string is read { // keep moving forward the pointer into the input string until // we encounter a non-whitespace character. While we're at it, // turn all those whitespace characters we're seeing into null chars.
while (*line == ' ' || *line == '\t' || *line == ' ' || *line == ' ') { *line = '\0'; line++; }
// If I got this far, I MUST be looking at a non-whitespace character, // or, the beginning of a token. So, let's record the address of this // beginning of token to the address I'm pointing at now. (Put it in *argv) // then we'll increment argv so that the next time I store an address, it // will be in the next slot of the array of integers.
*argv++ = line; /* save the argument position */
// Ok... now let's just keep incrementing the input line pointer until // I'm looking at whitespace again. This "eats" the token I just found // and sets me up to look for the next.
while (*line != '\0' && *line != ' ' && *line != '\t' && *line != ' ' && *line !=' ') line++; /* skip the argument until ... */ }
// Heh, I ran out of characters in the input string. I guess I'm out of tokens. // So, whatever slot of the array at argv I'm pointing at? Yeah, put a NULL // there so we can mark the end of entries in the table.
*argv = NULL; /* mark the end of argument list */ }
void execute(char **argv) { if (argv[1] == NULL) printf("I would fork() a process to execute %s if I knew how ", *argv); else { printf("I would fork() a process to execute %s with the parameters ", *argv++); while (*argv != NULL) printf(" %s ", *argv++); printf("if I knew how "); } }
int main(void) { char line[1024]; // This is the string buffer that will hold // the string typed in by the user. This // string will be parsed. The shell will do // what it needs to do based on the tokens it // finds. Note that a user may NOT type in // an input line of greater than 1024 characters // because that's the size of the array. char *largv[64]; // This is a pointer to an array of 64 pointers to // char, or, an array of pointers to strings. // after parsing, this array will hold pointers // to memory INSIDE of the string pointed to by // the pointer line. argv[0] will be the string // version of the first token inside of line... // argv[1] will be the second... and so on... // See the routine parse() for details.
char shell_prompt[15]; // This string will hold the shell prompt string
// set the default prompt strcpy(shell_prompt, "SillyShell");
// The shell by default goes forever... so... while forever ;)
while (1) { printf("%s> ",shell_prompt); // display the shell prompt
fgets(line, 1024, stdin); // use the safe fgets() function to read // the user's command line. Why wouldn't // we use gets() here?
line[strlen(line)-1]='\0'; // This is a dirty hack. Figure it out maybe?
if (*line != '\0') // If something was actually typed, then do something... { // First, get all the addresses of all of the tokens inside the input line parse(line, largv); // parse the line to break it into token references
// Check the first token to see if there are any built in commands // we want to handle directly. Do this with an "if/then/else" ladder. // if we hit the end of the ladder, we assume the command line was requesting // an external program be run as a child process and do that.... if (strcmp(largv[0], "exit") == 0) exit(0); else if (strcmp(largv[0], "done") == 0) exit(0); else if (strcmp(largv[0], "newprompt") == 0) { if (largv[1] != NULL) strncpy(shell_prompt, largv[1], 15); else strncpy(shell_prompt, "SillyShell", 15); } else execute(largv); /* otherwise, execute the command */ } } }
Task One: Add Simple Program Calling (50 points) For task one, modify the program so that when the token pointed to by largv[0] is NOT a built-in command, your sillyshell will do the following: a) fork a process b) have the child process load the program in the file specified by largv[0] and be passed the appropriate command line arguments. c) have the parent wait on the completion of the child, then return to normal processing of input lines. Note, ALL of modifications you need to make could be done INSIDE the sillyshell routine called execute(). Also note that this task is nearly identical to a task we did during an in-class activity.
Task Two: Properly Handle Control Codes (20 points) Generally speaking, shells should NOT react to signals in the way that other processes might. For example, typing control-c USUALLY interrupts a running process. A shell should not shut down just because someone types control-c. Also, a shell USUALLY shuts down when someone types control-d. The template I gave you goes into an endless loop if you try that (yes, this is an intentional bug). For this task, you should make silly shell PROPERLY handle both control-c and control-d. When you are running silly shell, typing control-c should have no effect when you are at a prompt. Typing control-d should make sillyshell quit. Adding each capability is worth 10 points each. Note, youll want to handle the control-c problem with material you can find here: https://www.usna.edu/Users/cs/aviv/classes/ic221/s16/lec/19/lec.html You will want to handle the control-d problem by investigating the fgets() routine and finding out what it returns if anyone types control-d.
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started