File indexing completed on 2024-05-05 17:39:48
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 mDaemon->start(); 0058 0059 return true; 0060 } 0061 0062 void SensorShellAgent::hostInfo(QString &shell, QString &command, int &port) const 0063 { 0064 shell = mShell; 0065 command = mCommand; 0066 port = -1; 0067 } 0068 0069 void SensorShellAgent::msgRcvd() 0070 { 0071 QByteArray buffer = mDaemon->readAllStandardOutput(); 0072 mRetryCount = 3; // we received an answer, so reset our retry count back to 3 0073 processAnswer(buffer.constData(), buffer.size()); 0074 } 0075 0076 void SensorShellAgent::errMsgRcvd() 0077 { 0078 const QByteArray buffer = mDaemon->readAllStandardOutput(); 0079 0080 // Because we read the error buffer in chunks, we may not have a proper utf8 string. 0081 // We should never get input over stderr anyway, so no need to worry too much about it. 0082 // But if this is extended, we will need to handle this better 0083 const QString buf = QString::fromUtf8(buffer); 0084 0085 qCDebug(LIBKSYSGUARD_KSGRD) << "SensorShellAgent: Warning, received text over stderr!" 0086 << "\n" 0087 << buf; 0088 } 0089 0090 void SensorShellAgent::daemonExited(int exitCode, QProcess::ExitStatus exitStatus) 0091 { 0092 Q_UNUSED(exitCode); 0093 qCDebug(LIBKSYSGUARD_KSGRD) << "daemon exited, exit status " << exitStatus; 0094 if (mRetryCount-- <= 0 || (mDaemon->start(), !mDaemon->waitForStarted())) { 0095 setDaemonOnLine(false); 0096 if (sensorManager()) { 0097 sensorManager()->disengage(this); // delete ourselves 0098 } 0099 } 0100 } 0101 0102 void SensorShellAgent::daemonError(QProcess::ProcessError errorStatus) 0103 { 0104 QString error; 0105 switch (errorStatus) { 0106 case QProcess::FailedToStart: 0107 qCDebug(LIBKSYSGUARD_KSGRD) << "failed to run" << mDaemon->program().join(QLatin1Char(' ')); 0108 error = i18n("Could not run daemon program '%1'.", mDaemon->program().join(" ")); 0109 break; 0110 case QProcess::Crashed: 0111 case QProcess::Timedout: 0112 case QProcess::WriteError: 0113 case QProcess::ReadError: 0114 default: 0115 error = i18n("The daemon program '%1' failed.", mDaemon->program().join(" ")); 0116 } 0117 setReasonForOffline(error); 0118 qCDebug(LIBKSYSGUARD_KSGRD) << "Error received " << error << "(" << errorStatus << ")"; 0119 setDaemonOnLine(false); 0120 if (sensorManager()) 0121 sensorManager()->disengage(this); // delete ourselves 0122 } 0123 bool SensorShellAgent::writeMsg(const char *msg, int len) 0124 { 0125 // write returns -1 on error, in which case we should return false. true otherwise. 0126 return mDaemon->write(msg, len) != -1; 0127 }