Question
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
#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
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