-1

I am writing C program which constantly generates two string values named stateName and timer (with the rate of five times per second). I need to concatenate and pass them to another process called ProcessNo3_TEST which is responsible for tokenizing and also displaying them.

The problem is I don't know how to pass them continuously via execl. I had a couple of attempts but none of them were successful. Here is my code which works fine for a single pair of values (e.g. UP2 and 98):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define READ 0
#define WRITE 1

int FIFO[2];
char fileDescriptor[10];

char* stringMaker( char *s1,char *s2 );

int main()
{
    char lengthInChar[15],msg[200];
    int msgLength,i;
    char *stateName, *timer;
    if (pipe(FIFO) == -1)
    {
        printf("cannot create pipe\n");
        exit(1);
    }
    sprintf(fileDescriptor, "%d", FIFO[READ]);

    stateName = "UP2";              // for instance
    timer = "98";                   // for instance

    msgLength = strlen(stateName) + strlen(timer) +3;
    strcpy(msg, stringMaker(stateName, timer) );
    write(FIFO[WRITE], msg, msgLength);

    switch (fork())
    {
    case 0:
        sprintf(lengthInChar, "%d", msgLength);
        execl("ProcessNo3_TEST", "ProcessNo3_TEST", lengthInChar, fileDescriptor, NULL);
        exit(1);
    case -1:
        perror("fork() failed-->");
        exit(2);
    default:
        break;
    }
    sleep(10);
    exit(0);
}

char* stringMaker( char *s1,char *s2 )
{
    char *s3;
    strcpy(s3,s1);
    strcat(s3,"-");
    strcat(s3,s2);
    strcat(s3,"-");
    strcat(s3,"\0");
    return s3;
}

Can anyone help on this please?

(I am running CygWin on Windows by the way)

----------UPDATE-------------

As advised in comments below, I found a good example of fdopen() which solved my problem. (Link)

Bababarghi
  • 571
  • 1
  • 4
  • 23

2 Answers2

0

Although one can arrange to pass one pipe end's file descriptor number (in string form) as a program argument, normally one would instead redirect the child process's standard streams to read from (in this case) or write to the pipe. This is usually achieved via dup2(), which you would apply in the child process, after forking but before execl().

Parent and child processes then communicate via the pipe. In this case, the parent writes to the writing end and the child reads from the reading end. Either or both can wrap their file descriptor in a stream by passing it to fdopen(). Then you can use stdio functions with it. Note, too, that after the fork, each process should close the FD for the pipe end it does not intend to use.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • Thanks for the thorough description John. Would I be considered as a pest if I ask for a sample code? – Bababarghi Oct 09 '15 at 17:51
  • @Bababarghi, only if you did not [do your own research](http://stackoverflow.com/search?q=pipe+exec) first. – John Bollinger Oct 09 '15 at 18:36
  • That's fair enough. So my question is what should I bother I using `dup2()`? The first line of your second paragraph is pretty much what I have currently got in my code mentioned above without `dup2()` i.e. parent writes to the writing end of the pipe and the child reads from the reading end of the pipe. Isn't it? – Bababarghi Oct 09 '15 at 22:21
  • @Bababarghi, as I wrote, you would use `dup2()` to *redirect [one of] the child process's standard streams* so that (in this case) you don't need to pass it a file descriptor number, and it can instead just read the wanted data from its standard input. That's especially convenient if you want the child process to be usable (or testable) as a standalone process, or if it already is such. That's pretty conventional, but not universal. You don't *need* to do it. – John Bollinger Oct 09 '15 at 23:22
  • Yeah. That's what I thought (I do not need it at this stage). My child process is not going to be a standalone application whatsoever and it only suppose to receive information from its parent. I am still confused on `streaming` part though. How can I send stream of data through `execl`? – Bababarghi Oct 09 '15 at 23:27
  • I am desperately stuck mate. Would you please show me a sample code? I really appreciate it. – Bababarghi Oct 11 '15 at 12:46
  • @Bababarghi, I gave you a search link from which you can draw multiple code samples. Most are not much different from what you already have. I think the problem must be that you don't know how to *recognize* the solution. You cannot pass a stream in the sense and form of a `FILE *` to a child process, period. You cannot *pass* a stream in the abstract sense, either, because a stream is an ongoing series of bytes, whereas any function call occurs at a fixed point in time. – John Bollinger Oct 11 '15 at 15:53
  • @Bababarghi, you you *can* do is allow the child process to inherit an open file descriptor from the parent (which happens automatically) that will serve as a communication endpoint from which it can receive the (abstract) stream of bytes, and around which, if you so desire, you create a `FILE *` stream by means of function `fdopen()`. – John Bollinger Oct 11 '15 at 15:55
  • Thanks John. Correct me if I am wrong. What you are saying is that I have to completely forget about using `execl` because that doesn't work in this scenario. Instead I need to replace `execl( "ProcessNo3_TEST" , "ProcessNo3_TEST", lengthInChar, fileDescriptor, NULL);` line in my code with something like: `FILE *to_child = fdopen(dup(FIFO[WRITE]), "w");`. Right? Next stage is, to go to `ProcessNo3_TEST.c` file and somehow try to get the handle of `to_child` and read from it. (I truly appreciate your time and effort answering my simplistic questions) – Bababarghi Oct 11 '15 at 23:24
  • I found a good example [here](http://www.gnu.org/software/libc/manual/html_node/Creating-a-Pipe.html) which solved my problem. Thank you John. – Bababarghi Oct 12 '15 at 12:47
0

If are set on using execl() (often people prefer not to, but sometimes it has it's benefits) than you should use named pipes instead of unanonymous. Anononymous pipe end is lost after execl(). But if you have a named pipe, you can pass it's name as an argument to the execl(), open it in child process and use there.

SergeyA
  • 61,605
  • 5
  • 78
  • 137
  • Thanks for the reply. Well I tried that approach but gcc linker couldn't find the reference to 'mkfifo' call. I couldn't resolve the issue in Dev-C++. Do you have any idea why it complains about using 'mkfifo'? – Bababarghi Oct 09 '15 at 17:48
  • most likely, cygwin does not provide an implementation of mkfifo. You will probably have to use native windows named pipes, which do exist :) – SergeyA Oct 09 '15 at 17:54
  • do you have any link for example code perhaps on similar application? – Bababarghi Oct 09 '15 at 23:57