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

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <signal.h>
#include <unistd.h>

#define MY_MSG_TYPE 1
#define BUFFER_SIZE 1024u

struct message {
    long type;
    char data[1];
};

int msgId;

void sigInt_handler(int sig) {
    if (msgctl(msgId, IPC_RMID, NULL) == -1)
	exit(EXIT_FAILURE);
    else
	exit(EXIT_SUCCESS);
}

int main(void) {
    struct sigaction sigInt;
    key_t kljuc;
    char *envKljuc;
    struct message myMsg;
    char buffer[BUFFER_SIZE];
    size_t bufSize = 0;
    int counter = 0;

    /* Dobavljanje kljuca za red poruka iz okoline */
    if ((envKljuc = getenv("MSG_KEY")) != NULL) {
	kljuc = atoi(envKljuc);
	printf("[R] Nadjena varijabla okoline %s\n", envKljuc);
    }
    else {
	printf("MSG_KEY varijabla okoline nije postavljena!\n");
	return EXIT_FAILURE;
    }

    /* Dobavljanje reda poruka */
    if ((msgId = msgget(kljuc, 0600 | IPC_CREAT)) == -1) {
	printf("Greska pri dobavljanju reda poruka!\n");
	return EXIT_FAILURE;
    }

    /* Postavljanje handlera za SIGINT */
    sigInt.sa_handler = sigInt_handler;
    sigemptyset(&sigInt.sa_mask);
    sigInt.sa_flags = 0;

    if (sigaction(SIGINT, &sigInt, NULL) == -1) {
	printf("Greska prilikom inicijalizacije SIGINT!\n");
	return EXIT_FAILURE;
    }

    /* Dobavljanje poruka iz reda. Ako tokom 10 sekundi nista ne dodje u
     * red, izlazimo. */
    while (counter < 10) {
	sleep(1);
	if (msgrcv(msgId, &myMsg, 1, MY_MSG_TYPE, IPC_NOWAIT) == (ssize_t)-1) {
	    printf("[R] receiver idle (%d)\n", counter);
	    ++counter;
	}
	else {
	    counter = 0;
	    printf("[R] received: %c\n", myMsg.data[0]);
	    buffer[bufSize++] = myMsg.data[0];
	    if (myMsg.data[0] == '\0') {
		printf("[RECEIVED] %s\n", buffer);
		bufSize = 0;
	    }
	}
    }

    printf("[R] receiver exiting\n");

    if (msgctl(msgId, IPC_RMID, NULL) == -1)
	return EXIT_FAILURE;
    else
	return EXIT_SUCCESS;
}

