Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

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 history

Explanation / 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;

}

Hire Me For All Your Tutoring Needs
Integrity-first tutoring: clear explanations, guidance, and feedback.
Drop an Email at
drjack9650@gmail.com
Chat Now And Get Quote