Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

I need help with a command line interpreter application similar to the Terminal or Konsole in Ubuntu. When the application starts, it should display a

I need help with a command line interpreter application similar to the Terminal or Konsole in Ubuntu. When the application starts, it should display a command line prompt for the user to enter a command. It should only recognize the "exit" command, and it should exit when that command is entered. You will also add history support, allowing the user to use the Up and Down arrow keys to view and autocomplete previous commands, just like a real terminal. It should also be able to execute external commands, including support for piped commands (e.g. "command1 | command2 | command3"). The application should be able to execute commands like a real terminal. It should have : A prompt to accept user commands The ability to execute user commands from a list of accepted commands Error handling for the following situations: -Command execution returned an error -Issued command is not an accepted command -Arguments are in the wrong format (only "-o ARG" is accepted, no "/" notation or "--option" long notation) It should also maintain and manage environmental information such as the root directory, current directory, prompt, and environmental variables. A "help" command that lists all available commands and options, and a "version" command that provides author and version information.

The commands you must implement, along with their parameters, are:

"wc" with parameters: -c, -w, -l, -L "expand" with parameters: -t, -i, -a "env" with parameter: -u

It must also support pipes in the commands, e.g. > ls -l | grep -e 'tmp' | wc -l; support redirection in the commands, e.g. > ls -l > out.txt and must support both pipes and redirection in the same command line, e.g. > ls -l | grep -e 'tmp' > out.txt Here is my code but it's not working fully.

#include #include #include #include #include #include #include #include

#define MAX_ARGS 10

int check_command(char *command) { if (strcmp(command, "wc") == 0 || strcmp(command, "expand") == 0 || strcmp(command, "env") == 0) { return 1; } return 0; }

int check_arg_format(char **args) { for (int i = 1; args[i] != NULL; i++) { if (args[i][0] != '-') { fprintf(stderr, "Error: invalid argument format "); return 0; } if (strlen(args[i]) != 2) { fprintf(stderr, "Error: invalid argument format "); return 0; } } return 1; }

int execute_wc(char **args) { // create pipes int pipefd[2]; if (pipe(pipefd) == -1) { perror("pipe"); return 1; } // fork a child process pid_t pid; pid = fork(); if (pid == 0) // child process { // close write end of the pipe close(pipefd[1]);

// redirect standard input from the read end of the pipe dup2(pipefd[0], STDIN_FILENO);

// execute wc command with specified options char *cmd[] = {"wc", "-c", "-w", "-l", "-L", NULL}; if (execvp("wc", cmd) == -1) { perror("wc"); } exit(EXIT_FAILURE); } else if (pid < 0) // fork error { perror("wc"); return 1; } else // parent process { // close read end of the pipe close(pipefd[0]);

// write to the write end of the pipe write(pipefd[1], "some data ", 10);

// close write end of the pipe close(pipefd[1]);

// wait for child process to finish int status; do { waitpid(pid, &status, WUNTRACED); } while (!WIFEXITED(status&& !WIFSIGNALED(status))); } return 1;

}

int execute_expand(char **args) { int t_flag = 0, i_flag = 0, a_flag = 0; char *file_name = NULL; // parse arguments for (int i = 0; args[i] != NULL; i++) { if (strcmp(args[i], "-t") == 0) t_flag = 1; else if (strcmp(args[i], "-i") == 0) i_flag = 1; else if (strcmp(args[i], "-a") == 0) a_flag = 1; else file_name = args[i]; }

// execute expand command pid_t pid; int status; pid = fork(); if (pid == 0) // child process { // redirect input from file if specified if (file_name != NULL) { freopen(file_name, "r", stdin); }

// execute expand command with specified options char *cmd[] = {"expand", "-t", "-i", "-a", NULL}; int cmd_index = 1; if (!t_flag) cmd[cmd_index++] = NULL; if (!i_flag) cmd[cmd_index++] = NULL; if (!a_flag) cmd[cmd_index++] = NULL;

if (execvp("expand", cmd) == -1) { perror("expand"); } exit(EXIT_FAILURE); } else if (pid < 0) // fork error { perror("expand"); return 1; } else // parent process { // wait for child process to finish do { waitpid(pid, &status, WUNTRACED); } while (!WIFEXITED(status) && !WIFSIGNALED(status)); }

return 1; }

int execute_env(char **args) { int u_flag = 0; char *var_name = NULL; // parse arguments for (int i = 0; args[i] != NULL; i++) { if (strcmp(args[i], "-u") == 0) { u_flag = 1; var_name = args[i+1]; } }

// check if -u option is specified without a variable name if (u_flag && var_name == NULL) { fprintf(stderr, "Error: missing variable name for -u option "); return 1; } // execute env command pid_t pid; int status; pid = fork(); if (pid == 0) // child process { if (u_flag) { // unset environment variable if (unsetenv(var_name) != 0) { perror("env"); exit(EXIT_FAILURE); } } else { // print all environment variables char **envp; for (envp = __environ; *envp != NULL; envp++) { printf("%s ", *envp); } }

exit(EXIT_SUCCESS); } else if (pid < 0) // fork error { perror("env"); return 1; } else // parent process { // wait for child process to finish do { waitpid(pid, &status, WUNTRACED); } while (!WIFEXITED(status) && !WIFSIGNALED(status)); }

return 1; }

int execute_command(char **args) { if (args[0] == NULL) // empty command { return 1; } if (strcmp(args[0], "exit") == 0) // exit command { return 0; }

if (!check_command(args[0])) // invalid command { fprintf(stderr, "Error: command not found: %s ", args[0]); return 1; }

if (!check_arg_format(args)) // invalid argument format { return 1; }

// execute command if (strcmp(args[0], "wc") == 0) { return execute_wc(args); } else if (strcmp(args[0], "expand") == 0) { return execute_expand(args); } else if (strcmp(args[0], "env") == 0) { return execute_env(args); }

return 1; }

char **split_line(char *line) { int position = 0; char **tokens = malloc(MAX_ARGS * sizeof(char)); char *token; if (!tokens) { fprintf(stderr, "Error: allocation error "); exit(EXIT_FAILURE); }

token = strtok(line, " "); while (token != NULL) { tokens[position] = token; position++;

if (position >= MAX_ARGS) { fprintf(stderr, "Error: too many arguments "); exit(EXIT_FAILURE); }

token = strtok(NULL, " "); } tokens[position] = NULL; return tokens; }

int main(int argc, char **argv) { char **args; int status; do { // print prompt and read line printf("$> "); char *line = readline("");

// split line into arguments args = split_line(line);

// execute command status = execute_command(args); // free memory free(line); free(args); } while (status);

return 0; }

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored 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

Recommended Textbook for

Machine Learning And Knowledge Discovery In Databases European Conference Ecml Pkdd 2015 Porto Portugal September 7 11 2015 Proceedings Part 3 Lnai 9286

Authors: Albert Bifet ,Michael May ,Bianca Zadrozny ,Ricard Gavalda ,Dino Pedreschi ,Francesco Bonchi ,Jaime Cardoso ,Myra Spiliopoulou

1st Edition

3319234609, 978-3319234601

More Books

Students also viewed these Databases questions

Question

describe the process of competition,

Answered: 1 week ago