Fork Exec Pipe: HOW??? - Unix

This is a discussion on Fork Exec Pipe: HOW??? - Unix ; Hallo there! I heard about fork() exec() and pipe() and i thought they would be the solutions to my problem: i'd like to write a C prog that interacts with gnuplot, sending commands to it, like plot, replot etc... The ...

+ Reply to Thread
Results 1 to 20 of 20

Thread: Fork Exec Pipe: HOW???

  1. Fork Exec Pipe: HOW???

    Hallo there!

    I heard about fork() exec() and pipe() and i thought they would be the
    solutions
    to my problem: i'd like to write a C prog that interacts with gnuplot,
    sending
    commands to it, like plot, replot etc...
    The problem is that i'm very unfamiliar with those functions and with
    the
    phylosophy that lies beneath them.

    Can you please suggest me something, writing some skeleton code
    or could you tell me where I can find some good literature about those
    syscalls?

    Thank you so much!!!

    Phoenix87.


  2. Re: Fork Exec Pipe: HOW???

    On Nov 9, 10:26 am, Phoenix87 wrote:
    > Hallo there!
    >
    > I heard about fork() exec() and pipe() and i thought they would be the
    > solutions
    > to my problem: i'd like to write a C prog that interacts with gnuplot,
    > sending
    > commands to it, like plot, replot etc...
    > The problem is that i'm very unfamiliar with those functions and with
    > the
    > phylosophy that lies beneath them.
    >
    > Can you please suggest me something, writing some skeleton code
    > or could you tell me where I can find some good literature about those
    > syscalls?


    For your purposes, popen() and pclose() will probably be sufficient,
    and much easier to use. Start by reading their man pages.


  3. Re: Fork Exec Pipe: HOW???

    On 10 Nov, 00:38, fjbl...@yahoo.com wrote:
    > On Nov 9, 10:26 am, Phoenix87 wrote:
    >
    > > Hallo there!

    >
    > > I heard about fork() exec() and pipe() and i thought they would be the
    > > solutions
    > > to my problem: i'd like to write a C prog that interacts with gnuplot,
    > > sending
    > > commands to it, like plot, replot etc...
    > > The problem is that i'm very unfamiliar with those functions and with
    > > the
    > > phylosophy that lies beneath them.

    >
    > > Can you please suggest me something, writing some skeleton code
    > > or could you tell me where I can find some good literature about those
    > > syscalls?

    >
    > For your purposes, popen() and pclose() will probably be sufficient,
    > and much easier to use. Start by reading their man pages.


    yeah! i solved with popen. Thank you!


  4. Re: Fork Exec Pipe: HOW???

    Phoenix87 wrote:

    # yeah! i solved with popen. Thank you!

    In case you're interested in it for the future, it's pipe/fork/exec,
    something like

    enum {R,W,N};
    int input[N],output[N];
    if (pipe(input)<0) {error processing}
    if (pipe(output)<0) {error processing}
    int child = fork();
    if (child<0) {
    error processing
    }else if (child==0) {
    close(0); dup(input[R]); close(input[0]); close(input[1]);
    close(1); dup(output[W]); close(output[0]); close(output[1]);
    exec...(...);
    error processing
    }else {
    close(input[R]); close(output[W]);
    write(input[W],...)...
    read(output[R],...)...
    close(input[W]); close(output[R]);
    wait...(...);
    }

    --
    SM Ryan http://www.rawbw.com/~wyrmwif/
    What kind of convenience store do you run here?

  5. Re: Fork Exec Pipe: HOW???

    SM Ryan schrieb:
    > close(0); dup(input[R]); close(input[0]); close(input[1]);
    > close(1); dup(output[W]); close(output[0]); close(output[1]);


    dup(2) does not guarantee that the file descriptors returned are the
    next ones available. It could well be that the two dup's return FDs 3
    and 4, leaving 0 and 1 unused.

    Better use dup2(2), and don't forget to save the original stdin/stdout
    using dup(2) to bend them back for error processing.

    Greetings,
    Johannes

    --
    "PS: Ein Realname wäre nett. Ich selbst nutze nur keinen, weil mich die
    meisten hier bereits mit Namen kennen." -- Markus Gronotte aka "Makus"
    aka "Kosst Amojan" aka "maqqusz" in de.sci.electronics
    <45608268$0$5719$9b4e6d93@newsspool3.arcor-online.net>

  6. Re: Fork Exec Pipe: HOW???

    In article ,
    Johannes Bauer wrote:

    > SM Ryan schrieb:
    > > close(0); dup(input[R]); close(input[0]); close(input[1]);
    > > close(1); dup(output[W]); close(output[0]); close(output[1]);

    >
    > dup(2) does not guarantee that the file descriptors returned are the
    > next ones available. It could well be that the two dup's return FDs 3
    > and 4, leaving 0 and 1 unused.


    SUS3 requires that the returned FD is the lowest one available.

    --
    Barry Margolin, barmar@alum.mit.edu
    Arlington, MA
    *** PLEASE post questions in newsgroups, not directly to me ***
    *** PLEASE don't copy me on replies, I'll read them in the group ***

  7. Re: Fork Exec Pipe: HOW???

    Barry Margolin schrieb:

    > SUS3 requires that the returned FD is the lowest one available.


    I have no idea what SUS3 is.

    But it doesn't matter anyways, as POSIX does not guarantee anything.

    Greetings,
    Johannes

    --
    "PS: Ein Realname wäre nett. Ich selbst nutze nur keinen, weil mich die
    meisten hier bereits mit Namen kennen." -- Markus Gronotte aka "Makus"
    aka "Kosst Amojan" aka "maqqusz" in de.sci.electronics
    <45608268$0$5719$9b4e6d93@newsspool3.arcor-online.net>

  8. Re: Fork Exec Pipe: HOW???

    Barry Margolin schrieb:

    > SUS3 requires that the returned FD is the lowest one available.


    Alright, thought about it. You mean the Unix Specification. Why doesn't
    POSIX state anything about this, then? Seems odd.

    Greetings,
    Johannes

    --
    "PS: Ein Realname wäre nett. Ich selbst nutze nur keinen, weil mich die
    meisten hier bereits mit Namen kennen." -- Markus Gronotte aka "Makus"
    aka "Kosst Amojan" aka "maqqusz" in de.sci.electronics
    <45608268$0$5719$9b4e6d93@newsspool3.arcor-online.net>

  9. Re: Fork Exec Pipe: HOW???

    Johannes Bauer wrote:
    > Barry Margolin schrieb:
    >
    >> SUS3 requires that the returned FD is the lowest one available.

    >
    > Alright, thought about it. You mean the Unix Specification. Why doesn't
    > POSIX state anything about this, then? Seems odd.


    I don't know, but let's take it as a given that both dup() and dup2() work.
    I maintain that dup2() should be preferred in production code because it
    makes the code's logic more explicit and thus easier to understand.

    - Logan

  10. Re: Fork Exec Pipe: HOW???

    Johannes Bauer wrote:

    >> SUS3 requires that the returned FD is the lowest one available.

    >
    > Alright, thought about it. You mean the Unix Specification. Why doesn't
    > POSIX state anything about this, then? Seems odd.


    Since SUS says it, so does POSIX. SUSv3 and POSIX.1-2001 are two
    names for the same document.

    --
    Geoff Clare

  11. Re: Fork Exec Pipe: HOW???

    In article <47374ccc$0$19585$4c368faf@roadrunner.com>,
    Logan Shaw wrote:

    > Johannes Bauer wrote:
    > > Barry Margolin schrieb:
    > >
    > >> SUS3 requires that the returned FD is the lowest one available.

    > >
    > > Alright, thought about it. You mean the Unix Specification. Why doesn't
    > > POSIX state anything about this, then? Seems odd.

    >
    > I don't know, but let's take it as a given that both dup() and dup2() work.
    > I maintain that dup2() should be preferred in production code because it
    > makes the code's logic more explicit and thus easier to understand.


    I agree that dup2() is generally preferable when you care what FD is
    used. It's also likely to simplify the code, since you don't have to
    close the stdXXX FD before dup2() -- it will do it automatically for you.

    --
    Barry Margolin, barmar@alum.mit.edu
    Arlington, MA
    *** PLEASE post questions in newsgroups, not directly to me ***
    *** PLEASE don't copy me on replies, I'll read them in the group ***

  12. Re: Fork Exec Pipe: HOW???

    On Nov 11, 12:35 pm, SM Ryan tango.fake.org> wrote:
    > Phoenix87 wrote:
    >
    > # yeah! i solved with popen. Thank you!
    >
    > In case you're interested in it for the future, it's pipe/fork/exec,
    > something like
    >
    > enum {R,W,N};
    > int input[N],output[N];
    > if (pipe(input)<0) {error processing}
    > if (pipe(output)<0) {error processing}
    > int child = fork();
    > if (child<0) {
    > error processing}else if (child==0) {
    >
    > close(0); dup(input[R]); close(input[0]); close(input[1]);
    > close(1); dup(output[W]); close(output[0]); close(output[1]);
    > exec...(...);
    > error processing}else {
    >
    > close(input[R]); close(output[W]);
    > write(input[W],...)...
    > read(output[R],...)...
    > close(input[W]); close(output[R]);
    > wait...(...);
    >
    > }
    >
    > --
    > SM Ryanhttp://www.rawbw.com/~wyrmwif/
    > What kind of convenience store do you run here?


    Thanks for your replies!!! I apreciate them. But it looks like i
    didn't understand something.
    Here my code

    #include
    #include
    #include

    enum {R,W,N};

    int main(void)
    {
    int input[N];
    int output[N];
    pid_t pid;
    char *args[] = {"gnuplot",/*"-persist",*/NULL};
    extern char **environ;
    char c;

    pid = fork();

    if (pipe(input) == -1) {
    perror("pipe(2)");
    exit(EXIT_FAILURE);
    }

    if (pipe(output) == -1) {
    perror("pipe(2)");
    exit(EXIT_FAILURE);
    }

    pid = fork();

    if (pid == -1) {
    perror("fork(2)");
    exit(EXIT_FAILURE);
    }

    if (pid == 0) { /* Child Process */
    close(0);
    dup2(input[R], 0);
    close(input[R]);
    close(input[W]);

    close(1);
    dup2(output[W], 1);
    close(output[R]);
    close(output[W]);

    execlp("gnuplot","gnuplot","-persist",NULL);
    perror("execlp(3)");
    exit(EXIT_FAILURE);
    }
    else { /* Parent process */
    close(input[R]);
    close(output[W]);
    write(input[W],"plsot sin(x)\n",128);
    while (read(output[R],&c,1) > 0)
    fputc('a',stdout);

    close(input[W]);
    close(output[R]);
    wait(NULL);

    exit(EXIT_SUCCESS);
    }

    return EXIT_SUCCESS;
    }

    The plot command is intentionally wrong, because i want
    to hear gnuplot lamenting for syntax errors.
    Something strange is that if I suppy the correct command
    I get TWO plot windows showing a sine curve.
    The same appens to the error messages which appear twice.
    The pipe I used to read from gnuplot seems not to work
    because I can't see any 'a's on screen.

    What's wrong with my code?

  13. Re: Fork Exec Pipe: HOW???

    On Nov 26, 2:49 pm, Phoenix87 wrote:

    > Thanks for your replies!!! I apreciate them. But it looks like i
    > didn't understand something.
    > Here my code
    >
    > #include
    > #include
    > #include
    >
    > enum {R,W,N};
    >
    > int main(void)
    > {
    > int input[N];
    > int output[N];
    > pid_t pid;
    > char *args[] = {"gnuplot",/*"-persist",*/NULL};
    > extern char **environ;
    > char c;
    >
    > pid = fork();
    >
    > if (pipe(input) == -1) {
    > perror("pipe(2)");
    > exit(EXIT_FAILURE);
    > }
    >
    > if (pipe(output) == -1) {
    > perror("pipe(2)");
    > exit(EXIT_FAILURE);
    > }
    >
    > pid = fork();
    >
    > if (pid == -1) {
    > perror("fork(2)");
    > exit(EXIT_FAILURE);
    > }
    >
    > if (pid == 0) { /* Child Process */
    > close(0);
    > dup2(input[R], 0);
    > close(input[R]);
    > close(input[W]);
    >
    > close(1);
    > dup2(output[W], 1);
    > close(output[R]);
    > close(output[W]);
    >
    > execlp("gnuplot","gnuplot","-persist",NULL);
    > perror("execlp(3)");
    > exit(EXIT_FAILURE);
    > }
    > else { /* Parent process */
    > close(input[R]);
    > close(output[W]);
    > write(input[W],"plsot sin(x)\n",128);
    > while (read(output[R],&c,1) > 0)
    > fputc('a',stdout);
    >
    > close(input[W]);
    > close(output[R]);
    > wait(NULL);
    >
    > exit(EXIT_SUCCESS);
    > }
    >
    > return EXIT_SUCCESS;
    >
    > }
    >
    > The plot command is intentionally wrong, because i want
    > to hear gnuplot lamenting for syntax errors.
    > Something strange is that if I suppy the correct command
    > I get TWO plot windows showing a sine curve.
    > The same appens to the error messages which appear twice.
    > The pipe I used to read from gnuplot seems not to work
    > because I can't see any 'a's on screen.
    >
    > What's wrong with my code?


    You called fork() twice. Cut/paste error?

  14. Re: Fork Exec Pipe: HOW???

    Phoenix87 writes:

    [...]

    > #include
    > #include
    > #include
    >
    > enum {R,W,N};
    >
    > int main(void)
    > {
    > int input[N];
    > int output[N];
    > pid_t pid;
    > char *args[] = {"gnuplot",/*"-persist",*/NULL};
    > extern char **environ;
    > char c;
    >
    > pid = fork();

    ^^^^^^^^^^^^


    >
    > if (pipe(input) == -1) {
    > perror("pipe(2)");
    > exit(EXIT_FAILURE);
    > }
    >
    > if (pipe(output) == -1) {
    > perror("pipe(2)");
    > exit(EXIT_FAILURE);
    > }
    >
    > pid = fork();

    ^^^^^^^^^^^^

    The first call to fork creates a 2nd process running your program
    which executes all code following this fork, hence, the two 'gnuplots'.

    >
    > if (pid == -1) {
    > perror("fork(2)");
    > exit(EXIT_FAILURE);
    > }
    >
    > if (pid == 0) { /* Child Process */
    > close(0);
    > dup2(input[R], 0);


    The close is redundant. dup2 closes the descriptor passed as 2nd
    argument.

    > close(input[R]);
    > close(input[W]);
    >
    > close(1);
    > dup2(output[W], 1);
    > close(output[R]);
    > close(output[W]);


    [...]

    > The pipe I used to read from gnuplot seems not to work
    > because I can't see any 'a's on screen.


    You need to redirect stderr (descriptor 2) to capture error
    output. Additionally, gnuplot apparently reads until an EOF
    when not reading from the terminal and your program block waiting for
    gnuplot output before signalling an EOF on the pipe going to the child
    process. A loop which works could be:

    close(input[R]);
    close(output[W]);
    write(input[W],"pslot sin(x)\n",128);
    close(input[W]);
    while (read(output[R],&c,1) > 0)
    fputc('a',stdout);

    close(output[R]);
    wait(NULL);

    Additionally, it is redundant to close descriptors before exiting a
    process, because they will be closed automatically.

  15. Re: Fork Exec Pipe: HOW???

    Thank you! That worked great!!!
    I thought gnuplot would have used stdout, but
    thinking of it it makes more sense to report errors
    on stderr

    > The first call to fork creates a 2nd process running your program
    > which executes all code following this fork, hence, the two 'gnuplots'.


    Uh I didn't notice that I had to calls to fork().

    > close(input[R]);
    > close(output[W]);
    > write(input[W],"pslot sin(x)\n",128);
    > close(input[W]);
    > while (read(output[R],&c,1) > 0)
    > fputc('a',stdout);
    >
    > close(output[R]);
    > wait(NULL);


    Yeah. This worked!
    Thank you very much!

    Actually I need to send more than just one command to gnuplot,
    so if I close the pipe immediatly after the while loop, i can't
    send commands any more. How can I solve this?

  16. Re: Fork Exec Pipe: HOW???

    Phoenix87 writes:

    [...]

    >> close(input[R]);
    >> close(output[W]);
    >> write(input[W],"pslot sin(x)\n",128);
    >> close(input[W]);
    >> while (read(output[R],&c,1) > 0)
    >> fputc('a',stdout);
    >>
    >> close(output[R]);
    >> wait(NULL);

    >
    > Yeah. This worked!
    > Thank you very much!
    >
    > Actually I need to send more than just one command to gnuplot,
    > so if I close the pipe immediatly after the while loop, i can't
    > send commands any more. How can I solve this?


    Try a pseudo-terminal instead of two pipes (=> pty(4) for Linux).


  17. Re: Fork Exec Pipe: HOW???

    > Try a pseudo-terminal instead of two pipes (=> pty(4) for Linux).

    Now I'm trying with pseudo-terminal, but I think i don't know how
    to use it:

    #define _XOPEN_SOURCE

    #include
    #include
    #include
    #include
    #include

    int main(void)
    {
    int fd_master, fd_slave;
    char *cb_slave;
    char buffer[128];
    int count;

    fd_master = getpt();
    grantpt(fd_master);
    unlockpt(fd_master);
    cb_slave = ptsname(fd_master);
    fd_slave = open(cb_slave,O_RDWR);

    count = write(fd_master, "gnuplot -persist\n", 128);
    count = read(fd_master,buffer,sizeof(buffer));
    count = write(fd_master, "p sin(x)\n",128);

    close(fd_slave);
    close(fd_master);

    return EXIT_SUCCESS;
    }

    I can't see any plots around with this code


  18. Re: Fork Exec Pipe: HOW???

    Phoenix87 writes:
    >> Try a pseudo-terminal instead of two pipes (=> pty(4) for Linux).

    >
    > Now I'm trying with pseudo-terminal, but I think i don't know how
    > to use it:
    >
    > #define _XOPEN_SOURCE
    >
    > #include
    > #include
    > #include
    > #include
    > #include
    >
    > int main(void)
    > {
    > int fd_master, fd_slave;
    > char *cb_slave;
    > char buffer[128];
    > int count;
    >
    > fd_master = getpt();
    > grantpt(fd_master);
    > unlockpt(fd_master);
    > cb_slave = ptsname(fd_master);
    > fd_slave = open(cb_slave,O_RDWR);
    >
    > count = write(fd_master, "gnuplot -persist\n", 128);
    > count = read(fd_master,buffer,sizeof(buffer));
    > count = write(fd_master, "p sin(x)\n",128);
    >
    > close(fd_slave);
    > close(fd_master);
    >
    > return EXIT_SUCCESS;
    > }
    >
    > I can't see any plots around with this code


    Ehh ... you still need to start the process and redirect its
    descriptors the same way you did in the other program, just using the
    pty slave descriptor (which should only be open in the child process
    to ensure proper eof handling) for its stdin/ out/ err instead of the
    two pipe descriptors and using the master pty descriptor for reading
    from and writing to the child process.

  19. Re: Fork Exec Pipe: HOW???

    On 28 Nov, 12:29, Rainer Weikusat wrote:
    > Phoenix87 writes:
    > >> Try a pseudo-terminal instead of two pipes (=> pty(4) for Linux).

    >
    > > Now I'm trying with pseudo-terminal, but I think i don't know how
    > > to use it:

    >
    > > #define _XOPEN_SOURCE

    >
    > > #include
    > > #include
    > > #include
    > > #include
    > > #include

    >
    > > int main(void)
    > > {
    > > int fd_master, fd_slave;
    > > char *cb_slave;
    > > char buffer[128];
    > > int count;

    >
    > > fd_master = getpt();
    > > grantpt(fd_master);
    > > unlockpt(fd_master);
    > > cb_slave = ptsname(fd_master);
    > > fd_slave = open(cb_slave,O_RDWR);

    >
    > > count = write(fd_master, "gnuplot -persist\n", 128);
    > > count = read(fd_master,buffer,sizeof(buffer));
    > > count = write(fd_master, "p sin(x)\n",128);

    >
    > > close(fd_slave);
    > > close(fd_master);

    >
    > > return EXIT_SUCCESS;
    > > }

    >
    > > I can't see any plots around with this code

    >
    > Ehh ... you still need to start the process and redirect its
    > descriptors the same way you did in the other program, just using the
    > pty slave descriptor (which should only be open in the child process
    > to ensure proper eof handling) for its stdin/ out/ err instead of the
    > two pipe descriptors and using the master pty descriptor for reading
    > from and writing to the child process.


    Ok! Following your unvaluable hints I produced this code that
    partly works

    #define _XOPEN_SOURCE

    #include
    #include
    #include
    #include
    #include
    #include

    enum {M,S,N};
    enum {STDIN,STDOUT,STDERR};

    int main(void)
    {
    int pt_fd[N];
    char *cb_slave;
    pid_t pid;
    char c;

    if ((pt_fd[M] = getpt()) == -1) {
    perror("getpt(3)");
    exit(EXIT_FAILURE);
    }

    pid = fork();

    switch (pid) {
    case -1: /* Fork failed */
    perror("fork(2)");
    exit(EXIT_FAILURE);

    case 0: /* Child Process */
    grantpt(pt_fd[M]);
    unlockpt(pt_fd[M]);
    cb_slave = ptsname(pt_fd[M]);
    pt_fd[S] = open(cb_slave, O_RDWR);
    close(pt_fd[M]);
    dup2(pt_fd[S], STDIN);
    dup2(pt_fd[S], STDERR);

    execlp("gnuplot","gnuplot","-persist",NULL);
    perror("execlp(3)");
    exit(EXIT_FAILURE);

    default: /* Parent process */
    write(pt_fd[M],"plost sin(x)\n",13);

    while (read(pt_fd[M],&c,1) > 0)
    fputc(c,stdout);

    write(pt_fd[M],"plot sin(x)\n",12);

    while (read(pt_fd[M],&c,1) > 0)
    fputc(c,stdout);

    wait(NULL);

    exit(EXIT_SUCCESS);
    }

    close(pt_fd[S]);
    close(pt_fd[M]);

    return EXIT_SUCCESS;
    }

    When I execute the program, in the terminal I get:



    plost sin(x)
    gnuplot> plost sin(x)
    ^
    invalid command

    gnuplot>

    and it freezes here, without executing the second write.
    But if I remove the first while loop, which prints all gnuplot
    program presentation and the other lines, gnuplot receives
    my second write call and he shows the plot.
    Trying debugging with gdb it seemed that the program
    entered an indefinite loop on the first while.
    What's the problem now?
    Thank you for your precious help!!!

  20. Re: Fork Exec Pipe: HOW???

    I have tried with this code to send commands
    and read responses, but i have some problem
    with this.

    default: /* Parent process */
    sleep(1);
    cb_slave = malloc(1024);
    memset(cb_slave,0,1024);

    read(pt_fd[M],cb_slave,1024);
    printf(cb_slave);
    memset(cb_slave,0,1024);

    write(pt_fd[M],"plost sin(x)\n",14);

    sleep(1);
    read(pt_fd[M],cb_slave,1024);
    printf(cb_slave);
    /* while (read(pt_fd[M],&c,1) > 0)
    fputc(c,stdout);*/

    sleep(1);
    write(pt_fd[M],"plot sin(x)\n",13);

    sleep(1);
    read(pt_fd[M],cb_slave,1024);
    printf(cb_slave);
    /*while (read(pt_fd[M],&c,1) > 0)
    fputc(c,stdout);*/

    free(cb_slave);

    sleep(3);
    write(pt_fd[M],"plot cos(x)\n",13);
    sleep(1);
    read(pt_fd[M],cb_slave,1024);
    printf(cb_slave);


    It seems to me that this isn't the best way to
    read frome and write to the pseudo-terminal.
    How can I improve this??

+ Reply to Thread