mkfifo make 2 processes talk to each other

1.2k views Asked by At

I am trying to write 2 programs that will talk to each other using fifo pipe. I used the example here (section 5.2), but I changed the mknod there to mkfifo and tried to change gets to fgets. This is the code (of one program which writes into the fifo):

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h> /*mkfifo, open */
#include <sys/wait.h>
#include <sys/stat.h> /* mkfifo, open */
#include <fcntl.h> /*open */

#define FIFO_PATH "/home/hana/Desktop"
#define BUFFER_SIZE 300



int main()
{
    char buffer[BUFFER_SIZE];
    int fd;
    int wStatus;
    
    mkfifo(FIFO_PATH, 666);
    printf("waiting for readers\n");
    fd = open(FIFO_PATH, O_RDWR);
    
    while (fgets(buffer, BUFFER_SIZE, fd), !feof(stdin)) 
    {
        if ((wStatus = write(fd, buffer, strlen(buffer))) == -1)
            perror("write");
        else
            printf("speak: wrote %d bytes\n", wStatus);
    }
    
    return 0;
}

I get a compilation error: passing argument 3 of fgets makes pointer from integer. So fgets is expecting FILE* and not file descriptor. What should I do? change something so that fgets works? use another function?

I am compiling with gcc (ansi, pedantic).

Thanks

2

There are 2 answers

0
Sergio On BEST ANSWER

mkfifo() just creates special node in filesystem. And you are free to open it in any way. Actually there are two alternatives - POSIX "non-buffered" I/O: open()/write()/read() or standard buffered I/O: fopen()/fread()/fwrite(). First family operates on file descriptors while second one uses so called file streams: FILE. You can not mix these APIs freely. Just choose one and stick to it. Standard I/O library offers some useful extra capabilities comparing to low-level non-buffered I/O. Like fgets() that you're trying to use. In this situation would be reasonable to use standard streams and replace open() with:

FILE* stream = fopen(FIFO_PATH, "r+");

Thus program will use FILE* instead of plain file descriptors. Also write() need to be changed to fwrite() immediately followed by fflush() to guarantee that written data are passed to FIFO.

P.S. In case of necessity it is possible to "wrap" low-level descriptors returned by open()(or something other) with standard FILE*. See fdopen(). But it is much like a workaround to use standard I/O API with special file objects that can not be opened with fopen().

3
JeremyP On

The answer from whjm is the cause of your error diagnostic, but I think you probably meant

fgets(buffer, BUFFER_SIZE, stdin)
//                         ^^^^^ 

It doesn't make sense that you would read from a pipe and then immediately write the same thing back to the pipe. Also, if you never read from stdin, feof(stdin) will never be true.

Also, with fgets just check for a null result and then outside the loop, do the check for eof:

while (fgets(...) != NULL)
{
    ...
}
if (!feof(stdin))
{
    // error handling
}