File indexing completed on 2024-03-24 17:23:05

0001 /*
0002  * Copyright (C) 2010-2018 Daniel Nicoletti <dantti12@gmail.com>
0003  *           (C) 2011 Modestas Vainius <modax@debian.org>
0004  *           (C) 2018 Harald Sitter <sitter@kde.org>
0005  *
0006  * This library is free software; you can redistribute it and/or
0007  * modify it under the terms of the GNU Library General Public
0008  * License as published by the Free Software Foundation; either
0009  * version 2 of the License, or (at your option) any later version.
0010  *
0011  * This library is distributed in the hope that it will be useful,
0012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0014  * Library General Public License for more details.
0015  *
0016  * You should have received a copy of the GNU Library General Public License
0017  * along with this library; see the file COPYING.LIB. If not, write to
0018  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0019  * Boston, MA 02110-1301, USA.
0020  */
0021 
0022 #include <QApplication>
0023 #include <QCommandLineParser>
0024 #include <QDebug>
0025 #include <QRegExp>
0026 #include <QSocketNotifier>
0027 
0028 #include <KAboutData>
0029 #include <KLocalizedString>
0030 
0031 #include <iostream>
0032 
0033 #include <signal.h>
0034 #include <sys/socket.h>
0035 #include <sys/types.h>
0036 #include <unistd.h>
0037 
0038 #include <DebconfGui.h>
0039 
0040 using namespace DebconfKde;
0041 
0042 // Handle SIGQUIT. Clients (e.g. packagekit) may use QUIT which would otherwise
0043 // result in a core dump.
0044 // Qt methods aren't signal-safe, so we'll defer the handling via a socket
0045 // notification.
0046 static void setupQuitHandler() {
0047     static int quitFD[2];
0048     if (socketpair(AF_UNIX, SOCK_STREAM, 0, quitFD)) {
0049        qErrnoWarning("Failed to create socket");
0050     }
0051     auto notifier = new QSocketNotifier(quitFD[1], QSocketNotifier::Read, qApp);
0052     QObject::connect(notifier, &QSocketNotifier::activated, [notifier]() {
0053         notifier->setEnabled(false);
0054         char c;
0055         read(quitFD[1], &c, sizeof(c));
0056         qApp->quit();
0057     });
0058 
0059     struct sigaction sa;
0060     sa.sa_handler = [](int) -> void {
0061         char c = 1;
0062         write(quitFD[0], &c, sizeof(c));
0063     };
0064     sigemptyset(&sa.sa_mask);
0065     sigaddset(&sa.sa_mask, SIGQUIT);
0066     sa.sa_flags = 0;
0067     sa.sa_flags |= SA_RESTART;
0068 
0069     if (sigaction(SIGQUIT, &sa, 0) != 0) {
0070        qErrnoWarning("Failed to set quit handler");
0071     }
0072 }
0073 
0074 int main(int argc, char **argv)
0075 {
0076     QApplication app(argc, argv);
0077     setupQuitHandler();
0078 
0079     KLocalizedString::setApplicationDomain("libdebconf-kde");
0080 
0081     KAboutData aboutData(QStringLiteral("debconf-kde-helper"),
0082                          i18nc("@title", "Debconf KDE"),
0083                          QStringLiteral(PROJECT_VERSION),
0084                          i18nc("@info", "Debconf frontend based on Qt"),
0085                          KAboutLicense::LicenseKey::LGPL);
0086     KAboutData::setApplicationData(aboutData);
0087 
0088     QCommandLineParser parser;
0089     QCommandLineOption socketOption(QStringLiteral("socket-path"),
0090                                     i18nc("@info:shell", "Path to where the socket should be created"),
0091                                     i18nc("@info:shell value name", "path_to_socket"),
0092                                     QStringLiteral("/tmp/debkonf-sock"));
0093     parser.addOption(socketOption);
0094     QCommandLineOption fifoFdsOption(QStringLiteral("fifo-fds"),
0095                                     i18nc("@info:shell", "FIFO file descriptors for communication with Debconf"),
0096                                     i18nc("@info:shell value name", "read_fd,write_fd"));
0097     parser.addOption(fifoFdsOption);
0098     aboutData.setupCommandLine(&parser);
0099     parser.process(app);
0100     aboutData.processCommandLine(&parser);
0101 
0102     DebconfGui *dcf = nullptr;
0103     if (parser.isSet(fifoFdsOption)) {
0104         int readfd, writefd;
0105         QRegExp regex(QLatin1String("(\\d+),(\\d+)"));
0106         if (regex.exactMatch(parser.value(fifoFdsOption))) {
0107             readfd = regex.cap(1).toInt();
0108             writefd = regex.cap(2).toInt();
0109 
0110             dcf = new DebconfGui(readfd, writefd);
0111             dcf->connect(dcf, &DebconfGui::activated, dcf, &DebconfGui::show);
0112             // Once FIFO pipes are closed, they cannot be reopened. Hence we
0113             // should terminate as well.
0114             dcf->connect(dcf, &DebconfGui::deactivated, dcf, &DebconfGui::close);
0115         } else {
0116             qFatal("Incorrect value of the --fifo-fds parameter");
0117         }
0118     } else {
0119         QString path = parser.value(socketOption);
0120         dcf = new DebconfGui(path);
0121         std::cout << "export DEBIAN_FRONTEND=passthrough" << std::endl;
0122         std::cout << "export DEBCONF_PIPE=" << path.toUtf8().data() << std::endl;
0123 
0124         dcf->connect(dcf, &DebconfGui::activated, dcf, &DebconfGui::show);
0125         dcf->connect(dcf, &DebconfGui::deactivated, dcf, &DebconfGui::hide);
0126     }
0127 
0128     if (!dcf)
0129         return 1;
0130 
0131     return app.exec();
0132 }