[英]Handling arguments in a custom shell
I am currently working on a shell, implemented in C, for class that I hope to build upon over time and have run into a problem with executing my arguments. 目前,我正在为用C实现的Shell编写类,我希望该类可以随着时间的推移逐步构建,并且在执行参数时遇到问题。 My program uses
getchar()
to parse entries into the array of arguments and then executes the arguments using execvp()
. 我的程序使用
getchar()
将条目解析为参数数组,然后使用execvp()
执行参数。 The issue I have is in repeated entry of arguments any subsequent shorter arguments are concatenated with characters left in memory somewhere. 我遇到的问题是重复输入参数时,任何后续的较短参数都与内存中剩余的字符连接在一起。 Example below.
下面的例子。 And I am required to use
getchar
, which rules out alternate methods of getting the arguments. 而且我需要使用
getchar
,它排除了获取参数的替代方法。
//Global Variables
char argument[64];
char **argv;
int main(int argc, char** argv) {
mainloop(); //Loop that calls the commands
return (EXIT_SUCCESS);
}
void prompt(){ //Modular prompt
printf ("?:");
}
void mainloop(){ //Loop that calls the functions
while(1){
prompt();
argv = (char**)malloc(sizeof(char*)*64); //allocate memory for argv
getcommand(argument, argv);
if((strcmp(argv[0],"exit" )) == 0){ //check for exit
return 0;
}
executecommand();
printcommand();
//clearcommand();
//printcommand();
}
}
void getcommand(char* argument, char** argv){ //Parser for the command
int i=0,j=0;
char c;
char* token;
while((c = getchar()) != '\n' ){ //gets char and checks for end of line
argument[i] = c;
i++;
}
token = strtok(argument, " ,."); //tokenize the command
while (token != NULL){
argv[j] = token; //pass command to array of arguments
token = strtok(NULL, " ,.");
j++;
}
//argv[j] = "\0";
}
void executecommand(){ //Function to call fork and execute with errors
pid_t childpid = fork();
int returnStatus;
if(childpid == -1){ //Fail to Fork
printf("failed to fork");
exit(1);
}
else if(childpid == 0){ //Child process
if (execvp(*argv, argv) < 0){
printf("error executing\n");
exit(1);
}
else{ //Execute successful
printf("executed");
}
}
int c=(int)waitpid(childpid, &returnStatus, 0);
if (returnStatus == 0) // Verify child process terminated without error.
{
printf("The child process terminated normally. \n");
}
if (returnStatus == 1)
{
printf("The child process terminated with an error!.\n");
}
//realloc(argv,64);
}
void printcommand(){ //Test function to print arguments
int i = 0;
while(argv[i] != NULL){
printf("Argv%d: %s \n",i, argv[i] );
i++;
}
}
/*void clearcommand(){ //Function to clear up the memory, does not work
int i=0;
argv[0] = " \0";
argv[1] = " \0";
}*/
Example output: 输出示例:
?: ls -l
//functions as intended
?:echo
//argument returns as echol
This is the case for any entry which is shorter than a previous entry. 对于任何比上一个条目短的条目都是如此。 I do not understand why exec is reading the argument continuing after a
'\\0'
and i am sure that I am making a memory error here. 我不明白为什么exec在
'\\0'
之后继续读取参数,并且我确定自己在这里出错。 Help would be very much appreciated, I have been stuck on this one for a couple of days now. 非常感谢您的帮助,我已经坚持了几天。
You need to indicate the end of the argv
array with an element that contains a null pointer. 您需要使用包含空指针的元素来指示
argv
数组的末尾。 The commented-out line: 注释掉的行:
argv[j] = "\0";
should be: 应该:
argv[j] = NULL;
You also need to put a null terminator at the end of the argument
string. 您还需要在
argument
字符串的末尾放置一个空终止符。 You're getting l
when you do the echo
because argument
still contains the previous command line. 执行
echo
时会得到l
,因为argument
仍然包含前一个命令行。 So the first line sets argument
to: 因此,第一行将
argument
设置为:
ls -l
Then you overwrite the first 4 characters with echo
, so it becomes: 然后,您用
echo
覆盖前四个字符,因此它变为:
echol
So the full function would be: 因此完整的功能将是:
void getcommand(char* argument, char** argv){ //Parser for the command
int i=0,j=0;
char c;
char* token;
while((c = getchar()) != '\n' ){ //gets char and checks for end of line
argument[i] = c;
i++;
}
argument[i] = '\0';
token = strtok(argument, " ,."); //tokenize the command
while (token != NULL){
argv[j] = token; //pass command to array of arguments
token = strtok(NULL, " ,.");
j++;
}
argv[j] = NULL;
}
You could also use fgets()
to read a line of input, instead of calling getchar()
yourself. 您也可以使用
fgets()
读取一行输入,而不用自己调用getchar()
。
You should also check for the input being larger than the size of argument
. 您还应该检查输入是否大于
argument
的大小。
After the loop that reads an input line, you need to terminate the line with a NUL character. 在读取输入行的循环之后,您需要使用NUL字符终止该行。
while((c = getchar()) != '\n' ){ //gets char and checks for end of line
argument[i] = c;
i++;
}
argument[i] = '\0'; // <<---- terminate the input line
You also need to do what @Barmar said, but that's a different issue than the one that you describe in the question. 您还需要执行@Barmar所说的,但这与您在问题中描述的问题不同。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.