File indexing completed on 2024-04-28 09:25:22

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 #endif
0028 
0029 static inline KAboutData aboutData()
0030 {
0031     return KAboutData(QStringLiteral("kwrited"), i18n("kwrited"), QLatin1String(PROJECT_VERSION));
0032 }
0033 
0034 #if BUILD_AS_EXECUTABLE
0035 
0036 static uid_t original_euid;
0037 static gid_t original_egid;
0038 
0039 static void sigterm_handler(int signal)
0040 {
0041     Q_UNUSED(signal)
0042     QGuiApplication::quit();
0043 }
0044 
0045 int main(int argc, char **argv)
0046 {
0047     // drop elevated privileges temporarily
0048     original_euid = geteuid();
0049     original_egid = getegid();
0050     seteuid(getuid());
0051     setegid(getgid());
0052 
0053     // install a signal handler to exit gracefully
0054     //(so that pty->logout() is called in ~KWrited())
0055     signal(SIGTERM, sigterm_handler);
0056     signal(SIGINT, sigterm_handler);
0057     signal(SIGHUP, sigterm_handler);
0058 
0059     QGuiApplication::setDesktopSettingsAware(false);
0060     QGuiApplication a(argc, argv);
0061     KAboutData::setApplicationData(aboutData());
0062     auto disableSessionManagement = [](QSessionManager &sm) {
0063         sm.setRestartHint(QSessionManager::RestartNever);
0064     };
0065     QObject::connect(&a, &QGuiApplication::commitDataRequest, disableSessionManagement);
0066     QObject::connect(&a, &QGuiApplication::saveStateRequest, disableSessionManagement);
0067 
0068     KWrited w;
0069     return a.exec();
0070 }
0071 
0072 #else // BUILD_AS_EXECUTABLE
0073 
0074 KWritedModule::KWritedModule(QObject *parent, const QList<QVariant> &)
0075     : KDEDModule(parent)
0076 {
0077     pro = new KWrited;
0078 }
0079 
0080 KWritedModule::~KWritedModule()
0081 {
0082     delete pro;
0083 }
0084 
0085 K_PLUGIN_FACTORY_WITH_JSON(KWritedFactory, "kwrited.json", registerPlugin<KWritedModule>();)
0086 
0087 #endif // BUILD_AS_EXECUTABLE
0088 
0089 KWrited::KWrited()
0090     : QObject()
0091 {
0092     pty = new KPtyDevice();
0093     pty->open();
0094 
0095 #if BUILD_AS_EXECUTABLE
0096     dup2(pty->slaveFd(), 0); // HACK: login() from glibc requires this to login correctly
0097     // restore elevated privileges
0098     seteuid(original_euid);
0099     setegid(original_egid);
0100 #endif
0101 
0102     pty->login(KUser(KUser::UseRealUserID).loginName().toLocal8Bit().data(), qgetenv("DISPLAY").constData());
0103 
0104 #if BUILD_AS_EXECUTABLE
0105     // drop privileges again
0106     seteuid(getuid());
0107     setegid(getgid());
0108 #endif
0109 
0110     connect(pty, &QIODevice::readyRead, this, &KWrited::block_in);
0111     // qDebug() << "listening on device" << pty->ttyName();
0112 }
0113 
0114 KWrited::~KWrited()
0115 {
0116 #if BUILD_AS_EXECUTABLE
0117     // restore elevated privileges
0118     seteuid(original_euid);
0119     setegid(original_egid);
0120 #endif
0121 
0122     pty->logout();
0123 
0124 #if BUILD_AS_EXECUTABLE
0125     // drop privileges again
0126     seteuid(getuid());
0127     setegid(getgid());
0128 #endif
0129 
0130     delete pty;
0131 }
0132 
0133 void KWrited::block_in()
0134 {
0135     QByteArray buf = pty->readAll();
0136     QString msg = QString::fromLocal8Bit(buf.constData(), buf.size());
0137     msg.remove(QLatin1Char('\r'));
0138     msg.remove(QLatin1Char('\a'));
0139     msg = msg.trimmed();
0140 
0141     KNotification *notification = new KNotification(QStringLiteral("NewMessage"), KNotification::Persistent);
0142 #if !BUILD_AS_EXECUTABLE
0143     notification->setComponentName(QStringLiteral("kwrited"));
0144 #endif
0145     notification->setText(msg);
0146     notification->setFlags(KNotification::SkipGrouping);
0147     connect(notification, &KNotification::closed, notification, &QObject::deleteLater);
0148     notification->sendEvent();
0149 }
0150 
0151 #if !BUILD_AS_EXECUTABLE
0152 #include "kwrited.moc"
0153 #endif
0154 
0155 #include "moc_kwrited.cpp"