2015-05-24 6 views
1

Моя цель - сделать IPC между дочерним и родительским с помощью FIFO. Ребенок должен работатьКак запустить мой stdin через команду cut с помощью функции execl()?

execl ("/bin/cat", "cat", "/etc/passwd", (char *)0); 

перенаправить вывод на вход родителей и родитель должен выполнить эту команду:

cut -l : -f 1 

и выход этого в командную строку.

Прямо сейчас, я успешно связал свой FIFO и перенаправил вывод моего дочернего процесса на вход родителя. Я провел несколько тестов, и это соединение работает правильно. Проблема с execl для разреза, который должен выглядеть примерно так:

execlp("/bin/cut", "cut", "-l:", "-f", "1", NULL); 

, но я уверен, что это не так.

int cut(){ 

    // 
    int myfifo;  
    char buf[MAX_BUF]; 


    printf("\nCut opening FIFO"); 
    if((myfifo = open("/tmp/myfifo", O_RDONLY | O_TRUNC))<0){ 
     perror("open FIFO at cut"); 
     quit(EXIT_FAILURE);} 
    else{printf("\nCut has FIFO opened and is reading\n");} 

    //read(myfifo, buf, MAX_BUF); outputting buf goes as supposed to 

    if(dup2(myfifo, 0) < 0){ 
     perror("dup2 at cut"); 
     quit(EXIT_FAILURE);} 

    //read(STDIN_FILENO, buf, MAX_BUF); 

    close(myfifo); 

    execlp("/bin/cut", "cut", "-l:", "-f", "1", NULL); 

    //this is for testing buf, but i guess the program shouldn't even get here 
    printf("\nCut has received: %s\nAnd is closing FIFO", buf); 

    return -1; 

} 


int cat(){ 

    int myfifo; 
    //OPEN FIFO 
    printf("\nCat opening FIFO"); 
    if((myfifo = open("/tmp/myfifo", O_WRONLY | O_TRUNC))<0){ 
     perror("open FIFO at cat"); 
     quit(EXIT_FAILURE); 
    } 
    else{ 
     printf("\nCat has opened FIFO"); 
    //WRITE OUTPUT OF "cat \etc\passwd" TO FIFO 
     dup2(myfifo, 1); 
     execl ("/bin/cat", "cat", "/etc/passwd", (char *)0); 
    } 
    close(myfifo); 


    return 0; 
} 

Основное в настоящее время создает только функции fifo (mkfifo), forks() и вызывает функцию. Моя проблема может возникнуть с помощью stdin родителя (run cut), но я так не думаю, или, может быть, я предполагаю, что execl() читает непосредственно из stdin, и это не так. Я думаю, что это действительно так, потому что я не пишу «вырезать» через execl() правильно.

Любые поправки к коду, или даже то, как я выразил некоторые идеи, может указывать на то, что я не понимаю что-то должным образом, был бы очень признателен. Благодарим за помощь

+0

Почему вы используете FIFO или именованный канал вместо нормального, обычного, анонимного канала? –

+0

Какая версия 'cut' поддерживает опцию' -l'? Ни GNU 'cut', ни BSD (Mac OS X)' cut' не делает. Кажется, вы используете его как эквивалент опции -d' (разделитель полей), что имеет смысл для чтения файла паролей. Кроме того, 'cut' в'/bin' на вашем компьютере? Он находится в '/ usr/bin' на моем, и два каталога отличаются друг от друга. –

ответ

0

Как указано в комментарии, команда cut под GNU и BSD (и POSIX) не поддерживает параметр -l; нужный вам вариант - -d для разделителя.

Этот код работает для меня. На моей машине, /bin/cat правильно, но /usr/bin/cut правильно (не /bin/cut), так что я должен был составить с:

$ rmk cutcat UFLAGS=-DCUT_CMD=/usr/bin/cut && ./cutcat 
    gcc -O3 -g -std=c11 -Wall -Wextra -Werror -DCUT_CMD=/usr/bin/cut cutcat.c -o cutcat 
$ 

Это использует пользовательский вариант make (так называемый rmk) и пользовательские makefile, но расположение команды cut указывается в командной строке с помощью макроса UFLAGS (пользовательские флаги). Макросы и EXPAND являются неудобством, но не так много неприятностей, поскольку пытаются получить двойные кавычки за оболочкой, которая вызывает make (или rmk), а затем оболочку, которую make вызывает для запуска компилятора.

Код: выход

#include <stdio.h> 
#include <unistd.h> 
#include <fcntl.h> 
#include <stdlib.h> 
#include <sys/stat.h> 

#ifndef CUT_CMD 
#define CUT_CMD /bin/cut 
#endif 
#ifndef CAT_CMD 
#define CAT_CMD /bin/cat 
#endif 
#define EXPAND(x) #x 
#define STRING(x) EXPAND(x) 

static const char cut_cmd[] = STRING(CUT_CMD); 
static const char cat_cmd[] = STRING(CAT_CMD); 

static inline void quit(int status) { exit(status); } 

enum { MAX_BUF = 4096 }; 

static void cut(void) 
{ 
    int myfifo; 

    printf("\nCut opening FIFO"); 
    if ((myfifo = open("/tmp/myfifo", O_RDONLY | O_TRUNC)) < 0) 
    { 
     perror("open FIFO at cut"); 
     quit(EXIT_FAILURE); 
    } 
    printf("\nCut has FIFO opened and is reading\n"); 

    if (dup2(myfifo, 0) < 0) 
    { 
     perror("dup2 at cut"); 
     quit(EXIT_FAILURE); 
    } 

    close(myfifo); 

    execlp(cut_cmd, "cut", "-d:", "-f", "1", NULL); 
    fprintf(stderr, "Failed to execute %s\n", cut_cmd); 
    exit(1); 
} 

static 
void cat(void) 
{ 
    int myfifo; 

    printf("\nCat opening FIFO"); 
    if ((myfifo = open("/tmp/myfifo", O_WRONLY | O_TRUNC)) < 0) 
    { 
     perror("open FIFO at cat"); 
     quit(EXIT_FAILURE); 
    } 
    printf("\nCat has opened FIFO"); 
    dup2(myfifo, 1); 
    close(myfifo); 
    execl(cat_cmd, "cat", "/etc/passwd", (char *)0); 
    fprintf(stderr, "Failed to execute %s\n", cat_cmd); 
    exit(1); 
} 

int main(void) 
{ 
    mkfifo("/tmp/myfifo", 0600); 
    if (fork() == 0) 
     cat(); 
    else 
     cut(); 
    /*NOTREACHED*/ 
    fprintf(stderr, "You should not see this message\n"); 
    return 0; 
} 

Пример:

Большая усеченный

… 
nobody 
root 
daemon 
_uucp 
_taskgated 
_networkd 
… 

код действительно не очень отличается от того, что у вас было. Я удалил какой-то беспорядок. Я убедился, что close(myfifo) был выполнен cat(); это было не в оригинале. Это может быть важно.

+0

Да, когда я скопировал свой код, я использовал флаг -l, чтобы проверить ошибку, которую я получал с консоли. Виноват./Usr/bin/cut работал отлично. –