1

My objective is to make an IPC between a child and parent through a FIFO. The child should run

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

redirect its output to the parents input and the parent should run this command:

cut -l : -f 1

and output this to command line.

Right now, I've successfully linked my FIFO and redirected the output of my child process to the input of the parent. I've done multiple tests and that connection is working properly. The problem is with the execl for the cut, which should look something like this:

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

but I'm pretty sure it isn't.

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;
}

The main currently only creates the fifo (mkfifo), forks() and calls the function. My problem could with the stdin of the parent (running cut), but I don't think so, or maybe I'm assuming execl() reads directly from the stdin and It doesn't. I think it's really bcause I'm not writing the "cut" through execl() properly.

Any corrections to the code, or even the way I expressed some ideas can indicate that I don't understand something properly, would be very appreciated. Thank you for helping

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • Why are you using a FIFO or named pipe instead of a sane, normal, ordinary, anonymous pipe? – Jonathan Leffler May 24 '15 at 03:06
  • Which version of `cut` supports the `-l` option? Neither GNU `cut` nor BSD (Mac OS X) `cut` does. You appear to be using it as equivalent to the `-d` option (field delimiter), which makes sense for reading a password file. Also, is `cut` in `/bin` on your machine? It's in `/usr/bin` on mine, and the two directories are different. – Jonathan Leffler May 24 '15 at 03:15

1 Answers1

0

As noted in a comment, the cut command under GNU and BSD (and POSIX) does not support a -l option; the option you need is -d for delimiter.

This code works for me. On my machine, /bin/cat is correct, but /usr/bin/cut is correct (not /bin/cut), so I had to compile with:

$ 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
$

That uses a custom variant of make (called rmk) and a custom makefile, but the location of the cut command is specified on the command line via the UFLAGS (user flags) macro. The STRING and EXPAND macros in the C code are a nuisance, but not as much of a nuisance as trying to get double quotes past the shell that invokes make (or rmk) and then the shell that make invokes to run the compiler.

The code:

#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;
}

Sample output:

Much truncated

…
nobody
root
daemon
_uucp
_taskgated
_networkd
…

The code is really not very different from what you had. I removed some clutter. I did ensure that close(myfifo) was executed by cat(); it wasn't in the original. It might be significant.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • Yes, when I copied my code I was using the -l flag to check the error i was getting from the console. My mistake. The /usr/bin/cut worked perfectly. – Francisco Monteiro May 24 '15 at 22:19