Answered step by step
Verified Expert Solution
Link Copied!

Question

00
1 Approved Answer

Will someone please help me with this? Thanks! /* SMP1: Simple Shell */ /* LIBRARY SECTION */ #include /* Character types */ #include /* Standard

Will someone please help me with this? Thanks!

/* SMP1: Simple Shell */

/* LIBRARY SECTION */

#include /* Character types */

#include /* Standard buffered input/output */

#include /* Standard library functions */

#include /* String operations */

#include /* Data types */

#include /* Declarations for waiting */

#include /* Standard symbolic constants and types */

#include "smp1_tests.h" /* Built-in test system */

/* DEFINE SECTION */

#define SHELL_BUFFER_SIZE 256 /* Size of the Shell input buffer */

#define SHELL_MAX_ARGS 8 /* Maximum number of arguments parsed */

/* VARIABLE SECTION */

enum { STATE_SPACE, STATE_NON_SPACE }; /* Parser states */

int imthechild(const char *path_to_exec, char *const args[])

{

return execv(path_to_exec, args) ? -1 : 0;

}

void imtheparent(pid_t child_pid, int run_in_background)

{

int child_return_val, child_error_code;

/* fork returned a positive pid so we are the parent */

fprintf(stderr,

" Parent says 'child process has been forked with pid=%d' ",

child_pid);

if (run_in_background) {

fprintf(stderr,

" Parent says 'run_in_background=1 ... so we're not waiting for the child' ");

return;

}

wait(&child_return_val);

/* Use the WEXITSTATUS to extract the status code from the return value */

child_error_code = WEXITSTATUS(child_return_val);

fprintf(stderr,

" Parent says 'wait() returned so the child with pid=%d is finished.' ",

child_pid);

if (child_error_code != 0) {

/* Error: Child process failed. Most likely a failed exec */

fprintf(stderr,

" Parent says 'Child process %d failed with code %d' ",

child_pid, child_error_code);

}

}

/* MAIN PROCEDURE SECTION */

int main(int argc, char **argv)

{

pid_t shell_pid, pid_from_fork;

int n_read, i, exec_argc, parser_state, run_in_background;

/* buffer: The Shell's input buffer. */

char buffer[SHELL_BUFFER_SIZE];

/* exec_argv: Arguments passed to exec call including NULL terminator. */

char *exec_argv[SHELL_MAX_ARGS + 1];

/* Entrypoint for the testrunner program */

if (argc > 1 && !strcmp(argv[1], "-test")) {

return run_smp1_tests(argc - 1, argv + 1);

}

/* Allow the Shell prompt to display the pid of this process */

shell_pid = getpid();

while (1) {

/* The Shell runs in an infinite loop, processing input. */

fprintf(stdout, "Shell(pid=%d)> ", shell_pid);

fflush(stdout);

/* Read a line of input. */

if (fgets(buffer, SHELL_BUFFER_SIZE, stdin) == NULL)

return EXIT_SUCCESS;

n_read = strlen(buffer);

run_in_background = n_read > 2 && buffer[n_read - 2] == '&';

buffer[n_read - run_in_background - 1] = ' ';

/* Parse the arguments: the first argument is the file or command *

* we want to run. */

parser_state = STATE_SPACE;

for (exec_argc = 0, i = 0;

(buffer[i] != ' ') && (exec_argc < SHELL_MAX_ARGS); i++) {

if (!isspace(buffer[i])) {

if (parser_state == STATE_SPACE)

exec_argv[exec_argc++] = &buffer[i];

parser_state = STATE_NON_SPACE;

} else {

buffer[i] = '\0';

parser_state = STATE_SPACE;

}

}

/* run_in_background is 1 if the input line's last character *

* is an ampersand (indicating background execution). */

buffer[i] = '\0'; /* Terminate input, overwriting the '&' if it exists */

/* If no command was given (empty line) the Shell just prints the prompt again */

if (!exec_argc)

continue;

/* Terminate the list of exec parameters with NULL */

exec_argv[exec_argc] = NULL;

/* If Shell runs 'exit' it exits the program. */

if (!strcmp(exec_argv[0], "exit")) {

printf("Exiting process %d ", shell_pid);

return EXIT_SUCCESS; /* End Shell program */

} else if (!strcmp(exec_argv[0], "cd") && exec_argc > 1) {

/* Running 'cd' changes the Shell's working directory. */

/* Alternative: try chdir inside a forked child: if(fork() == 0) { */

if (chdir(exec_argv[1]))

/* Error: change directory failed */

fprintf(stderr, "cd: failed to chdir %s ", exec_argv[1]);

/* End alternative: exit(EXIT_SUCCESS);} */

} else {

/* Execute Commands */

/* Try replacing 'fork()' with '0'. What happens? */

pid_from_fork = fork();

if (pid_from_fork < 0) {

/* Error: fork() failed. Unlikely, but possible (e.g. OS *

* kernel runs out of memory or process descriptors). */

fprintf(stderr, "fork failed ");

continue;

}

if (pid_from_fork == 0) {

return imthechild(exec_argv[0], &exec_argv[0]);

/* Exit from main. */

} else {

imtheparent(pid_from_fork, run_in_background);

/* Parent will continue around the loop. */

}

} /* end if */

} /* end while loop */

return EXIT_SUCCESS;

} /* end main() */

1. Modify this MP so that you can use 'ls' instead of '/bin/ls' (i.e. the shell searches the path for the command to execute.).

2. Modify this MP so that the command prompt includes a counter that increments for each command executed (starting with 1). Your program should use the following prompt format: "Shell(pid=%1)%2> " %1=process pid %2=counter (You will need to change this into a correct printf format) Do not increment the counter if no command is supplied to execute.

3. Modify this MP so that '!NN' re-executes the n'th command entered. You can assume that NN will only be tested with values 1 through 9, no more than 9 values will be entered.

Shell(...)1> ls

Shell(...)2> !1 # re-executes ls

Shell(...)3> !2 # re-executes ls

Shell(...)4> !4 # prints "Not valid" to stderr

4. Modify the MP so that it uses waitpid instead of wait.

5. Create a new builtin command 'sub' that forks the program to create a new subshell. The parent shell should run the imtheparent() function just as if we were running an external command (like 'ls').

./shell

Shell(.n1..)1> sub

Shell(.n2..)1> exit # Exits sub shell

Shell(.n1..)1> exit # Exits back to 'real' shell

6. Create a new global variable to prevent a subshell from invoking a subshell invoking a subshell (i.e., more than 3 levels deep):

./shell

Shell(.n1..)1> sub

Shell(.n2..)1> sub

Shell(.n3..)1> sub # prints "Too deep!" to stderr

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access with AI-Powered Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Students also viewed these Databases questions