#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <unistd.h>
#include <zmq.h>
#include <errno.h>

int main (int argc, char *argv[]) {
    if (argc != 3) {
        printf("%s [pubsub]\n\nEx.\n%s tcp://127.0.0.1:7817 /path/to/storage\n", argv[0], argv[0]);
        exit(-1);
    }

    /* Security is important, first we move to our target directory */
    chdir(argv[2]);
    
    /* Now we chroot to this directory, preventing any write access outside it */
    chroot(argv[2]);

    /* Setup the connection to the PubSub and subscribe to the envelopes */
	void *context  = zmq_init (1);
	void *subscriber = zmq_socket (context, ZMQ_SUB);

	zmq_connect (subscriber, argv[1]);
    zmq_setsockopt (subscriber, ZMQ_SUBSCRIBE, "/GOVI/KV7kalender", 17);
    zmq_setsockopt (subscriber, ZMQ_SUBSCRIBE, "/GOVI/KV7planning", 17);

	/* After we bind to the socket, we drop priviledges to nobody */
	setuid(65534);

	while (1) {
        #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3,0,0)
        int more;
        #else
		int64_t more;
        #endif
		size_t more_size = sizeof(more);
		FILE *fd = NULL;
		do {
            /* Create an empty 0MQ message to hold the message part */
			zmq_msg_t part;
			int rc = zmq_msg_init (&part);
			assert (rc == 0);
			/* Block until a message is available to be received from socket */
			#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3,0,0)
			rc = zmq_msg_recv (&part, subscriber, 0);
			#else
			rc = zmq_recv (subscriber, &part, 0);
			#endif
			assert (rc != -1);

			if (fd == NULL) {
	       		struct timeval tv;
				char path[222];
				assert (zmq_msg_size(&part) < 200);
			    gettimeofday(&tv,NULL);
                memcpy(path, zmq_msg_data(&part),  zmq_msg_size(&part));
			    snprintf(path + zmq_msg_size(&part), 22, "/%u.%06u.gz", (unsigned int) tv.tv_sec, (unsigned int) tv.tv_usec);
				fd = fopen(path + 1, "w");
			    assert (fd != NULL);
            } else {
				fwrite(zmq_msg_data(&part), zmq_msg_size(&part), 1, fd);
			}			
            /* Determine if more message parts are to follow */
			rc = zmq_getsockopt (subscriber, ZMQ_RCVMORE, &more, &more_size);
			assert (rc == 0);
			zmq_msg_close (&part);
		} while (more);
		
        if (fd) {
			fclose(fd);
        }
	}
}
