Warning, file /plasma/plasma-workspace/ksmserver/client.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002     ksmserver - the KDE session management server
0003 
0004     SPDX-FileCopyrightText: 2000 Matthias Ettrich <ettrich@kde.org>
0005     SPDX-FileCopyrightText: 2005 Lubos Lunak <l.lunak@kde.org>
0006 
0007     SPDX-FileContributor: Oswald Buddenhagen <ob6@inf.tu-dresden.de>
0008 
0009     some code taken from the dcopserver (part of the KDE libraries), which is
0010     SPDX-FileCopyrightText: 1999 Matthias Ettrich <ettrich@kde.org>
0011     SPDX-FileCopyrightText: 1999 Preston Brown <pbrown@kde.org>
0012 
0013     SPDX-License-Identifier: MIT
0014 */
0015 
0016 #include <config-workspace.h>
0017 
0018 #include "client.h"
0019 
0020 #include <stdlib.h>
0021 #include <unistd.h>
0022 #ifdef HAVE_SYS_TIME_H
0023 #include <sys/time.h>
0024 #endif
0025 #include <time.h>
0026 
0027 #include <QRandomGenerator>
0028 
0029 extern KSMServer *the_server;
0030 
0031 KSMClient::KSMClient(SmsConn conn)
0032     : smsConn(conn)
0033 {
0034     id = nullptr;
0035     resetState();
0036 }
0037 
0038 KSMClient::~KSMClient()
0039 {
0040     foreach (SmProp *prop, properties)
0041         SmFreeProperty(prop);
0042     if (id)
0043         free((void *)id);
0044 }
0045 
0046 SmProp *KSMClient::property(const char *name) const
0047 {
0048     foreach (SmProp *prop, properties) {
0049         if (!qstrcmp(prop->name, name))
0050             return prop;
0051     }
0052     return nullptr;
0053 }
0054 
0055 void KSMClient::resetState()
0056 {
0057     saveYourselfDone = false;
0058     pendingInteraction = false;
0059     waitForPhase2 = false;
0060     wasPhase2 = false;
0061 }
0062 
0063 /*
0064  * This fakes SmsGenerateClientID() in case we can't read our own hostname.
0065  * In this case SmsGenerateClientID() returns NULL, but we really want a
0066  * client ID, so we fake one.
0067  */
0068 Q_GLOBAL_STATIC(QString, my_addr)
0069 char *safeSmsGenerateClientID(SmsConn /*c*/)
0070 {
0071     //  Causes delays with misconfigured network :-/.
0072     //    char *ret = SmsGenerateClientID(c);
0073     char *ret = nullptr;
0074     if (!ret) {
0075         if (my_addr->isEmpty()) {
0076             //           qCWarning(KSMSERVER, "Can't get own host name. Your system is severely misconfigured\n");
0077 
0078             /* Faking our IP address, the 0 below is "unknown" address format
0079                (1 would be IP, 2 would be DEC-NET format) */
0080             char hostname[256];
0081             if (gethostname(hostname, 255) != 0)
0082                 *my_addr = QStringLiteral("0%1").arg(QRandomGenerator::global()->generate(), 8, 16);
0083             else {
0084                 // create some kind of hash for the hostname
0085                 int addr[4] = {0, 0, 0, 0};
0086                 int pos = 0;
0087                 for (unsigned int i = 0; i < strlen(hostname); ++i, ++pos)
0088                     addr[pos % 4] += hostname[i];
0089                 *my_addr = QStringLiteral("0");
0090                 for (int i = 0; i < 4; ++i)
0091                     *my_addr += QString::number(addr[i], 16);
0092             }
0093         }
0094         /* Needs to be malloc(), to look the same as libSM */
0095         ret = (char *)malloc(1 + my_addr->length() + 13 + 10 + 4 + 1 + /*safeness*/ 10);
0096         static int sequence = 0;
0097 
0098         if (ret == nullptr)
0099             return nullptr;
0100 
0101         sprintf(ret, "1%s%.13ld%.10d%.4d", my_addr->toLatin1().constData(), (long)time(nullptr), getpid(), sequence);
0102         sequence = (sequence + 1) % 10000;
0103     }
0104     return ret;
0105 }
0106 
0107 void KSMClient::registerClient(const char *previousId)
0108 {
0109     id = previousId;
0110     if (!id)
0111         id = safeSmsGenerateClientID(smsConn);
0112     SmsRegisterClientReply(smsConn, (char *)id);
0113     SmsSaveYourself(smsConn, SmSaveLocal, false, SmInteractStyleNone, false);
0114     SmsSaveComplete(smsConn);
0115     the_server->clientRegistered(previousId);
0116 }
0117 
0118 QString KSMClient::program() const
0119 {
0120     SmProp *p = property(SmProgram);
0121     if (!p || qstrcmp(p->type, SmARRAY8) || p->num_vals < 1)
0122         return QString();
0123     return QLatin1String((const char *)p->vals[0].value);
0124 }
0125 
0126 QStringList KSMClient::restartCommand() const
0127 {
0128     QStringList result;
0129     SmProp *p = property(SmRestartCommand);
0130     if (!p || qstrcmp(p->type, SmLISTofARRAY8) || p->num_vals < 1)
0131         return result;
0132     for (int i = 0; i < p->num_vals; i++)
0133         result += QLatin1String((const char *)p->vals[i].value);
0134     return result;
0135 }
0136 
0137 QStringList KSMClient::discardCommand() const
0138 {
0139     QStringList result;
0140     SmProp *p = property(SmDiscardCommand);
0141     if (!p || qstrcmp(p->type, SmLISTofARRAY8) || p->num_vals < 1)
0142         return result;
0143     for (int i = 0; i < p->num_vals; i++)
0144         result += QLatin1String((const char *)p->vals[i].value);
0145     return result;
0146 }
0147 
0148 int KSMClient::restartStyleHint() const
0149 {
0150     SmProp *p = property(SmRestartStyleHint);
0151     if (!p || qstrcmp(p->type, SmCARD8) || p->num_vals < 1)
0152         return SmRestartIfRunning;
0153     return *((unsigned char *)p->vals[0].value);
0154 }
0155 
0156 QString KSMClient::userId() const
0157 {
0158     SmProp *p = property(SmUserID);
0159     if (!p || qstrcmp(p->type, SmARRAY8) || p->num_vals < 1)
0160         return QString();
0161     return QLatin1String((const char *)p->vals[0].value);
0162 }