制作Linux shell时流重定向和管道
副标题[/!--empirenews.page--]
我有一个在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("%sn",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); } } 解决方法部分问题出在管道处理代码中 – 正如您所怀疑的那样.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,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"); } 第一个execvp()可能是为了使用argList,因为你刚刚复制了一些材料.但是,你已经复制了i个字节,而不是我的字符指针,并且你没有确保管道被切换并用空指针替换. memcpy(argList,i * sizeof(char *)); argList[i] = 0; execvp(argList[0],argList); 请注意,这还没有验证argList上没有缓冲区溢出;请注意,没有为argList分配空间;如果你使用它,你应该在执行memcpy()之前分配内存. 或者,更简单地说,您可以不使用副本.由于您处于子进程中,因此您可以简单地使用空指针替换argArray [i],而不会影响父进程或其他子进程: argArray[i] = 0; execvp(argArray[0],argArray); 您可能还会注意到execvp()的第二次调用使用了一个无法看到的变量pA;它几乎肯定是错误的初始化.作为一个适度的经验法则,你应该写: execvp(array[n],&array[n]); 上面的调用不符合这个模式,但如果你遵循它,你就不会出错. (编辑:威海站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |