/* aritmetika_named.c
 *
 * Operacijski sustavi -- vjezba 4, zadatak 4c
 *
 * Rijesio:
 * Filip Niksic (fniksic@gmail.com)
 * 2008-06-10
 **/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <wait.h>
#include <limits.h>
#include <sys/stat.h>
#include <fcntl.h>

/* Ocekujem neprazan string na ulazu u kojem ima
 * mjesta za dodavanje jos jednog znaka
 **/
void addNewline(char *line) {
    size_t length = strlen(line);
    if (line[length - 1] != '\n') {
        line[length] = '\n';
        line[length + 1] = '\0';
    }
}

void clearNewline(char *line) {
    size_t length = strlen(line);
    if (line[length - 1] == '\n')
        line[length - 1] = '\0';
}

int main(int argc, char *argv[]) {
    FILE *in;
    int pipeToBc, pipeFromBc;
    char line[LINE_MAX]; // linija koju citam iz datoteke
    char response[LINE_MAX]; // odgovor od bc-a
    char result[LINE_MAX]; // korisnikovo rjesenje
    ssize_t bytes_read;
    //size_t total;

    if (argc < 2) {
        printf("%s <datoteka>\n", argv[0]);
        return EXIT_FAILURE;
    }

    if ((in = fopen(argv[1], "r")) == NULL) {
        printf("Greska pri otvaranju datoteke %s\n", argv[1]);
        return EXIT_FAILURE;
    }

    unlink("./pipeToBc");
    if (mkfifo("./pipeToBc", S_IRUSR | S_IWUSR) == -1) {
        printf("Greska pri kreiranju imenovanog cjevovoda pipeToBc.\n");
        return EXIT_FAILURE;
    }
    unlink("./pipeFromBc");
    if (mkfifo("./pipeFromBc", S_IRUSR | S_IWUSR) == -1) {
        printf("Greska pri kreiranju imenovanog cjevovoda pipeFromBc.\n");
        return EXIT_FAILURE;
    }
    
    /* Forkam se na dva dijela */
    switch (fork()) {
    case -1: // error
        printf("Greska pri forkanju.\n");
        return EXIT_FAILURE;

    case 0: // dijete
        fclose(in);
        if ((pipeFromBc = open("./pipeFromBc", O_WRONLY)) == -1) {
            printf("Greska pri otvaranju pipeFromBc!\n");
            return EXIT_FAILURE;
        }
        if ((pipeToBc = open("./pipeToBc", O_RDONLY)) == -1) {
            printf("Greska pri otvaranju pipeToBc!\n");
            return EXIT_FAILURE;
        }
        /* Preusmjeravam pipeToBc na stdin */
        close(0);
        dup(pipeToBc);
        close(pipeToBc);
        /* Preusmjeravam pipeFromBc na stdout i stderr */
        close(1);
        dup(pipeFromBc);
        close(2);
        dup(pipeFromBc);
        close(pipeFromBc);
        /* Pokrecem bc s argumentom -q */
        execlp("bc", "bc", "-q", (char *)0);
        /* Ako smo jos ovdje, execlp nije uspio */
        printf("Greska pri pokretanju bc!\n");
        return EXIT_FAILURE;

    default: // roditelj
        if ((pipeFromBc = open("./pipeFromBc", O_RDONLY)) == -1) {
            printf("Greska pri otvaranju pipeFromBc!\n");
            return EXIT_FAILURE;
        }
        if ((pipeToBc = open("./pipeToBc", O_WRONLY)) == -1) {
            printf("Greska pri otvaranju pipeToBc!\n");
            return EXIT_FAILURE;
        }

        while (fgets(line, LINE_MAX, in) != NULL) {
            /* Prvo saljem liniju bc-u */
            addNewline(line); // za slucaj da linija ne zavrsava s \n
            write(pipeToBc, line, strlen(line));
            sleep(1);
#ifndef NDEBUG
            printf("[DEBUG] Poslao: %s\n", line);
#endif
/*
            total = 0;
            do {
                bytes_read = read(pipeFromBc[0], response + total, LINE_MAX - total);
                total += bytes_read;
            } while (response[total - 1] != '\n');
            response[total] = '\0';
*/
            bytes_read = read(pipeFromBc, response, LINE_MAX);
            response[bytes_read] = '\0';
#ifndef NDEBUG
            printf("[DEBUG] Primio: %s\n", response);
#endif
            clearNewline(line);
            if (!isdigit(response[0]))
                printf("NEISPRAVAN IZRAZ: %s\n", line);
            else {
                clearNewline(response);
                printf("%s = ", line);
                scanf("%s", result);
                if (strcmp(result, response) == 0)
                    printf("ISPRAVNO\n");
                else
                    printf("NEISPRAVNO, tocan odgovor je %s\n", response);
            }
        }

        /* Izlazim iz bc-a i cekam da zavrsi */
        write(pipeToBc, "quit\n", 5);
        wait(NULL);
        
        /* Brisem cjevovode */
        unlink("./pipeFromBc");
        unlink("./pipeToBc");
    }

    return EXIT_SUCCESS;
}

