File indexing completed on 2024-04-21 16:17:05

0001 /*
0002     kwrited is a write(1) receiver for KDE.
0003     SPDX-FileCopyrightText: 1997, 1998 Lars Doelle <lars.doelle@on-line.de>
0004     SPDX-FileCopyrightText: 2008 George Kiagiadakis <gkiagia@users.sourceforge.net>
0005 
0006     SPDX-License-Identifier: GPL-2.0-or-later
0007 */
0008 
0009 // Own
0010 #include "kwrited.h"
0011 
0012 #include <QDebug>
0013 #include <kaboutdata.h>
0014 #include <klocalizedstring.h>
0015 #include <knotification.h>
0016 #include <kptydevice.h>
0017 #include <kuser.h>
0018 
0019 #if BUILD_AS_EXECUTABLE
0020 #include <QGuiApplication>
0021 #include <QSessionManager>
0022 #include <signal.h>
0023 #include <sys/types.h>
0024 #include <unistd.h>
0025 #else
0026 #include <kpluginfactory.h>
0027 #include <kpluginloader.h>
0028 #endif
0029 
0030 static inline KAboutData aboutData()
0031 {
0032     return KAboutData(QStringLiteral("kwrited"), i18n("kwrited"), QLatin1String(PROJECT_VERSION));
0033 }
0034 
0035 #if BUILD_AS_EXECUTABLE
0036 
0037 static uid_t original_euid;
0038 static gid_t original_egid;
0039 
0040 static void sigterm_handler(int signal)
0041 {
0042     Q_UNUSED(signal)
0043     QGuiApplication::quit();
0044 }
0045 
0046 int main(int argc, char **argv)
0047 {
0048     // drop elevated privileges temporarily
0049     original_euid = geteuid();
0050     original_egid = getegid();
0051     seteuid(getuid());
0052     setegid(getgid());
0053 
0054     // install a signal handler to exit gracefully
0055     //(so that pty->logout() is called in ~KWrited())
0056     signal(SIGTERM, sigterm_handler);
0057     signal(SIGINT, sigterm_handler);
0058     signal(SIGHUP, sigterm_handler);
0059 
0060     QGuiApplication::setDesktopSettingsAware(false);
0061     QGuiApplication a(argc, argv);
0062     KAboutData::setApplicationData(aboutData());
0063 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0064     QGuiApplication::setFallbackSessionManagementEnabled(false);
0065 #endif
0066     auto disableSessionManagement = [](QSessionManager &sm) {
0067         sm.setRestartHint(QSessionManager::RestartNever);
0068     };
0069     QObject::connect(&a, &QGuiApplication::commitDataRequest, disableSessionManagement);
0070     QObject::connect(&a, &QGuiApplication::saveStateRequest, disableSessionManagement);
0071 
0072     KWrited w;
0073     return a.exec();
0074 }
0075 
0076 #else // BUILD_AS_EXECUTABLE
0077 
0078 KWritedModule::KWritedModule(QObject *parent, const QList<QVariant> &)
0079     : KDEDModule(parent)
0080 {
0081     pro = new KWrited;
0082 }
0083 
0084 KWritedModule::~KWritedModule()
0085 {
0086     delete pro;
0087 }
0088 
0089 K_PLUGIN_FACTORY_WITH_JSON(KWritedFactory, "kwrited.json", registerPlugin<KWritedModule>();)
0090 
0091 #endif // BUILD_AS_EXECUTABLE
0092 
0093 KWrited::KWrited()
0094     : QObject()
0095 {
0096     pty = new KPtyDevice();
0097     pty->open();
0098 
0099 #if BUILD_AS_EXECUTABLE
0100     dup2(pty->slaveFd(), 0); // HACK: login() from glibc requires this to login correctly
0101     // restore elevated privileges
0102     seteuid(original_euid);
0103     setegid(original_egid);
0104 #endif
0105 
0106     pty->login(KUser(KUser::UseRealUserID).loginName().toLocal8Bit().data(), qgetenv("DISPLAY").constData());
0107 
0108 #if BUILD_AS_EXECUTABLE
0109     // drop privileges again
0110     seteuid(getuid());
0111     setegid(getgid());
0112 #endif
0113 
0114     connect(pty, &QIODevice::readyRead, this, &KWrited::block_in);
0115     // qDebug() << "listening on device" << pty->ttyName();
0116 }
0117 
0118 KWrited::~KWrited()
0119 {
0120 #if BUILD_AS_EXECUTABLE
0121     // restore elevated privileges
0122     seteuid(original_euid);
0123     setegid(original_egid);
0124 #endif
0125 
0126     pty->logout();
0127 
0128 #if BUILD_AS_EXECUTABLE
0129     // drop privileges again
0130     seteuid(getuid());
0131     setegid(getgid());
0132 #endif
0133 
0134     delete pty;
0135 }
0136 
0137 void KWrited::block_in()
0138 {
0139     QByteArray buf = pty->readAll();
0140     QString msg = QString::fromLocal8Bit(buf.constData(), buf.size());
0141     msg.remove(QLatin1Char('\r'));
0142     msg.remove(QLatin1Char('\a'));
0143     msg = msg.trimmed();
0144 
0145     KNotification *notification = new KNotification(QStringLiteral("NewMessage"), KNotification::Persistent);
0146 #if !BUILD_AS_EXECUTABLE
0147     notification->setComponentName(QStringLiteral("kwrited"));
0148 #endif
0149     notification->setText(msg);
0150     notification->setFlags(KNotification::SkipGrouping);
0151     connect(notification, &KNotification::closed, notification, &QObject::deleteLater);
0152     notification->sendEvent();
0153 }
0154 
0155 #if !BUILD_AS_EXECUTABLE
0156 #include "kwrited.moc"
0157 #endif