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
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.