/***************************************************************************
         dcsigterm.cpp  -  Turn SIGTERM into a QCloseEvent properly
                             -------------------
    begin                : Mon Sep 08 2008
    copyright            : (C) 2008 by Edward Sheldrake
    email                : ejs1920@yahoo.co.uk
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include "dcsigterm.h"

#include <QSocketNotifier>
#include <QCloseEvent>
#include <QApplication>

#ifndef WIN32
#include <sys/types.h>
#include <sys/socket.h>
#endif
#include <unistd.h>
#include <stdio.h>

int DCSigTerm::sigtermsfd[2] = { -1, -1 };

/** */
DCSigTerm::DCSigTerm( QObject * parent ) : QObject( parent )
{
#ifndef WIN32
	if ( socketpair( AF_UNIX, SOCK_STREAM, 0, sigtermsfd ) == 0 )
	{
		notifier = new QSocketNotifier( sigtermsfd[1], QSocketNotifier::Read, this );
		connect( notifier, SIGNAL(activated(int)), this, SLOT(slotSocketReadyRead(int)) );
	}
	else
	{
		perror("DCSigTerm: socketpair");
		sigtermsfd[0] = -1;
		sigtermsfd[1] = -1;
		notifier = 0;
	}
#else
	sigtermsfd[0] = -1;
	sigtermsfd[1] = -1;
	notifier = 0;
#endif	
}

/** */
DCSigTerm::~DCSigTerm()
{
#ifndef WIN32
	if ( notifier )
	{
		delete notifier;
	}
	
	if ( sigtermsfd[0] != -1 )
	{
		if ( close( sigtermsfd[0] ) == -1 )
		{
			perror("~DCSigTerm: close sigtermsfd[0]");
		}
	}
	
	if ( sigtermsfd[1] != -1 )
	{
		if ( close( sigtermsfd[1] ) == -1 )
		{
			perror("~DCSigTerm: close sigtermsfd[1]");
		}
	}
#endif
}

/** */
void DCSigTerm::signal_handler( int /* signum */ )
{
	char q = 'q';
	if ( write( sigtermsfd[0], &q, sizeof(q) ) != 1 )
	{
		/* ignored */
	}
}

/** */
void DCSigTerm::slotSocketReadyRead( int /* unused */ )
{
	char q = 'p';
	if ( read( sigtermsfd[1], &q, sizeof(q) ) == 1 )
	{
		if ( q == 'q' )
		{
			QApplication::postEvent( parent(), new QCloseEvent() );
		}
	}
}
