/***************************************************************************
         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());
        }
    }
}
