[pipe] Ping pong

Gli eseguibili (Linux 32/64 bit e OS X) sono disponibili al seguente link. Le istruzioni vengono mostrate quando eseguite il programma.

Una possibile soluzione (commentata) della verifica è la seguente:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

#define PIPEIN "pipePongIn"
#define PIPEOUT "pipePongOut"
#define BUFSIZE 10
#define LEFT "l"
#define RIGHT "r"

int main() {
    int i, fd_in, fd_out, ballx, position, num_moves;
    char stop, buffer[BUFSIZE], *direction;

    /* Crea le due pipe (se già non esistono) ed apri:
     * - pipePongIn in scrittura, per inviare le mosse all'altro programma;
     * - pipePongOut in lettura, per leggere la posizione corrente della pallina. */
    mkfifo(PIPEOUT, 0666);
    mkfifo(PIPEIN, 0666);
    fd_in = open(PIPEOUT, O_RDONLY);
    fd_out = open(PIPEIN, O_WRONLY);
    if (fd_in < 0 || fd_out < 0) {
        perror("Errore nell'apertura delle pipe");
        exit(EXIT_FAILURE);
    }

    /* Flag usata per la terminazione della partita. */
    stop = 0;
    /* La posizione iniziale della racchetta è 10, al centro del campo. */
    position = 10;

    /* Inizia la partita! */
    write(fd_out, "g", 1);
    while(!stop) {
        /* Leggi la posizione della pallina. */
        i = 0;
        while(i < BUFSIZE-1 && read(fd_in, &buffer[i], 1) && buffer[i] != ',') {
            i++;
        }

        if (i == 0) {
            /* In questo caso la partita è finita (l'altro programma ha chiuso la pipe e read
             * ha restituito zero). */
            stop = 1;
        } else if (i == BUFSIZE-1) {
            /* Qui non ci dovremmo mai arrivare, ma è sempre bene gestire eventuali overflow. */
            fprintf(stderr, "Non dovrei essere qui. BOOM!\n");
            exit(EXIT_FAILURE);
        } else {
            /* Estrai la posizione dalla stringa letta dal buffer. */
            buffer[i+1] = '\0';
            sscanf(buffer, "%d,", &ballx);

            /* Vai a sinistra o a destra del numero di mosse necessarie per muovere la
             * racchetta nella stessa posizione della pallina. */
            direction = ballx < position ? LEFT : RIGHT;
            num_moves = abs(ballx - position);
            while (num_moves > 0) {
                write(fd_out, direction, 1);
                num_moves--;
            }
            position = ballx;   
        }
    }

    /* Chiudi entrambe le pipe (la rimozione dal filesystem con 'unlink' viene già
     * fatta dall'altro programma). */
    close(fd_in);
    close(fd_out);

    return EXIT_SUCCESS;
}