/* ksmserver - the KDE session management server SPDX-FileCopyrightText: 2000 Matthias Ettrich SPDX-FileCopyrightText: 2005 Lubos Lunak SPDX-FileContributor: Oswald Buddenhagen some code taken from the dcopserver (part of the KDE libraries), which is SPDX-FileCopyrightText: 1999 Matthias Ettrich SPDX-FileCopyrightText: 1999 Preston Brown SPDX-License-Identifier: MIT */ #include #include "client.h" #include #include #ifdef HAVE_SYS_TIME_H #include #endif #include #include extern KSMServer *the_server; KSMClient::KSMClient(SmsConn conn) : smsConn(conn) { id = nullptr; resetState(); } KSMClient::~KSMClient() { for (SmProp *prop : std::as_const(properties)) SmFreeProperty(prop); if (id) free((void *)id); } SmProp *KSMClient::property(const char *name) const { for (SmProp *prop : std::as_const(properties)) { if (!qstrcmp(prop->name, name)) return prop; } return nullptr; } void KSMClient::resetState() { saveYourselfDone = false; pendingInteraction = false; waitForPhase2 = false; wasPhase2 = false; } /* * This fakes SmsGenerateClientID() in case we can't read our own hostname. * In this case SmsGenerateClientID() returns NULL, but we really want a * client ID, so we fake one. */ Q_GLOBAL_STATIC(QString, my_addr) char *safeSmsGenerateClientID(SmsConn /*c*/) { // Causes delays with misconfigured network :-/. // char *ret = SmsGenerateClientID(c); char *ret = nullptr; if (!ret) { if (my_addr->isEmpty()) { // qCWarning(KSMSERVER, "Can't get own host name. Your system is severely misconfigured\n"); /* Faking our IP address, the 0 below is "unknown" address format (1 would be IP, 2 would be DEC-NET format) */ char hostname[256]; if (gethostname(hostname, 255) != 0) *my_addr = QStringLiteral("0%1").arg(QRandomGenerator::global()->generate(), 8, 16); else { // create some kind of hash for the hostname int addr[4] = {0, 0, 0, 0}; int pos = 0; for (unsigned int i = 0; i < strlen(hostname); ++i, ++pos) addr[pos % 4] += hostname[i]; *my_addr = QStringLiteral("0"); for (int i = 0; i < 4; ++i) *my_addr += QString::number(addr[i], 16); } } /* Needs to be malloc(), to look the same as libSM */ ret = (char *)malloc(1 + my_addr->length() + 13 + 10 + 4 + 1 + /*safeness*/ 10); static int sequence = 0; if (ret == nullptr) return nullptr; sprintf(ret, "1%s%.13ld%.10d%.4d", my_addr->toLatin1().constData(), (long)time(nullptr), getpid(), sequence); sequence = (sequence + 1) % 10000; } return ret; } void KSMClient::registerClient(const char *previousId) { id = previousId; if (!id) id = safeSmsGenerateClientID(smsConn); SmsRegisterClientReply(smsConn, (char *)id); SmsSaveYourself(smsConn, SmSaveLocal, false, SmInteractStyleNone, false); SmsSaveComplete(smsConn); the_server->clientRegistered(previousId); } QString KSMClient::program() const { SmProp *p = property(SmProgram); if (!p || qstrcmp(p->type, SmARRAY8) || p->num_vals < 1) return QString(); return QLatin1String((const char *)p->vals[0].value); } QStringList KSMClient::restartCommand() const { QStringList result; SmProp *p = property(SmRestartCommand); if (!p || qstrcmp(p->type, SmLISTofARRAY8) || p->num_vals < 1) return result; for (int i = 0; i < p->num_vals; i++) result += QLatin1String((const char *)p->vals[i].value); return result; } QStringList KSMClient::discardCommand() const { QStringList result; SmProp *p = property(SmDiscardCommand); if (!p || qstrcmp(p->type, SmLISTofARRAY8) || p->num_vals < 1) return result; for (int i = 0; i < p->num_vals; i++) result += QLatin1String((const char *)p->vals[i].value); return result; } int KSMClient::restartStyleHint() const { SmProp *p = property(SmRestartStyleHint); if (!p || qstrcmp(p->type, SmCARD8) || p->num_vals < 1) return SmRestartIfRunning; return *((unsigned char *)p->vals[0].value); } QString KSMClient::userId() const { SmProp *p = property(SmUserID); if (!p || qstrcmp(p->type, SmARRAY8) || p->num_vals < 1) return QString(); return QLatin1String((const char *)p->vals[0].value); }