Я пытаюсь «объединить» две команды в одну (несуществующую) команду и передать ее. Это я имею в виду … Предположим, что у вас есть эти две команды: grep text out.txt
grep text out.txt
, (несуществующая) команда, которая могла бы представлять эти две команды, могла бы быть чем-то вроде (grepwc -l < file.txt)
который затем выводит количество строк в out.txt. В основном эти команды (grepwc) должны иметь такое же поведение, как grep text out.txt
grep text out.txt
но короче.
Я пробовал что-то вроде этого, но я думаю, что мой подход далеко не для достижения цели. Я использую структуру с именем commlist, которая содержит команды, уже обработанные cmd, argc и argv. inputfile и outputfile – это пути к файлам, используемым для open ().
Я использую структуру.
typedef struct command { char *cmd; int argc; char *argv[MAXARGS+1]; struct command *next; } COMMAND;
и код:
void execute(COMMAND *commlist) { int fd[2]; pid_t pid; int n_pipes=2; //pipes needed COMMAND *aux = commlist; int i; for(i=0;i<n_pipes; i++){ int oldfd = 0; if(fd[0]!=0){ close(fd[1]); oldfd = fd[0]; } pipe(fd); if((pid=fork())cmd == "grepwc"){ if(i==0){ if(execlp("grep","grep","celio",NULL)<0){ perror("Bad command"); exit(1); } } if(i==1){ if(execlp("wc","wc","-l",NULL) < 0){ perror("Bad command"); exit(1); } } } }//child } }
имеютvoid execute(COMMAND *commlist) { int fd[2]; pid_t pid; int n_pipes=2; //pipes needed COMMAND *aux = commlist; int i; for(i=0;i<n_pipes; i++){ int oldfd = 0; if(fd[0]!=0){ close(fd[1]); oldfd = fd[0]; } pipe(fd); if((pid=fork())cmd == "grepwc"){ if(i==0){ if(execlp("grep","grep","celio",NULL)<0){ perror("Bad command"); exit(1); } } if(i==1){ if(execlp("wc","wc","-l",NULL) < 0){ perror("Bad command"); exit(1); } } } }//child } }
Полный код находится здесь:
http://pastebin.com/tYGWwUjS
http://pastebin.com/sNJhEg2Y
Ваш подход действительно немного сложнее. Это может быть достигнуто только с одним дочерним процессом и с одним каналом (как в исходной команде оболочки). Давайте посмотрим на это:
grep text < file.txt | wc -l > out.txt
это
Но достаточно разблокировать только один процесс, так как нам не нужно возвращаться к родительскому процессу. Это приводит к следующему коду:
#include #include int main (void) { int fd[2]; pipe(fd); if (fork()) { // Child process dup2(fd[0], 0); // wc reads from the pipe close(fd[0]); close(fd[1]); execlp("wc", "wc", "-l", NULL); } else { // Parent process dup2(fd[1], 1); // grep writes to the pipe close(fd[0]); close(fd[1]); execlp("grep", "grep", "celio", NULL); } exit(EXIT_FAILURE); }
exit()
достигается только в случае сбоя одного из execlp()
.