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

I have a simple shell code implemented by c (in ubuntu) I need to modify it to a

ID: 3858467 • Letter: I

Question

I have a simple shell code implemented by c (in ubuntu)

I need to modify it to add history feature which allows the user to access the most recently entered commands.

The user will be able to access up to 10 commands by using the feature.

The commands will be consecutively numbered starting at 1, and the numbering will continue past 10. For example, if the user has entered 35 commands, the 10 most recent commands will be numbered 26 to 35. The user will be able to list the command history by entering the command history

-------- The Code ---------

#include "sys/types.h"
#include "sys/wait.h"
#include "stdio.h"
#include "unistd.h"
#include "string.h"
#define MAXLINE 80 /* The maximum length command */


int main(void)

{
   char *args[MAXLINE/2 + 1]; /* command line arguments */
   char nn[MAXLINE];
   int shouldrun = 1; /* flag to determine when to exit program */
   int i=0;
   int j;


   while (shouldrun)

   {
       printf("OSH>");
       fflush(stdout);
        scanf ("%[^ ]%*c", nn);
        printf("input:%s ",nn);
        i = 0;
        int j;
        args[i] = strtok(nn," ");

        while (args[i] != NULL)
        {
          args[i] = strtok(NULL, " ");
          ++i;
        }

        if(strcmp(args[0], "exit") == 0)
          break;


        if(strcmp(args[i-1], "&") != 0)
        {

           //from the book example

           pid_t ID;
           ID = fork();
           if (ID < 0)
           {
               fprintf(stderr, "Fork failed ");
               return 1;
           }

           else if (ID == 0) /*child processes*/
           {
               execvp(args[0],args);
               for(int j=0;j<i;j++) //loop for arg
                   args[j] = NULL;
           }

           else
           {
               wait(NULL);
           }

        }

        else
        {
           pid_t ID;
           ID = fork();
           if(ID < 0)
           {
               fprintf(stderr,"FORK Failed ");
               return 1;
           }

           else if (ID == 0)
           {

               args[i-1] = NULL;
               execvp(args[0],args);
           }
           else
           {
               printf(" ");
           }
        }
   }

return 0;

}

-------- please help :( I tried many things but I couldn't done it

Explanation / Answer

The code as per your requrement is given below:

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

static char * cmd_history[CMD_HISTORY_SIZE];

static int cmd_history_count = 0;

static void exec_cmd(const char * line)

{

char * CMD = strdup(line);

char *params[10];

int argc = 0;

params[argc++] = strtok(CMD, " ");

while(params[argc-1] != NULL){

params[argc++] = strtok(NULL, " ");

}

argc--;

int background = 0;

if(strcmp(params[argc-1], "&") == 0){

background = 1;

params[--argc] = NULL;

}

int fd[2] = {-1, -1};

while(argc >= 3){

if(strcmp(params[argc-2], ">") == 0){

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;

}

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();

switch(pid){

case -1:

perror("fork");

break;

case 0:

if(fd[0] != -1){

if(dup2(fd[0], STDIN_FILENO) != STDIN_FILENO){

perror("dup2");

exit(1);

}

}

if(fd[1] != -1){

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);

}

static void add_to_history(const char * cmd){

if(cmd_history_count == (CMD_HISTORY_SIZE-1)){

int i;

free(cmd_history[0]);

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);

}

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] == '!')

index = cmd_history_count-1;

else{

index = atoi(&cmd[1]) - 1;

if((index < 0) || (index > cmd_history_count)){

fprintf(stderr, "No such command in history. ");

return;

}

}

printf("%s ", cmd);

exec_cmd(cmd_history[index]);

}

static void list_history(){

int i;

for(i=cmd_history_count-1; i >=0 ; i--){

printf("%i %s ", i+1, cmd_history[i]);

}

}

static void signal_handler(const int rc){

switch(rc){

case SIGTERM:

case SIGINT:

break;

case SIGCHLD:

while (waitpid(-1, NULL, WNOHANG) > 0);

break;

}

}

int main(int argc, char *argv[]){

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;

}

size_t line_size = 100;

char * line = (char*) malloc(sizeof(char)*line_size);

if(line == NULL){

perror("malloc");

return 1;

}

int inter = 0;

while(1){

if(!inter)

printf("mysh > ");

if(getline(&line, &line_size, stdin) == -1){

if(errno == EINTR){

clearerr(stdin);

inter = 1;

continue;

}

perror("getline");

break;

}

inter = 0;

int line_len = strlen(line);

if(line_len == 1){

continue;

}

line[line_len-1] = '';

if(strcmp(line, "exit") == 0){

break;

}else if(strcmp(line, "history") == 0){

list_history();

}else if(line[0] == '!'){

run_from_history(line);

}else{

add_to_history(line);

exec_cmd(line);

}

}

free(line);

return 0;

}

Hope this Helps

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