File indexing completed on 2024-05-12 03:56:42
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 1999-2000 Waldo Bastian <bastian@kde.org> 0004 SPDX-FileCopyrightText: 1999 Mario Weilguni <mweilguni@sime.com> 0005 SPDX-FileCopyrightText: 2001 Lubos Lunak <l.lunak@kde.org> 0006 0007 SPDX-License-Identifier: LGPL-2.0-only 0008 */ 0009 0010 #include <cerrno> 0011 #include <locale.h> 0012 #include <signal.h> 0013 #include <stdio.h> 0014 #include <stdlib.h> 0015 0016 #include <QFile> 0017 #include <QLibrary> 0018 #include <QPluginLoader> 0019 #include <QString> 0020 0021 #ifdef Q_OS_WIN 0022 #include <QProcess> 0023 #include <QStandardPaths> 0024 #include <QStringList> 0025 0026 #include <process.h> 0027 #include <qt_windows.h> 0028 #endif 0029 0030 #ifndef Q_OS_WIN 0031 #include <unistd.h> 0032 0033 /* These are to link libkio even if 'smart' linker is used */ 0034 #include <kio/authinfo.h> 0035 extern "C" KIO::AuthInfo *_kioworker_init_kio() 0036 { 0037 return new KIO::AuthInfo(); 0038 } 0039 #endif 0040 0041 int main(int argc, char **argv) 0042 { 0043 if (argc < 5) { 0044 fprintf(stderr, "Usage: kioworker <worker-lib> <protocol> <klauncher-socket> <app-socket>\n\nThis program is part of KDE.\n"); 0045 return 1; 0046 } 0047 0048 setlocale(LC_ALL, ""); 0049 QString libname = QFile::decodeName(argv[1]); 0050 0051 if (libname.isEmpty()) { 0052 fprintf(stderr, "library path is empty.\n"); 0053 return 1; 0054 } 0055 0056 // Use QPluginLoader to locate the library when using a relative path 0057 // But we need to use QLibrary to actually load it, because of resolve()! 0058 QString libpath = QPluginLoader(libname).fileName(); 0059 if (libpath.isEmpty()) { 0060 fprintf(stderr, "could not locate %s, check QT_PLUGIN_PATH\n", qPrintable(libname)); 0061 return 1; 0062 } 0063 0064 QLibrary lib(libpath); 0065 if (!lib.load()) { 0066 fprintf(stderr, "could not open %s: %s\n", qPrintable(libname), qPrintable(lib.errorString())); 0067 return 1; 0068 } 0069 0070 QFunctionPointer sym = lib.resolve("kdemain"); 0071 if (!sym) { 0072 fprintf(stderr, "Could not find kdemain: %s\n", qPrintable(lib.errorString())); 0073 return 1; 0074 } 0075 0076 const QByteArray workerDebugWait = qgetenv("KIOWORKER_DEBUG_WAIT"); 0077 0078 #ifdef Q_OS_WIN 0079 // enter debugger in case debugging is activated 0080 if (workerDebugWait == "all" || workerDebugWait == argv[2]) { 0081 #ifdef Q_CC_MSVC 0082 // msvc debugger or windbg supports jit debugging, the latter requires setting up windbg jit with windbg -i 0083 DebugBreak(); 0084 #else 0085 // gdb does not support win32 jit debug support, so implement it by ourself 0086 WCHAR buf[1024]; 0087 GetModuleFileName(NULL, buf, 1024); 0088 QStringList params; 0089 params << QString::fromUtf16(reinterpret_cast<const char16_t *>(buf)); 0090 params << QString::number(GetCurrentProcessId()); 0091 const QString gdbExec = QStandardPaths::findExecutable(QStringLiteral("gdb")); 0092 if (gdbExec.isEmpty()) { 0093 fprintf(stderr, "Could not find 'gdb' executable in PATH\n"); 0094 return 1; 0095 } 0096 QProcess::startDetached(gdbExec, params); 0097 Sleep(1000); 0098 #endif 0099 } 0100 #if defined(Q_CC_MSVC) 0101 else { 0102 QString workerDebugPopup(QString::fromLocal8Bit(qgetenv("KIOWORKER_DEBUG_POPUP"))); 0103 if (workerDebugPopup == QLatin1String("all") || workerDebugPopup == QString::fromLocal8Bit(argv[2])) { 0104 // A workaround for OSes where DebugBreak() does not work in administrative mode (actually Vista with msvc 2k5) 0105 // - display a native message box so developer can attach the debugger to the KIO worker process and click OK. 0106 MessageBoxA( 0107 NULL, 0108 QStringLiteral("Please attach the debugger to process #%1 (%2)").arg(getpid()).arg(QString::fromLocal8Bit(argv[0])).toLatin1().constData(), 0109 QStringLiteral("\"%1\" KIO Worker Debugging").arg(QString::fromLocal8Bit(argv[2])).toLatin1().constData(), 0110 MB_OK | MB_ICONINFORMATION | MB_TASKMODAL); 0111 } 0112 } 0113 #endif 0114 #endif // Q_OS_WIN 0115 0116 #if defined(Q_OS_UNIX) 0117 // Enter debugger in case debugging is activated 0118 if (workerDebugWait == "all" || workerDebugWait == argv[2]) { 0119 const pid_t pid = getpid(); 0120 fprintf(stderr, 0121 "kioworker: Suspending process to debug io worker(s): %s\n" 0122 "kioworker: 'gdb kioworker %d' to debug\n" 0123 "kioworker: 'kill -SIGCONT %d' to continue\n", 0124 workerDebugWait.constData(), 0125 pid, 0126 pid); 0127 0128 kill(pid, SIGSTOP); 0129 } 0130 #endif 0131 0132 int (*func)(int, char *[]) = (int (*)(int, char *[]))sym; 0133 0134 // We need argv[0] to remain /path/to/kioworker 0135 // so that applicationDirPath() is correct on non-Linux (no /proc) 0136 // and we want to skip argv[1] so the kioworker exe is transparent to kdemain. 0137 const int newArgc = argc - 1; 0138 QVarLengthArray<char *, 5> newArgv(newArgc); 0139 newArgv[0] = argv[0]; 0140 for (int i = 1; i < newArgc; ++i) { 0141 newArgv[i] = argv[i + 1]; 0142 } 0143 0144 return func(newArgc, newArgv.data()); /* Launch! */ 0145 }