/***************************************************/
/* program2.c                                      */
/* Justin Hartman                                  */
/* EECS 338 - Spring 2003                          */
/* Assignment 2                                    */
/***************************************************/

/***************************************************/
/* Written in Microsoft Visual C++ 6.0             */
/* Compiled and executed on CWRU's EECS department */
/* lab's (Olin 404.5) SUN boxes using SSH and      */
/* secure FTP                                      */
/***************************************************/

#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>

int file_des;
char *filename;

int main(int argc, char* argv[]) {
	void signal_catcher(int);

	/* Check arg usage */
	if (argc != 2) {
		printf("Usage: %s filename\n", argv[0]);
		exit(1);
	}

	/* Set the global pointer for the output filename */
	filename = argv[1];

	/* Set up the signal handler */
	if (signal(SIGUSR2, signal_catcher) == SIG_ERR) {
		perror("Error setting signal handler for SIGUSR2");
		exit(3);
	}

	/* Sleep one second */
	sleep(1);

	/* Send SIGUSR1 to the parent process */
	kill(getppid(), SIGUSR1);

	/* Wait for SIGUSR2, which will be handled, then exit */
	sigpause(SIGUSR2);

	exit(0);
}

void signal_catcher(int the_sig) {
	struct flock lock;
	
	/* Reset the signal (it's really unimportant, since we'll only get one) */
	signal(the_sig, signal_catcher);

	if (the_sig == SIGUSR2) {
		/* Set up a write lock */
		lock.l_type = F_WRLCK;
		lock.l_whence = 0;
		lock.l_start = 0L;
		lock.l_len = 0L;

		/* Open a file handle for the output file */
		if ((file_des = open(filename, O_RDONLY)) < 0) {
			perror("Error opening output file");
			exit(4);
		}

		/* try to set the write lock */
		while (fcntl(file_des, F_SETLK, &lock) < 0) {
			/* While it doesn't work, report on who owns it, then wait one second */
			fcntl(file_des, F_GETLK, &lock);
			printf("\nProcess %d cannot lock '%s' for writing: in use by process %d\n", (int)getpid(), filename, (int)lock.l_pid);
			sleep(1);
		}

		/* unlock the write lock */
		lock.l_type = F_UNLCK;
		lock.l_whence = 0;
		lock.l_start = 0L;
		lock.l_len = 0L;

		if (fcntl(file_des, F_SETLK, &lock) < 0) {
			perror("Error removing lock on output file");
			exit(1);
		}

		/* close the file handle */
		close(file_des);

		/* cat the output file */
		execlp("cat", "cat", filename, (char *)NULL);
	}
}