I need help asap history at the osh> prompt. As an example, assume that the hist
ID: 3721768 • Letter: I
Question
I need help asap
history at the osh> prompt. As an example, assume that the history consists of the commands (from most to least recent): ps, 1s -1, top, cal, vho, date The command history will output: 6 ps 5 1s -1 4 top 3 cal 2 who 1 date froeprogamd houl support two techniques for retrieving commands 1. When the user enters !, the most recent command in the history is 2. When the user enters a single followed by an integer N, the Nr the command history executed command in the history is executed. Continuing our example from above, if the user enters I I, the ps command will be performed; if the user enters !3, the command cal will be executed. Any command executed in this fashion should be echoed on the user's screen. The command should also be placed in the history buffer as the next command The program should also manage basic error handling. If there are no commands in the history, entering !! should result in a message "No commands in history."If there is no command corresponding to the number entered with the single , the program should output "No such comnand in historyExplanation / Answer
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <limits.h>
#include <errno.h>
#define CMD_HISTORY_SIZE 10 // size 10 for the 10 most-typed commands
static char * cmd_history[CMD_HISTORY_SIZE];
static int cmd_history_count = 0;
// function receives and process commands from user
static void exec_cmd(const char * line)
{
char * CMD = strdup(line);
char *params[10];
int argc = 0;
// parses command parameters
params[argc++] = strtok(CMD, " ");
while(params[argc-1] != NULL){ // As long as you get token
params[argc++] = strtok(NULL, " ");
}
argc--; // Decrement argc a little so that it doesn't take null parameter as token
// backplane operation controls
int background = 0;
if(strcmp(params[argc-1], "&") == 0){
background = 1; // set to run backplane
params[--argc] = NULL;
}
int fd[2] = {-1, -1};
while(argc >= 3){
// routing parameter control
if(strcmp(params[argc-2], ">") == 0){ // output
// open file function
fd[1] = open(params[argc-1], O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP|S_IWGRP);
if(fd[1] == -1){
perror("open");
free(CMD);
return;
}
// update parameter array
params[argc-2] = NULL;
argc -= 2;
}else if(strcmp(params[argc-2], "<") == 0){ // input
fd[0] = open(params[argc-1], O_RDONLY);
if(fd[0] == -1){
perror("open");
free(CMD);
return;
}
params[argc-2] = NULL;
argc -= 2;
}else{
break;
}
}
int status;
pid_t pid = fork(); // create a new transaction
switch(pid){
case -1:
perror("fork");
break;
case 0: // child
if(fd[0] != -1){ // if redirect is there
if(dup2(fd[0], STDIN_FILENO) != STDIN_FILENO){
perror("dup2");
exit(1);
}
}
if(fd[1] != -1){ // if redirect is there
if(dup2(fd[1], STDOUT_FILENO) != STDOUT_FILENO){
perror("dup2");
exit(1);
}
}
execvp(params[0], params);
perror("execvp");
exit(0);
default: // parent
close(fd[0]);close(fd[1]);
if(!background)
waitpid(pid, &status, 0);
break;
}
free(CMD);
}
// function add command to history
static void add_to_history(const char * cmd){
if(cmd_history_count == (CMD_HISTORY_SIZE-1)){
int i;
free(cmd_history[0]); // first command in history
// shift an index to other commands
for(i=1; i < cmd_history_count; i++)
cmd_history[i-1] = cmd_history[i];
cmd_history_count--;
}
cmd_history[cmd_history_count++] = strdup(cmd);
}
// function to execute history commands
static void run_from_history(const char * cmd){
int index = 0;
if(cmd_history_count == 0){
printf("No commands in history ");
return ;
}
if(cmd[1] == '!') // second character '!' get index of last command entered
index = cmd_history_count-1;
else{
index = atoi(&cmd[1]) - 1; // fetch from user for second character history index
if((index < 0) || (index > cmd_history_count)){ // If history doesn't have such index, print error
fprintf(stderr, "No such command in history. ");
return;
}
}
printf("%s ", cmd); // press index command is entered
exec_cmd(cmd_history[index]); // run the command
}
// function to print items in history buffer
static void list_history(){
int i;
for(i=cmd_history_count-1; i >=0 ; i--){
printf("%i %s ", i+1, cmd_history[i]);
}
}
// function for signal operations
static void signal_handler(const int rc){
switch(rc){
case SIGTERM:
case SIGINT:
break;
case SIGCHLD:
/* wait for all dead processes and if finished in another part of a child program
Use non-blocking call to block signal handler operation */
while (waitpid(-1, NULL, WNOHANG) > 0);
break;
}
}
// main function
int main(int argc, char *argv[]){
// grab the signals
struct sigaction act, act_old;
act.sa_handler = signal_handler;
act.sa_flags = 0;
sigemptyset(&act.sa_mask);
if( (sigaction(SIGINT, &act, &act_old) == -1) ||
(sigaction(SIGCHLD, &act, &act_old) == -1)){ // Ctrl^C
perror("signal");
return 1;
}
// allocate buffer for line
size_t line_size = 100;
char * line = (char*) malloc(sizeof(char)*line_size);
if(line == NULL){
perror("malloc");
return 1;
}
int inter = 0; // flag for row fetches
while(1){
if(!inter)
printf("mysh > ");
if(getline(&line, &line_size, stdin) == -1){ // read line to get input
if(errno == EINTR){
clearerr(stdin);
inter = 1;
continue; // return to loop without going down
}
perror("getline");
break;
}
inter = 0; // reset flag again
int line_len = strlen(line);
if(line_len == 1){ // if only new line is entered
continue;
}
line[line_len-1] = ''; // delete new line
if(strcmp(line, "exit") == 0){ // exit loop if input line is "exit"
break;
}else if(strcmp(line, "history") == 0){ // calls list_history function if input line is "history"
list_history();
}else if(line[0] == '!'){ // first character of the input line is "!" character calls run_from_history function
run_from_history(line);
}else{ // if not above
add_to_history(line); // call add_to_history function to append to input history
exec_cmd(line); // call exec_cmd function to get new line
}
}
free(line);
return 0;
}
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.