使用管道和fork

问题描述

我正在尝试使用C99 / gcc / Linux(unistd.h)编写一个程序,以从用户处接收Linux Shell命令,执行它们,检索其输出并将其存储在动态大小的数组/字符串中以进行输出/稍后进行修改

在下面的代码中,我一次将Shell命令一次传递给该函数char * cmd),希望使用一个链接的字符列表({{1 }})甚至是动态分配的足以容纳所有数据的字符串,因为某些命令可能返回5个字符(node * charLinkedList),而其他命令可能返回很多pwd )。

我已经彻底测试并确认以下各项可以正常工作:

  • 存储/检索/打印到字符链接列表
  • 派生该进程并使子进程执行命令(不使用管道)
  • 执行shell命令并将其打印到控制台(不使用管道)
  • 执行带有和不带有不同长度参数的shell命令

什么不起作用:

  • 将每个命令的输出插入变量/链表
cat [file]

我尝试使用#define READPIPE 0 #define WRITEPIPE 1 /* % Inputs % * char * cmd : a string containing the command * node * charLinkedList : a linked list of char to store the output */ void execCmd(char * cmd,node * charLinkedList) { int fd[2]; // fd is the pipe pid_t pid; // pid is for holding the process ID char* shellOutput; // shellOutput is a string to store the output in,it's //> not being used in this code but I'm ok using it in place //> of my character linked list (charLinkedList) if(pipe(fd) == -1){ fprintf(stderr,"Pipe Failed"); } /* Logic for separating the command from it's arguments */ int argNum = argumentCounter(cmd); // argNum counts the arguments and returns it char * args[argNum + 2]; // for holding the arguments that we will be passing later on char ** delimArguments; // to hold the deliminated command string if(argNum > 0) { //if there are arguments with the command delimArguments = stringSplitter(cmd,' '); //stringSplitter splits the string at a deliminer and returns it for (int i = 0; i < (argNum + 1); i++){ //loads the commands into an array args[i] = *(delimArguments + i); // this logic has been tested and works } args[argNum + 1] = 0; // please ignore this spaghetti code,I'll clean } //> it up later I promise /* Forking & executing the commands */ pid = fork(); if(pid == -1) { printf("FORK Failed\n"); } if (pid == 0) { /* Child Process */ close(fd[READPIPE]); // same as close(fd[0]) /* This next if/else statement is for toggling between whether or not the * command has arguments or not. It's a mess and I'll 100% be merging * this at a later date. */ if (argNum > 0){ /* command with arguments */ //i.e. ls -l -a dup2(fd[WRITEPIPE],STDOUT_FILENO); //duplicate the STDOUT to the write end of the pipe (fd[1]) execvp(args[0],args); //execute the command and it's arguments } else { /* command without argument */ //i.e. ls dup2(fd[WRITEPIPE],STDOUT_FILENO); //duplicate the STDOUT to the write end of the pipe (fd[1]) execlp(cmd,cmd,NULL); //execute the command } close(fd[WRITEPIPE]); //if something goes wrong and the code gets to here,close the pipe return; //return to int main() function; don't continue this one as the child } else { /* Parent Process */ close(fd[WRITEPIPE]); //closing the writing side of the pipe fcntl(fd[READPIPE],F_SETFL,fcntl(fd[READPIPE],F_GETFL) | O_NONBLOCK); //using fcntl to get the file descriptor of the pipe FILE * theOutput; // creating a file to point at the output theOutput = fdopen(fd[READPIPE],"r"); // opening the stream from the child process char buffer; // a char for grabbing output one character at a time while((buffer = fgetc(theOutput)) != NULL) // while we havn't hit the end of the file { addToQueue(charLinkedList,buffer); // one by one add each character of the output to } //> the linked list queue printLinkedList(charLinkedList); //outputting the list to verify the output captured } read()函数,尽管无法正常工作。我实现了dup2以将write()克隆到管道中,然后从那里开始与之战斗,试图使其正常工作(没有成功)。我发现another post建议按照目前的方式来做事,尽管我不知道如何从文件描述符中获取输出

我尝试同时使用STDOUTfgetc都无济于事,这有点困扰。这是正确的方法,还是有更好的方法将子进程的fgets输出输出到父进程的字符串/链接列表/ 变量中?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)