Writing to pipe or pipes Writing to pipe or pipes unix unix

Writing to pipe or pipes


Suggestion #1: Use functions

Use functions, even for little jobs such as:

void create_fifo(const char *name){    /* Create the first named - pipe */    int ret_val = mkfifo(name, 0666);    if ((ret_val == -1) && (errno != EEXIST))    {        perror("Error creating the named pipe");        exit(1);    } }

Now you can simply write in your main program:

create_fifo(PIPE1);create_fifo(PIPE5);

This cuts down on the clutter in your main program. It also adheres to the Agile principle DRY - Don't Repeat Yourself.

Suggestion #2: Error check system calls.

You did that for creating the FIFOs, which is good. You don't for the open() calls, or the read() or write() calls. You probably should. I use a function similar to the following in my programs:

#include <stdarg.h>#include <string.h>#include <stdio.h>#include <errno.h>static const char *arg0 = "did not call err_setarg0(argv[0])";void err_setarg0(const char *argv0){    arg0 = argv0;}void err_exit(const char *fmt, ...){    int errnum = errno;   /* Capture errno before it is changed */    va_lists args;    fprintf(stderr, "%s: ", arg0);    va_start(args, fmt);    vfprintf(stderr, fmt, args);    va_end(args);    if (errnum != 0)        fprintf(stderr, "%d: %s\n", errnum, strerror(errnum));    exit(1);}

You can then use:

if ((rdfd1 = open(PIPE1, O_RDONLY)) < 0)    err_exit("Failed to open FIFO %s for reading: ", PIPE1);if ((wrfd1 = open(PIPE5, O_WRONLY)) < 0)    err_exit("Failed to open FIFO %s for writing: ", PIPE5);

Suggestion #3: Make an iterative server

Your server program currently opens the FIFOs once, then reads from one, write to the other, and terminates. You need a loop around some portion of this code, maybe two nested loops. You have to decide whether you need an inner loop to read until EOF. You also need to know how you will terminate the server.

Suggestion #4: Maybe the server needs pipe names as arguments

Your server currently works on fixed FIFO names. You probably need it to take input and output file names as command line arguments, so that when your client spawns multiple servers, each server can have its own set of FIFOs, rather than all processes sharing the same two FIFOs, which is going to lead to confusion and chaos.

Indeed, the need for generating names calls the whole design into question - are you sure using FIFOs is the best way to do this? It looks to me like a case where anonymous pipes would serve you better; you wouldn't have to invent names, and the server would simply read from its standard input and write the (modified?) data to its standard output, so you could even simply use cat or tr or sed or ... as your server.

Clearly, if you use pipes, you will need to do some careful plumbing, but you also need to do careful plumbing with the pairs of FIFOs per server.