【发布时间】:2011-09-26 00:40:01
【问题描述】:
我有一个任务是在 C 中创建一个 Linux shell。目前,我被困在实现重定向和管道上。我到目前为止的代码如下。 main() 解析用户的输入。如果命令是内置的,则执行该命令。否则,将标记化的输入传递给 execute()(我知道我可能应该将内置命令拉入它们自己的函数中)。
execute() 的作用是遍历数组。如果遇到<、> 或|,它应该采取适当的措施。我试图正确工作的第一件事是管道。不过,我肯定做错了什么,因为我什至无法让它为一根管道工作。例如,一个示例输入/输出:
/home/ad/Documents> ls -l | grep sh
|: sh: No such file or directory
|
我的想法是让每个方向和管道仅适用于一种情况,然后通过使函数递归,我希望可以在同一命令行中使用多个重定向/管道。例如,我可以使用program1 < input1.txt > output1.txt 或ls -l | grep sh > output2.txt。
我希望有人能指出我在尝试管道时的错误,并可能就如何处理用户输入多个重定向/管道的情况提供一些指示。
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
int MAX_PATH_LENGTH = 1024; //Maximum path length to display.
int BUF_LENGTH = 1024; // Length of buffer to store user input
char * delims = " \n"; // Delimiters for tokenizing user input.
const int PIPE_READ = 0;
const int PIPE_WRITE = 1;
void execute(char **argArray){
char **pA = argArray;
int i = 0;
while(*pA != NULL) {
if(strcmp(argArray[i],"<") == 0) {
printf("<\n");
}
else if(strcmp(argArray[i],">") == 0) {
printf(">\n");
}
else if(strcmp(argArray[i],"|") == 0) {
int fds[2];
pipe(fds);
pid_t pid;
if((pid = fork()) == 0) {
dup2(fds[PIPE_WRITE], 1);
close(fds[PIPE_READ]);
close(fds[PIPE_WRITE]);
char** argList;
memcpy(argList, argArray, i);
execvp(argArray[0], argArray);
}
if((pid = fork()) == 0) {
dup2(fds[PIPE_READ], 0);
close(fds[PIPE_READ]);
close(fds[PIPE_WRITE]);
execvp(argArray[i+1], pA);
}
close(fds[PIPE_READ]);
close(fds[PIPE_WRITE]);
wait(NULL);
wait(NULL);
printf("|\n");
}
else {
if(pid == 0){
execvp(argArray[0], argArray);
printf("Command not found.\n");
}
else
wait(NULL);*/
}
*pA++;
i++;
}
}
int main () {
char path[MAX_PATH_LENGTH];
char buf[BUF_LENGTH];
char* strArray[BUF_LENGTH];
/**
* "Welcome" message. When mash is executed, the current working directory
* is displayed followed by >. For example, if user is in /usr/lib/, then
* mash will display :
* /usr/lib/>
**/
getcwd(path, MAX_PATH_LENGTH);
printf("%s> ", path);
fflush(stdout);
/**
* Loop infinitely while waiting for input from user.
* Parse input and display "welcome" message again.
**/
while(1) {
fgets(buf, BUF_LENGTH, stdin);
char *tokenPtr = NULL;
int i = 0;
tokenPtr = strtok(buf, delims);
if(strcmp(tokenPtr, "exit") == 0){
exit(0);
}
else if(strcmp(tokenPtr, "cd") == 0){
tokenPtr = strtok(NULL, delims);
if(chdir(tokenPtr) != 0){
printf("Path not found.\n");
}
getcwd(path, MAX_PATH_LENGTH);
}
else if(strcmp(tokenPtr, "pwd") == 0){
printf("%s\n", path);
}
else {
while(tokenPtr != NULL) {
strArray[i++] = tokenPtr;
tokenPtr = strtok(NULL, delims);
}
execute(strArray);
}
bzero(strArray, sizeof(strArray)); // clears array
printf("%s> ", path);
fflush(stdout);
}
}
【问题讨论】:
-
不要在 main 上执行隐式
int;明确:int main(void)或(更合理的是,一般来说,int main(int argc, char **argv)。不要这样做else {}不要留下注释掉的代码(尤其是在 SO 问题中)。更系统地缩进你的代码;整个函数体应至少缩进一级(除了左大括号和右大括号)。 -
感谢您的建议。我肯定在努力改进我的代码。
-
错误信息说:你正在尝试执行“sh”而不是“grep”。