1/*
2 This file is part of the KDE libraries
3 SPDX-FileCopyrightText: 1999-2000 Waldo Bastian <bastian@kde.org>
4 SPDX-FileCopyrightText: 1999 Mario Weilguni <mweilguni@sime.com>
5 SPDX-FileCopyrightText: 2001 Lubos Lunak <l.lunak@kde.org>
6
7 SPDX-License-Identifier: LGPL-2.0-only
8*/
9
10#include <cerrno>
11#include <locale.h>
12#include <signal.h>
13#include <stdio.h>
14#include <stdlib.h>
15
16#include <QFile>
17#include <QLibrary>
18#include <QPluginLoader>
19#include <QString>
20
21#ifdef Q_OS_WIN
22#include <QProcess>
23#include <QStandardPaths>
24#include <QStringList>
25
26#include <process.h>
27#include <qt_windows.h>
28#endif
29
30#ifndef Q_OS_WIN
31#include <unistd.h>
32
33/* These are to link libkio even if 'smart' linker is used */
34#include <kio/authinfo.h>
35extern "C" KIO::AuthInfo *_kioworker_init_kio()
36{
37 return new KIO::AuthInfo();
38}
39#endif
40
41int main(int argc, char **argv)
42{
43 if (argc < 5) {
44 fprintf(stderr, format: "Usage: kioworker <worker-lib> <protocol> <klauncher-socket> <app-socket>\n\nThis program is part of KDE.\n");
45 return 1;
46 }
47
48 setlocale(LC_ALL, locale: "");
49 QString libname = QFile::decodeName(localFileName: argv[1]);
50
51 if (libname.isEmpty()) {
52 fprintf(stderr, format: "library path is empty.\n");
53 return 1;
54 }
55
56 // Use QPluginLoader to locate the library when using a relative path
57 // But we need to use QLibrary to actually load it, because of resolve()!
58 QString libpath = QPluginLoader(libname).fileName();
59 if (libpath.isEmpty()) {
60 fprintf(stderr, format: "could not locate %s, check QT_PLUGIN_PATH\n", qPrintable(libname));
61 return 1;
62 }
63
64 QLibrary lib(libpath);
65 if (!lib.load()) {
66 fprintf(stderr, format: "could not open %s: %s\n", qPrintable(libname), qPrintable(lib.errorString()));
67 return 1;
68 }
69
70 QFunctionPointer sym = lib.resolve(symbol: "kdemain");
71 if (!sym) {
72 fprintf(stderr, format: "Could not find kdemain: %s\n", qPrintable(lib.errorString()));
73 return 1;
74 }
75
76 const QByteArray workerDebugWait = qgetenv(varName: "KIOWORKER_DEBUG_WAIT");
77
78#ifdef Q_OS_WIN
79 // enter debugger in case debugging is activated
80 if (workerDebugWait == "all" || workerDebugWait == argv[2]) {
81#ifdef Q_CC_MSVC
82 // msvc debugger or windbg supports jit debugging, the latter requires setting up windbg jit with windbg -i
83 DebugBreak();
84#else
85 // gdb does not support win32 jit debug support, so implement it by ourself
86 WCHAR buf[1024];
87 GetModuleFileName(NULL, buf, 1024);
88 QStringList params;
89 params << QString::fromUtf16(reinterpret_cast<const char16_t *>(buf));
90 params << QString::number(GetCurrentProcessId());
91 const QString gdbExec = QStandardPaths::findExecutable(QStringLiteral("gdb"));
92 if (gdbExec.isEmpty()) {
93 fprintf(stderr, "Could not find 'gdb' executable in PATH\n");
94 return 1;
95 }
96 QProcess::startDetached(gdbExec, params);
97 Sleep(1000);
98#endif
99 }
100#if defined(Q_CC_MSVC)
101 else {
102 QString workerDebugPopup(QString::fromLocal8Bit(qgetenv("KIOWORKER_DEBUG_POPUP")));
103 if (workerDebugPopup == QLatin1String("all") || workerDebugPopup == QString::fromLocal8Bit(argv[2])) {
104 // A workaround for OSes where DebugBreak() does not work in administrative mode (actually Vista with msvc 2k5)
105 // - display a native message box so developer can attach the debugger to the KIO worker process and click OK.
106 MessageBoxA(
107 NULL,
108 QStringLiteral("Please attach the debugger to process #%1 (%2)").arg(getpid()).arg(QString::fromLocal8Bit(argv[0])).toLatin1().constData(),
109 QStringLiteral("\"%1\" KIO Worker Debugging").arg(QString::fromLocal8Bit(argv[2])).toLatin1().constData(),
110 MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
111 }
112 }
113#endif
114#endif // Q_OS_WIN
115
116#if defined(Q_OS_UNIX)
117 // Enter debugger in case debugging is activated
118 if (workerDebugWait == "all" || workerDebugWait == argv[2]) {
119 const pid_t pid = getpid();
120 fprintf(stderr,
121 format: "kioworker: Suspending process to debug io worker(s): %s\n"
122 "kioworker: 'gdb kioworker %d' to debug\n"
123 "kioworker: 'kill -SIGCONT %d' to continue\n",
124 workerDebugWait.constData(),
125 pid,
126 pid);
127
128 kill(pid: pid, SIGSTOP);
129 }
130#endif
131
132 int (*func)(int, char *[]) = (int (*)(int, char *[]))sym;
133
134 // We need argv[0] to remain /path/to/kioworker
135 // so that applicationDirPath() is correct on non-Linux (no /proc)
136 // and we want to skip argv[1] so the kioworker exe is transparent to kdemain.
137 const int newArgc = argc - 1;
138 QVarLengthArray<char *, 5> newArgv(newArgc);
139 newArgv[0] = argv[0];
140 for (int i = 1; i < newArgc; ++i) {
141 newArgv[i] = argv[i + 1];
142 }
143
144 return func(newArgc, newArgv.data()); /* Launch! */
145}
146

source code of kio/src/kioworker/kioworker.cpp