C and Named Pipes | Self explanatory code…

… if you know the concept of Named Pipes in a UNIX system. I tried to write clean c-code by applying the principles of the almost new book Clean Code. Try if you can understand this program only by reading the function’s name. Comments were only made if I thought they were really necessary to understand the code. Give it a try by starting in the main method …

#include <string.h>
#include <errno.h>

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/stat.h>

#include "namedpipe.h"

#define REMOVE_FILE_SUCCESSFUL 0
#define FALSE 0
#define TRUE 1

const char *szCommandName = "<not yet set>";

volatile static FILE *pNamedPipe = (FILE *) 0;

/* Flag which indicates the pipes creation status. */
volatile static int bPipeCreated = FALSE;

void free_resources();

void print_error_message(const char *szMessage) {
    fprintf(stderr, "%s: %s\n", szMessage, strerror(errno));
    exit(EXIT_FAILURE);
}

void bailOut(const char *szMessage) {
    if (szMessage != (const char *) 0) {
        print_error_message(szMessage);
    }
    free_resources();
    exit(EXIT_FAILURE);
}

int named_pipe_already_open() {
    return pNamedPipe != (FILE *) 0;
}

void pipe_no_longer_open() {
    pNamedPipe = (FILE *) 0;
}

void close_pipe() {
    if (fclose((FILE *) pNamedPipe) == EOF) {
        pipe_no_longer_open();
        bailOut("Couldn’t close named pipe!");
    }
    pipe_no_longer_open();
}

int named_pipe_already_created() {
    return bPipeCreated;
}

void pipe_no_longer_present() {
    bPipeCreated = FALSE;
}

void remove_pipe() {
    if (remove(PIPE_PATH) != REMOVE_FILE_SUCCESSFUL) {
        pipe_no_longer_present();
        bailOut("Can’t remove named pipe!");
    }
    pipe_no_longer_open();
}

void check_if_named_pipe_already_open() {
    if (named_pipe_already_open()) {
        close_pipe();
    }
}

void check_if_named_pipe_already_created() {
    if (named_pipe_already_created()) {
        remove_pipe();
    }
}

void free_resources() {
    check_if_named_pipe_already_open();
    check_if_named_pipe_already_created();
}

void print_application_usage() {
    (void) fprintf(stderr, "USAGE: %s\n", szCommandName);
    bailOut((const char *) 0);
}

void save_the_applications_name(char *commandName) {
    szCommandName = commandName;
}

void check_arguments(int argumentCounter) {
    if (argumentCounter != 1) {
        print_application_usage();
    }
}

void signal_handler() {
    free_resources();
    exit(EXIT_SUCCESS);
}

void configure_signal_handling() {
    (void) signal(SIGINT, signal_handler);
    (void) signal(SIGTERM, signal_handler);
    (void) signal(SIGQUIT, signal_handler);
}

void create_named_pipe() {
    if (mkfifo(PIPE_PATH, PERMISSION_BITS) == -1) {
        bailOut("Couldn’t create the named pipe!");
    }
    bPipeCreated = TRUE;
}

void open_named_pipe() {
    /* fopen blocks until an other process opens the pipe with write access. It
     * is also called implicit synchronisation. */
    if ((pNamedPipe = fopen(PIPE_PATH, "r")) == (FILE *) 0) {
        bailOut("Couldn’t open named pipe!");
    }
}

void strip_new_line(pipedata_t szPipeName) {
    szPipeName[strlen(szPipeName) – 1] = “;
}

void print_file(pipedata_t szPipeName) {
    printf("Named Pipe: %s\n", szPipeName);
}

void read_from_pipe_until_EOF_or_error(pipedata_t szPipeName) {
    while (fgets(szPipeName, sizeof(szPipeName), (FILE *) pNamedPipe) != NULL) {
        strip_new_line(szPipeName);
        print_file(szPipeName);
    }
}

int main(int argc, char** argv) {

    pipedata_t szPipeName;

    save_the_applications_name(argv[0]);

    check_arguments(argc);

    configure_signal_handling();

    create_named_pipe();

    while (TRUE) {
        open_named_pipe();
        read_from_pipe_until_EOF_or_error(szPipeName);       
    }

    /* Still should be refactored. */
    if (ferror((FILE *) pNamedPipe) == TRUE) {
        bailOut("Can’t read from named pipe.");
    }

    close_pipe();
    return (EXIT_SUCCESS);
}

… and, what do you think. I really recommend the book Clean Code and The Productive Programmer

Technorati-Tags:

Über sageniuz

https://about.me/ClausPolanka
Dieser Beitrag wurde unter Programming veröffentlicht. Setze ein Lesezeichen auf den Permalink.

Schreibe einen Kommentar

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s