gpt4 book ai didi

c - 在自己的 c shell 中实现历史命令并重新运行旧命令

转载 作者:行者123 更新时间:2023-11-30 15:17:04 25 4
gpt4 key购买 nike

我正在制作自己的c shell。 shell 有一个历史功能,可以显示过去的命令。我已经做到了这一点,但我在重新运行旧命令时遇到问题。当用户输入 rr 时,我尝试重新运行最后一个命令。当rr = args[0]时,问题被标记在主函数中。

这是我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define MAX_LINE 80 /* 80 chars per line, per command, should be enough. */
#define HIST_SIZE 12

int place=0;

char cmd[MAX_LINE+1]; //used to keep copy of inBuffer to put in *hist

/** The setup() routine reads in the next command line string storing it in the input buffer.
The line is separated into distinct tokens using whitespace as delimiters. Setup also
modifies the args parameter so that it holds points to the null-terminated strings which
are the tokens in the most recent user command line as well as a NULL pointer, indicating the
end of the argument list, which comes after the string pointers that have been assigned to
args. ***/

void setup(char inputBuffer[], char *args[],int *background){

int length, /* # characters in the command line */
start, /* Beginning of next command parameter */
i, /* Index for inputBuffer arrray */
j; /* Where to place the next parameter into args[] */

/* Read what the user enters */
length = read(STDIN_FILENO, inputBuffer, MAX_LINE);

strcpy(cmd,inputBuffer);

start = -1;
j = 0;

if (length == 0)
exit(0); /* Cntrl-d was entered, end of user command stream */

if (length < 0){
perror("error reading command");
exit(-1); /* Terminate with error code of -1 */
}

/* Examine every character in the input buffer */
for (i = 0; i < length; i++) {

switch (inputBuffer[i]){
case ' ':
case '\t' : /* Argument separators */

if(start != -1){
args[j] = &inputBuffer[start]; /* Set up pointer */
j++;
}

inputBuffer[i] = '\0'; /* Add a null char; make a C string */
start = -1;
break;

case '\n': /* Final char examined */
if (start != -1){
args[j] = &inputBuffer[start];
j++;
}

inputBuffer[i] = '\0';
args[j] = NULL; /* No more arguments to this command */
break;

case '&':
*background = 1;
inputBuffer[i] = '\0';
break;

default : /* Some other character */
if (start == -1)
start = i;
}

}
args[j] = NULL; /* Just in case the input line was > 80 */
}

int displayHistory(char *hist[], int place){
int i=place;
int hist_num=1;

do{
if(hist[i]){
printf("%d %s", hist_num, hist[i]);
hist_num++;
}
i=(i+1)%HIST_SIZE;
} while(i != place);
return 0;
}


int main(void){
char inputBuffer[MAX_LINE]; /* Input buffer to hold the command entered */
char *args[MAX_LINE/2+1];/* Command line arguments */
int background; /* Equals 1 if a command is followed by '&', else 0 */

char *hist[HIST_SIZE];
int i=0;
for(i=0; i<HIST_SIZE; i++){
hist[i]=NULL;
}

while (1){ /* Program terminates normally inside setup */

background = 0;

printf("COMMAND--> "); /* Shell prompt */
fflush(0);

setup(inputBuffer, args, &background); /* Get next command */

if(strcmp(args[0],"rr")==0){
//rr does not go into *hist
}
else{
cmd[strlen(cmd)]='\0';
free(hist[place]);
hist[place]=strdup(cmd);
place=(place+1)%HIST_SIZE;
}
/* Fill in the code for these steps:
(1) Fork a child process using fork(),
(2) The child process will invoke execvp(),
(3) If background == 0, the parent will wait,
o/w returns to the setup() function. */

pid_t pid=fork();
int status;
if(pid<0){ //error forking
fprintf(stderr, "Fork Failed");
exit(-1);
}
else if(pid==0){ //child process
if(strcmp(inputBuffer,"h")==0){
displayHistory(hist,place);
}
else if(strcmp(args[0],"rr")==0){
printf("%s",hist[place-1]); //this is here to show that hist[place-1] does have the last command
execvp(hist[place-1], args); //PROBLEM HERE. why doesn't the hist[place-1]get executed?
}
else{
if(execvp(inputBuffer, args)<0){
printf("Invalid Command\n");
}
}
}
else{ //parent process
if(background==0){ //wait
waitpid(pid, &status, 0);
}
}
memset(inputBuffer,0,sizeof(inputBuffer)); //this is done so garbage chars from old input does not show up later when history is displayed
memset(cmd, 0, sizeof(cmd));
}
}

最好能解释一下为什么旧命令没有被执行。如果有一种真正让命令运行的方法那就太好了。

最佳答案

要提高循环缓冲区索引,请正确使用

place = (place + 1) % HIST_SIZE

但是你错误地后退了一步

hist[place - 1]

这应该是

hist [ (place + HIST_SIZE - 1) % HIST_SIZE ]

关于c - 在自己的 c shell 中实现历史命令并重新运行旧命令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32703531/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com