1 /*
2     This file is part of the KDE libraries
3     SPDX-FileCopyrightText: 1999 David Faure <faure@kde.org>
4     SPDX-FileCopyrightText: 2002-2003 Waldo Bastian <bastian@kde.org>
5 
6     SPDX-License-Identifier: LGPL-2.0-only
7 */
8 
9 #include <kbuildsycoca_p.h>
10 
11 #include "../../kservice_version.h"
12 
13 #include <KAboutData>
14 #include <KLocalizedString>
15 
16 #include <QCommandLineOption>
17 #include <QCommandLineParser>
18 #include <QCoreApplication>
19 #include <QDateTime>
20 #include <QDebug>
21 #include <QDir>
22 #include <QFile>
23 #include <QFileInfo>
24 #include <QStandardPaths>
25 
26 #include <qplatformdefs.h> // for unlink
27 #ifdef Q_OS_WIN
28 #include <qt_windows.h>
29 #endif
30 
crashHandler(int)31 static void crashHandler(int)
32 {
33     // If we crash while reading sycoca, we delete the database
34     // in an attempt to recover.
35     if (KBuildSycoca::sycocaPath()) {
36         unlink(KBuildSycoca::sycocaPath());
37     }
38 }
39 
40 #if defined(Q_OS_WIN)
41 // glue function for calling the unix signal handler from the windows unhandled exception filter
42 // Inspired from KCrash, but heavily simplified
win32UnhandledExceptionFilter(_EXCEPTION_POINTERS *)43 LONG WINAPI win32UnhandledExceptionFilter(_EXCEPTION_POINTERS *)
44 {
45     crashHandler(0);
46     return EXCEPTION_EXECUTE_HANDLER; // allow windows to do the default action (terminate)
47 }
48 #endif
49 
setCrashHandler()50 void setCrashHandler()
51 {
52 #if defined(Q_OS_WIN)
53     SetUnhandledExceptionFilter(win32UnhandledExceptionFilter);
54 #elif !defined(Q_OS_ANDROID)
55     sigset_t mask;
56     sigemptyset(&mask);
57 
58 #ifdef SIGSEGV
59     signal(SIGSEGV, crashHandler);
60     sigaddset(&mask, SIGSEGV);
61 #endif
62 #ifdef SIGBUS
63     signal(SIGBUS, crashHandler);
64     sigaddset(&mask, SIGBUS);
65 #endif
66 #ifdef SIGFPE
67     signal(SIGFPE, crashHandler);
68     sigaddset(&mask, SIGFPE);
69 #endif
70 #ifdef SIGILL
71     signal(SIGILL, crashHandler);
72     sigaddset(&mask, SIGILL);
73 #endif
74 #ifdef SIGABRT
75     signal(SIGABRT, crashHandler);
76     sigaddset(&mask, SIGABRT);
77 #endif
78 
79     sigprocmask(SIG_UNBLOCK, &mask, nullptr);
80 #endif
81 }
82 
main(int argc,char ** argv)83 int main(int argc, char **argv)
84 {
85     QCoreApplication app(argc, argv);
86 
87     KLocalizedString::setApplicationDomain("kservice5");
88 
89     KAboutData about(QStringLiteral(KBUILDSYCOCA_EXENAME),
90                      i18nc("application name", "KBuildSycoca"),
91                      QStringLiteral(KSERVICE_VERSION_STRING),
92                      i18nc("application description", "Rebuilds the system configuration cache."),
93                      KAboutLicense::GPL,
94                      i18nc("@info:credit", "Copyright 1999-2014 KDE Developers"));
95     about.addAuthor(i18nc("@info:credit", "David Faure"), i18nc("@info:credit", "Author"), QStringLiteral("faure@kde.org"));
96     about.addAuthor(i18nc("@info:credit", "Waldo Bastian"), i18nc("@info:credit", "Author"), QStringLiteral("bastian@kde.org"));
97     KAboutData::setApplicationData(about);
98 
99     QCommandLineParser parser;
100     about.setupCommandLine(&parser);
101     parser.addOption(
102         QCommandLineOption(QStringLiteral("nosignal"),
103                            i18nc("@info:shell command-line option", "Do not signal applications to update (deprecated, no longer having any effect)")));
104     parser.addOption(
105         QCommandLineOption(QStringLiteral("noincremental"), i18nc("@info:shell command-line option", "Disable incremental update, re-read everything")));
106     parser.addOption(QCommandLineOption(QStringLiteral("checkstamps"),
107                                         i18nc("@info:shell command-line option", "Check file timestamps (deprecated, no longer having any effect)")));
108     parser.addOption(QCommandLineOption(QStringLiteral("nocheckfiles"),
109                                         i18nc("@info:shell command-line option", "Disable checking files (deprecated, no longer having any effect)")));
110     parser.addOption(QCommandLineOption(QStringLiteral("menutest"), i18nc("@info:shell command-line option", "Perform menu generation test run only")));
111     parser.addOption(
112         QCommandLineOption(QStringLiteral("track"), i18nc("@info:shell command-line option", "Track menu id for debug purposes"), QStringLiteral("menu-id")));
113     parser.addOption(
114         QCommandLineOption(QStringLiteral("testmode"), i18nc("@info:shell command-line option", "Switch QStandardPaths to test mode, for unit tests only")));
115     parser.process(app);
116     about.processCommandLine(&parser);
117 
118     const bool bMenuTest = parser.isSet(QStringLiteral("menutest"));
119 
120     if (parser.isSet(QStringLiteral("testmode"))) {
121         QStandardPaths::setTestModeEnabled(true);
122     }
123 
124     setCrashHandler();
125 
126     fprintf(stderr, "%s running...\n", KBUILDSYCOCA_EXENAME);
127 
128     const bool incremental = !parser.isSet(QStringLiteral("noincremental"));
129 
130     KBuildSycoca sycoca; // Build data base
131     if (parser.isSet(QStringLiteral("track"))) {
132         sycoca.setTrackId(parser.value(QStringLiteral("track")));
133     }
134     sycoca.setMenuTest(bMenuTest);
135     if (!sycoca.recreate(incremental)) {
136         return -1;
137     }
138 
139     return 0;
140 }
141