EOF on the pipe prints trash

Edit: So, with some additional debugging, EOF successfully writes to the pipe (I know this because I tested the function to write()return 0 on produceStdin. HOWEVER , when reading from the same channel, it says that I encountered EOF ( good), but the value of the EOF element is 255 (usually -1 instead of -1) Does anyone know why this is so?

I am trying to write this program, but when I come across EOF from stdin, I am not writing -1 to the channel. For some reason, when trying to go through the EOF through the pipes, garbage is recorded, and therefore all subsequent processes are captured in an endless loop.

All of these print instructions, other than the one that prints the array in the function printOut(), I am trying to debug (cannot use the debugger due to forks)

Also: some of these comments are reworked, so if you see a mention of the “buffer”, this is because it was preprogrammed using buffers instead of pipes.

Here is the code:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#define MAX_CHARS 81 //80 chars + null-terminator
#define NUM_CHILDREN 3

void produceStdin(int writePipe);
void child1(int readPipe, int writePipe);
void child2(int readPipe, int writePipe);
void printOut(int readPipe);

int main(int argc, char const *argv[])
{
    int i,pipe1[2],pipe2[2],pipe3[2];
    pid_t childPid;

    if(pipe(pipe1)==-1||pipe(pipe2)==-1||pipe(pipe3)==-1)
    {
        fprintf(stderr, "Error in creating pipe");
    }
    //despite what it looks like only four children are being forked,
    // all to the same parent. The children get called to their respective 
    //functions where they get terminated before getting to fork themselves.
    for(i=0;i<NUM_CHILDREN;i++)
    {
        childPid=fork();
        switch (childPid) {
            case -1:
                perror("fork() failed. Aborting.");
                exit(EXIT_FAILURE);

            case 0:
                switch (i) {
                    case 0:
                        close(pipe1[0]); //close pipe1 read (since we're reading from stdin)

                        close(pipe2[0]); //close pipe2
                        close(pipe2[1]);

                        printf("right before calling stdin i=%d\n",i);
                        produceStdin(pipe1[1]); //write to pipe1
                        break;

                    case 1:
                        close(pipe1[1]); //close pipe1 write

                        close(pipe2[0]); //close pipe2 read

                        close(pipe3[0]); //close pipe3
                        close(pipe3[1]);
                        printf("right before calling child1 i=%d\n",i);
                        child1(pipe1[0], pipe2[1]); //read from pipe1, write to pipe2
                        break;

                    case 2:
                        close(pipe1[0]); //close pipe1
                        close(pipe1[1]);

                        close(pipe2[1]); //close pipe2 write

                        close(pipe3[0]); //close pipe3 read
                        printf("right before calling child2 i=%d\n",i);
                        child2(pipe2[0], pipe3[1]); //read from pipe2, write to pipe3
                        break;

                    default:
                        break;
                }

            default:
                if(i==2)
                {
                    close(pipe1[1]); //close pipe1
                    close(pipe1[0]);

                    close(pipe2[1]); //close pipe2
                    close(pipe2[0]);

                    close(pipe3[1]); //close pipe3 write

                    printOut(pipe3[0]); //read from pipe3 read
                }
                break;
        }
    }
    return 0;
}
void produceStdin(int writePipe)
{
    int c=0;
    while(c!=EOF)
    {
        c=fgetc(stdin);
        write(writePipe, &c, sizeof(char)); //writing EOF here is where the problem starts I believe
    }
    printf("Got EOF in ProdStdin\n");
    printf("EOF has a value of: %d",c);
    exit(0);
}
void child1(int readPipe, int writePipe)
{
    int c=0;
    while(c!=EOF)
    {
        read(readPipe,&c,sizeof(char));
//        printf("Child1 got a char from pipe1: %c\n",c);
        if(c=='\n')
        {
            c=' '; //test for newline
        }
        write(writePipe, &c, sizeof(char));
    }
    exit(0);
}
void child2(int readPipe, int writePipe)
{
    int c=0;
    int c2=0;
    while(c!=EOF && c2!=EOF)
    {
        read(readPipe, &c, sizeof(char));
//        printf("Child2 got a char from pipe2: %c\n",c);
        if(c=='*')
        {
            read(readPipe, &c2, sizeof(char)); //if c is a * remove another char
            if(c2=='*')
            {
                c='^'; //if c2 is a * then put a ^ on buffer3
                write(writePipe,&c,sizeof(char));
            }
            else
            {
                write(writePipe,&c,sizeof(char));
                write(writePipe,&c2,sizeof(char));
            }
        }
        else
        {
            write(writePipe,&c,sizeof(char));
        }
    }
    exit(0);
}
void printOut(int readPipe)
{
    int c=0,numChars=0;
    char output[MAX_CHARS];
    while (c!=EOF)
    {
        read(readPipe, &c, sizeof(char));
//        printf("PrintOut got a char from pipe3: %c\nnumChars= %d\n",c,numChars);
        if (numChars==MAX_CHARS-2)
        {
            printf("%s\n",output);
            memset(output, '\0', sizeof(char)*MAX_CHARS);
            numChars=0;
        }

        output[numChars]=c;
        numChars++;
    }
    printf("ABOUT TO EXIT PRINTOUT()\n");
    exit(0);
}
+4
source share
2 answers

Alternative Transmit a 2-byte version of what was read through the pipe, so the receiving side can distinguish between char and EOF.

int c = 0;
while(c!=EOF) {
  c = fgetc(stdin);
  short sc = (short) c;
  // `sc` will _typically_ have the values -1 (EOF) and 0,1,2,... 255.
  write(writePipe, &sc, sizeof(sc));
}

int c=0;
int c2=0;
while(c != EOF && c2 != EOF) {
  short sc;          
  if (sizeof(sc) != read(readPipe, &sc, sizeof(sc))) handle_error();
  // `sc` will _typically_ have the values -1 (EOF) and 0,1,2,... 255.
  c = sc;
  ...

Original suggested answer.

c EOF , .
:

// while(c!=EOF) {
//   c=fgetc(stdin);
//   write(writePipe, &c, sizeof(char));
// }
while((c = fgetc(stdin)) != EOF) {
  write(writePipe, &c, sizeof(char));
}

read(readPipe, &c, sizeof(char)); , c, EOF. EOF char.

// int c=0;
// int c2=0;
// while(c!=EOF && c2!=EOF) {
//    read(readPipe, &c, sizeof(char));

char c=0;
char c2=0;
while(1 == read(readPipe, &c, sizeof(char))) {

+3

:

int c = 0;

while(c!=EOF)
{
    c=fgetc(stdin);
    write(writePipe, &c, sizeof(char));
}

:

int c;

while ((c = fgetc(stdin)) != EOF)
{
    char c1 = c;
    write(writePipe, &c1, sizeof(char));
}

fgetc() , int, EOF. , EOF, , . c1; , , , , . , , .

. :

int c=0;
while(c!=EOF)
{
    read(readPipe,&c,sizeof(char));
    if(c=='\n')
    {
        c=' '; //test for newline
    }
    write(writePipe, &c, sizeof(char));
}

:

char c;
while (read(readPipe, &c, sizeof(char)) == sizeof(char))
{
    if (c == '\n')
        c = ' ';
    write(writePipe, &c, sizeof(char));
}

, , (, , , , ).

, - read() write() . / - , . .

, chux , .

+1

All Articles