/*
Ниже небольшая тестовая программа на СИ. Она в принципе работает.
И заглушка утилиты.
Замечу следующее.
Запись в pipe делается, если там есть свободное место, если не ошибаюсь 512 байт.
Если в утилите построчная буферизация, то скорее всего и будете получать построчно.
Если там другая буферизация или строки длиннее 512, то будете получать разными
кусками. Тогда к этому нужно быть готовым.
*/   // ТЕСТОВАЯ ПРОГРАММА
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>
//   c:\СИ\all_funk\forum.c
//   cd /usr/home/test3test/all_funk/tar/
//   gcc forum.c -o forum.cgi
//   ./forum.cgi
//------------------------------ call_util --------------------------------
int call_util()
{
    int k, n;
    int pipesin[2], pipesout[2];
    pid_t  pid, status=0;
    char buf[100];
    pipesin[0] = -1;
    pipesin[1] = -1;
    pipesout[0] = -1;
    pipesout[1] = -1;
    k=pipe(pipesin);
    if(k<0){ printf("k=pipe(pipesin)=%d\n", k); goto ERR;}
    k=pipe(pipesout);
    if(k<0){ printf("k=pipe(pipesout)=%d\n", k); goto ERR;}
    pid=fork();
    if(pid<0){ printf("pid=fork()=%d\n", (int)pid); goto ERR;}
    if(pid==0){
        //this is child process
        char *args[] = {"forum_util.cgi", "-c" ,NULL};
        int in, out;
        close(pipesin[1]);
        close(pipesout[0]);
        close(1);//close stdout
        k=dup(pipesout[1]);
        if(k!=1) exit(1);
        close(pipesout[1]);     // это все так делают
        close(0); //close stdin
        k=dup(pipesin[0]);
        if(k!=0) exit(1);
        close(pipesin[0]);     // это все так делают
        k=execvp("./forum_util.cgi", args);
        printf("k=execvp()=%d: %s\n", k, strerror(errno));
        exit(2);
    }
    //this is parent process
    signal(SIGPIPE, SIG_IGN); // это чтоб не завалить главный процесс
    close(pipesin[0]);
    pipesin[0]=-1;
    close(pipesout[1]);
    pipesout[1]=-1;
    n=0;
    while(n<4){
        snprintf(buf, sizeof(buf), "n=%d\n", n);
        k=write(pipesin[1], buf, strlen(buf));
        fflush(stdout);
        if(k<0){ printf("k=write(pipesin[1])=%d\n", k); goto ERR;}
        printf(">>> %s\n", buf);
        k=read(pipesout[0], buf, sizeof(buf)-1);
        if(k<=0){ printf("k=read(pipesout[0])=%d\n", k); goto ERR;}
        buf[k]=0;
        printf("<<< %s\n", buf);
        n++;
    }
    if(pipesin[0] >= 0) close(pipesin[0]);
    if(pipesin[1] >= 0) close(pipesin[1]);
    if(pipesout[0] >= 0) close(pipesout[0]);
    if(pipesout[1] >= 0) close(pipesout[1]);
    wait(&status);  // борьба с зомби
    printf("status=0xX\n", status);
    return(0);
ERR:
    if(pipesin[0] >= 0) close(pipesin[0]);
    if(pipesin[1] >= 0) close(pipesin[1]);
    if(pipesout[0] >= 0) close(pipesout[0]);
    if(pipesout[1] >= 0) close(pipesout[1]);
    wait(&status);  // борьба с зомби
    printf("status=0xX\n", status);
    return(-1);
}
//-------------------------- main ---------------------------------
int main()
{
    int k;
    k=call_util();
    printf("k=call_util()=%d\n\n", k);
    exit(0);
}
//=====================================================================
  //  ЗАГЛУШКА УТИЛИТЫ
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//   c:\СИ\all_funk\forum_util.c
//   cd /usr/home/test3test/all_funk/tar/
//   gcc forum_util.c -o forum_util.cgi
//   ./forum_util.cgi
//----------------- main ------------------
int main(int argc, char *argv[])
{
    char *ptr, buf[100];
    alarm(10);
    while(1){
        ptr=fgets(buf, sizeof(buf), stdin);
        if(ptr==NULL) exit(9);
        printf("%s", buf);
        fflush(stdout);
    }
    exit(10);
}