File indexing completed on 2024-04-21 14:53:25

0001 /*
0002     SPDX-FileCopyrightText: 2008 Nicola Gigante <nicola.gigante@gmail.com>
0003     SPDX-FileCopyrightText: 2009 Dario Freddi <drf@kde.org>
0004     SPDX-FileCopyrightText: 2020 Harald Sitter <sitter@kde.org>
0005 
0006     SPDX-License-Identifier: LGPL-2.1-or-later
0007 */
0008 
0009 #include "helpersupport.h"
0010 
0011 #include <cstdlib>
0012 
0013 #ifndef Q_OS_WIN
0014 #include <pwd.h>
0015 #include <sys/types.h>
0016 #include <syslog.h>
0017 #include <unistd.h>
0018 #else
0019 // Quick hack to replace syslog (just write to stderr)
0020 // TODO: should probably use ReportEvent
0021 #define LOG_ERR 3
0022 #define LOG_WARNING 4
0023 #define LOG_DEBUG 7
0024 #define LOG_INFO 6
0025 #define LOG_USER (1 << 3)
0026 static inline void openlog(const char *, int, int)
0027 {
0028 }
0029 static inline void closelog()
0030 {
0031 }
0032 #define syslog(level, ...) fprintf(stderr, __VA_ARGS__)
0033 
0034 #endif
0035 
0036 #include <QCoreApplication>
0037 #include <QTimer>
0038 #if defined(Q_OS_UNIX) && QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0039 #include <QTextCodec>
0040 #endif
0041 
0042 #include "BackendsManager.h"
0043 
0044 namespace KAuth
0045 {
0046 namespace HelperSupport
0047 {
0048 void helperDebugHandler(QtMsgType type, const QMessageLogContext &context, const QString &msgStr);
0049 }
0050 
0051 static bool remote_dbg = false;
0052 
0053 #ifdef Q_OS_UNIX
0054 static void fixEnvironment()
0055 {
0056     // try correct HOME
0057     const char *home = "HOME";
0058     if (getenv(home) == nullptr) {
0059         struct passwd *pw = getpwuid(getuid());
0060 
0061         if (pw != nullptr) {
0062             int overwrite = 0;
0063             setenv(home, pw->pw_dir, overwrite);
0064         }
0065     }
0066 }
0067 #endif
0068 
0069 int HelperSupport::helperMain(int argc, char **argv, const char *id, QObject *responder)
0070 {
0071 #ifdef Q_OS_UNIX
0072     fixEnvironment();
0073 
0074     // With Qt6, it's UTF-8 by default
0075 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0076     // As we don't inherit lang, the locale could be something that doesn't support UTF-8. Force it
0077     auto utf8Codec = QTextCodec::codecForName("UTF-8");
0078     if (utf8Codec) {
0079         QTextCodec::setCodecForLocale(utf8Codec);
0080     }
0081 #endif
0082 #endif
0083 
0084 #ifdef Q_OS_OSX
0085     openlog(id, LOG_CONS | LOG_PID, LOG_USER);
0086     int logLevel = LOG_WARNING;
0087 #else
0088     openlog(id, 0, LOG_USER);
0089     int logLevel = LOG_DEBUG;
0090 #endif
0091     qInstallMessageHandler(&HelperSupport::helperDebugHandler);
0092 
0093     // NOTE: The helper proxy might use dbus, and we should have the qapp
0094     //       before using dbus.
0095     QCoreApplication app(argc, argv);
0096 
0097     if (!BackendsManager::helperProxy()->initHelper(QString::fromLatin1(id))) {
0098         syslog(logLevel, "Helper initialization failed");
0099         return -1;
0100     }
0101 
0102     // closelog();
0103     remote_dbg = true;
0104 
0105     BackendsManager::helperProxy()->setHelperResponder(responder);
0106 
0107     // Attach the timer
0108     QTimer *timer = new QTimer(nullptr);
0109     responder->setProperty("__KAuth_Helper_Shutdown_Timer", QVariant::fromValue(timer));
0110     timer->setInterval(10000);
0111     timer->start();
0112     QObject::connect(timer, &QTimer::timeout, &app, &QCoreApplication::quit);
0113     app.exec(); // krazy:exclude=crashy
0114 
0115     return 0;
0116 }
0117 
0118 void HelperSupport::helperDebugHandler(QtMsgType type, const QMessageLogContext &context, const QString &msgStr)
0119 {
0120     Q_UNUSED(context); // can be used to find out about file, line, function name
0121     QByteArray msg = msgStr.toLocal8Bit();
0122     if (!remote_dbg) {
0123         int level = LOG_DEBUG;
0124         switch (type) {
0125         case QtDebugMsg:
0126             level = LOG_DEBUG;
0127             break;
0128         case QtWarningMsg:
0129             level = LOG_WARNING;
0130             break;
0131         case QtCriticalMsg:
0132         case QtFatalMsg:
0133             level = LOG_ERR;
0134             break;
0135         case QtInfoMsg:
0136             level = LOG_INFO;
0137             break;
0138         }
0139         syslog(level, "%s", msg.constData());
0140     } else {
0141         BackendsManager::helperProxy()->sendDebugMessage(type, msg.constData());
0142     }
0143 
0144     // Anyway I should follow the rule:
0145     if (type == QtFatalMsg) {
0146         exit(-1);
0147     }
0148 }
0149 
0150 void HelperSupport::progressStep(int step)
0151 {
0152     BackendsManager::helperProxy()->sendProgressStep(step);
0153 }
0154 
0155 void HelperSupport::progressStep(const QVariantMap &data)
0156 {
0157     BackendsManager::helperProxy()->sendProgressStepData(data);
0158 }
0159 
0160 bool HelperSupport::isStopped()
0161 {
0162     return BackendsManager::helperProxy()->hasToStopAction();
0163 }
0164 
0165 int HelperSupport::callerUid()
0166 {
0167     return BackendsManager::helperProxy()->callerUid();
0168 }
0169 
0170 } // namespace Auth