File indexing completed on 2024-05-05 05:34:26
0001 /* 0002 KSysGuard, the KDE System Guard 0003 0004 SPDX-FileCopyrightText: 1999-2001 Chris Schlaeger <cs@kde.org> 0005 0006 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0007 0008 */ 0009 0010 #include <QDebug> 0011 #include <klocalizedstring.h> 0012 #include <kprocess.h> 0013 #include <kshell.h> 0014 0015 #include "SensorManager.h" 0016 #include "ksgrd_debug.h" 0017 0018 #include "SensorShellAgent.h" 0019 0020 using namespace KSGRD; 0021 0022 SensorShellAgent::SensorShellAgent(SensorManager *sm) 0023 : SensorAgent(sm) 0024 , mDaemon(nullptr) 0025 { 0026 } 0027 0028 SensorShellAgent::~SensorShellAgent() 0029 { 0030 if (mDaemon) { 0031 mDaemon->write("quit\n", sizeof("quit\n") - 1); 0032 mDaemon->disconnect(); 0033 mDaemon->waitForFinished(); 0034 delete mDaemon; 0035 mDaemon = nullptr; 0036 } 0037 } 0038 0039 bool SensorShellAgent::start(const QString &host, const QString &shell, const QString &command, int) 0040 { 0041 mDaemon = new KProcess(); 0042 mDaemon->setOutputChannelMode(KProcess::SeparateChannels); 0043 mRetryCount = 3; 0044 setHostName(host); 0045 mShell = shell; 0046 mCommand = command; 0047 0048 connect(mDaemon, SIGNAL(error(QProcess::ProcessError)), SLOT(daemonError(QProcess::ProcessError))); 0049 connect(mDaemon, SIGNAL(finished(int, QProcess::ExitStatus)), SLOT(daemonExited(int, QProcess::ExitStatus))); 0050 connect(mDaemon.data(), &QProcess::readyReadStandardOutput, this, &SensorShellAgent::msgRcvd); 0051 connect(mDaemon.data(), &QProcess::readyReadStandardError, this, &SensorShellAgent::errMsgRcvd); 0052 0053 if (!command.isEmpty()) { 0054 *mDaemon << KShell::splitArgs(command); 0055 } else { 0056 *mDaemon << mShell << hostName() << QStringLiteral("ksysguardd"); 0057 } 0058 mDaemon->start(); 0059 0060 return true; 0061 } 0062 0063 void SensorShellAgent::hostInfo(QString &shell, QString &command, int &port) const 0064 { 0065 shell = mShell; 0066 command = mCommand; 0067 port = -1; 0068 } 0069 0070 void SensorShellAgent::msgRcvd() 0071 { 0072 QByteArray buffer = mDaemon->readAllStandardOutput(); 0073 mRetryCount = 3; // we received an answer, so reset our retry count back to 3 0074 processAnswer(buffer.constData(), buffer.size()); 0075 } 0076 0077 void SensorShellAgent::errMsgRcvd() 0078 { 0079 const QByteArray buffer = mDaemon->readAllStandardOutput(); 0080 0081 // Because we read the error buffer in chunks, we may not have a proper utf8 string. 0082 // We should never get input over stderr anyway, so no need to worry too much about it. 0083 // But if this is extended, we will need to handle this better 0084 const QString buf = QString::fromUtf8(buffer); 0085 0086 qCDebug(LIBKSYSGUARD_KSGRD) << "SensorShellAgent: Warning, received text over stderr!" 0087 << "\n" 0088 << buf; 0089 } 0090 0091 void SensorShellAgent::daemonExited(int exitCode, QProcess::ExitStatus exitStatus) 0092 { 0093 Q_UNUSED(exitCode); 0094 qCDebug(LIBKSYSGUARD_KSGRD) << "daemon exited, exit status " << exitStatus; 0095 if (mRetryCount-- <= 0 || (mDaemon->start(), !mDaemon->waitForStarted())) { 0096 setDaemonOnLine(false); 0097 if (sensorManager()) { 0098 sensorManager()->disengage(this); // delete ourselves 0099 } 0100 } 0101 } 0102 0103 void SensorShellAgent::daemonError(QProcess::ProcessError errorStatus) 0104 { 0105 QString error; 0106 switch (errorStatus) { 0107 case QProcess::FailedToStart: 0108 qCDebug(LIBKSYSGUARD_KSGRD) << "failed to run" << mDaemon->program().join(QLatin1Char(' ')); 0109 error = i18n("Could not run daemon program '%1'.", mDaemon->program().join(" ")); 0110 break; 0111 case QProcess::Crashed: 0112 case QProcess::Timedout: 0113 case QProcess::WriteError: 0114 case QProcess::ReadError: 0115 default: 0116 error = i18n("The daemon program '%1' failed.", mDaemon->program().join(" ")); 0117 } 0118 setReasonForOffline(error); 0119 qCDebug(LIBKSYSGUARD_KSGRD) << "Error received " << error << "(" << errorStatus << ")"; 0120 setDaemonOnLine(false); 0121 if (sensorManager()) { 0122 sensorManager()->disengage(this); // delete ourselves 0123 } 0124 } 0125 0126 bool SensorShellAgent::writeMsg(const char *msg, int len) 0127 { 0128 // write returns -1 on error, in which case we should return false. true otherwise. 0129 return mDaemon->write(msg, len) != -1; 0130 }