Question
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.). /* LIBRARY
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.).
/* LIBRARY SECTION */
#include <ctype.h> /* Character types */
#include <stdio.h> /* Standard buffered input/output */
#include <stdlib.h> /* Standard library functions */
#include <string.h> /* String operations */
#include <sys/types.h> /* Data types */
#include <sys/wait.h> /* Declarations for waiting */
#include <unistd.h> /* Standard symbolic constants and types */
#include <ctype.h> //includes isspace function
#include <sys/stat.h> // mkdir system call per manual
/* 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 execvp(path_to_exec, args) ? -1 : 0;
}
void imtheparent(pid_t child_pid, int run_in_background)
{
int child_return_val;
int 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_t pid_from_fork;
size_t n_read;
int i;
int exec_argc = 0;
int parser_state = STATE_SPACE;
int 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];
/* 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. */
scanf("%s", buffer);
parser_state = STATE_SPACE;
printf("Enter a line of command, up to 8 words seperated by space: ");
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.
*/
exec_argv[exec_argc] = NULL;
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 (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();
pid_from_fork = 0;
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() */
Step by Step Solution
3.50 Rating (153 Votes )
There are 3 Steps involved in it
Step: 1
My Answer LIBRARY SECTION include Character types include Standard buffered inputoutput include Standard library functions include String operations include Data types include Declarations for waiting ...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