mirror of
https://github.com/mumble-voip/mumble.git
synced 2025-10-26 11:19:16 +00:00
parent
f5778ec615
commit
10cd98ecf7
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -37,3 +37,6 @@
|
||||
[submodule "3rdparty/spdlog"]
|
||||
path = 3rdparty/spdlog
|
||||
url = https://github.com/gabime/spdlog.git
|
||||
[submodule "3rdparty/CLI11"]
|
||||
path = 3rdparty/CLI11
|
||||
url = https://github.com/CLIUtils/CLI11.git
|
||||
|
||||
1
3rdparty/CLI11
vendored
Submodule
1
3rdparty/CLI11
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 4160d259d961cd393fd8d67590a8c7d210207348
|
||||
@ -34,6 +34,11 @@ Build an x86 overlay
|
||||
Bundle Qt's translations as well
|
||||
(Default: ${static})
|
||||
|
||||
### bundled-cli11
|
||||
|
||||
Use the bundled CLI11 version instead of looking for one on the system
|
||||
(Default: ON)
|
||||
|
||||
### bundled-gsl
|
||||
|
||||
Use the bundled GSL version instead of looking for one on the system
|
||||
|
||||
@ -55,6 +55,7 @@ licenses = [
|
||||
["licensePCRE", "3rdPartyLicenses/pcre_license.txt", "PCRE", "http://www.pcre.org/", "USE_BUILDENV"],
|
||||
["licenseQt", "3rdPartyLicenses/qt_license.txt", "Qt", "https://www.qt.io/", "USE_BUILDENV"],
|
||||
["licenseSQLite3", "3rdPartyLicenses/sqlite3_license.txt", "SQLite3", "http://sqlite.org", "USE_BUILDENV"],
|
||||
["licenseCLI11", "3rdparty/CLI11/LICENSE", "CLI11", "https://github.com/CLIUtils/CLI11", "USE_BUILDENV"],
|
||||
["licenseXar", "3rdPartyLicenses/xar_license.txt", "XAR", "https://opensource.apple.com/source/xar/", "USE_BUILDENV"], # macOS only
|
||||
["licenseAvahi", "3rdPartyLicenses/avahi_license.txt", "Avahi", "https://www.avahi.org/", "USE_BUILDENV"], # Linux only
|
||||
["licenseAppImageRuntime", "3rdPartyLicenses/appimage_runtime_license.txt", "AppImage Runtime", "http://www.appimage.org", "USE_BUILDENV"], # Linux only
|
||||
|
||||
@ -17,6 +17,7 @@ option(tracy "Enable the tracy profiler." OFF)
|
||||
option(bundled-gsl "Use the bundled GSL version instead of looking for one on the system" ON)
|
||||
option(bundled-json "Build the included version of nlohmann_json instead of looking for one on the system" ON)
|
||||
option(bundled-spdlog "Use the bundled spdlog version instead of looking for one on the system" ON)
|
||||
option(bundled-cli11 "Use the bundled CLI11 version instead of looking for one on the system" ON)
|
||||
|
||||
find_pkg(Qt6
|
||||
VERSION 6.2
|
||||
@ -251,6 +252,12 @@ else()
|
||||
endif()
|
||||
target_link_libraries(shared PUBLIC spdlog::spdlog)
|
||||
|
||||
if (bundled-cli11)
|
||||
add_subdirectory("${3RDPARTY_DIR}/CLI11" "${CMAKE_CURRENT_BINARY_DIR}/CLI11" EXCLUDE_FROM_ALL)
|
||||
else()
|
||||
find_pkg("CLI11" 2 REQUIRED)
|
||||
endif()
|
||||
|
||||
if(client)
|
||||
add_subdirectory(mumble)
|
||||
|
||||
|
||||
@ -392,6 +392,7 @@ target_sources(mumble PRIVATE "ApplicationPalette.h")
|
||||
target_include_directories(mumble PRIVATE "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
|
||||
target_link_libraries(mumble PRIVATE mumble_client_object_lib shared spdlog::spdlog)
|
||||
target_link_libraries(mumble PRIVATE CLI11::CLI11)
|
||||
|
||||
target_compile_definitions(mumble_client_object_lib
|
||||
PUBLIC
|
||||
|
||||
@ -53,6 +53,8 @@
|
||||
|
||||
#include "widgets/TrayIcon.h"
|
||||
|
||||
#include <CLI/CLI.hpp>
|
||||
|
||||
#include <QLocale>
|
||||
#include <QScreen>
|
||||
#include <QtCore/QProcess>
|
||||
@ -62,7 +64,9 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
#include <spdlog/sinks/dist_sink.h>
|
||||
#include <spdlog/sinks/qt_sinks.h>
|
||||
@ -207,6 +211,165 @@ extern int os_early_init();
|
||||
extern HWND mumble_mw_hwnd;
|
||||
#endif // Q_OS_WIN
|
||||
|
||||
|
||||
struct CLIOptions {
|
||||
bool allowMultiple = false;
|
||||
bool suppressIdentity = false;
|
||||
bool rpcMode = false;
|
||||
bool startHiddenInTray = false;
|
||||
bool printTranslationDirs = false;
|
||||
bool quit = false;
|
||||
bool showLicense = false;
|
||||
bool showAuthors = false;
|
||||
bool showThirdPartyLicenses = false;
|
||||
bool dumpInputStreams = false;
|
||||
bool printEchoCancelQueue = false;
|
||||
bool skipSettingsBackupPrompt = false;
|
||||
|
||||
std::optional< std::string > configFile;
|
||||
std::optional< std::string > jackClientName;
|
||||
std::optional< std::string > windowTitleExt;
|
||||
std::optional< std::string > hyperlink;
|
||||
std::optional< std::string > translationDir;
|
||||
std::optional< std::string > locale;
|
||||
std::optional< std::string > defaultCertDir;
|
||||
|
||||
std::optional< std::string > rpcCommand;
|
||||
|
||||
static constexpr const char *CLI_GENERAL_SECTION = "General";
|
||||
static constexpr const char *CLI_LANGUAGE_SECTION = "Language";
|
||||
static constexpr const char *CLI_ABOUT_SECTION = "About";
|
||||
static constexpr const char *CLI_DEBUG_SECTION = "Debug";
|
||||
static constexpr const char *CLI_REMOTE_SECTION = "Remote Control";
|
||||
|
||||
static const std::set< std::string > knownRpcCommands;
|
||||
};
|
||||
|
||||
const std::set< std::string > CLIOptions::knownRpcCommands = {
|
||||
"mute", "unmute", "togglemute", "deaf", "undeaf", "toggledeaf", "starttalking", "stoptalking",
|
||||
};
|
||||
|
||||
CLIOptions parseCLI(int argc, char **argv) {
|
||||
CLIOptions options;
|
||||
|
||||
CLI::App app("Mumble Client");
|
||||
app.set_version_flag("--version", "Mumble version " + Version::getRelease().toStdString());
|
||||
app.add_flag("--license", options.showLicense, "Show the Mumble license.")->group(CLIOptions::CLI_ABOUT_SECTION);
|
||||
app.add_flag("--authors", options.showAuthors, "Show the Mumble authors.")->group(CLIOptions::CLI_ABOUT_SECTION);
|
||||
app.add_flag("--third-party-licenses", options.showThirdPartyLicenses,
|
||||
"Show licenses for third-party software used by Mumble.")
|
||||
->group(CLIOptions::CLI_ABOUT_SECTION);
|
||||
|
||||
app.add_option("-c,--config", options.configFile,
|
||||
"Specify an alternative configuration file. "
|
||||
"If you use this to run multiple instances of Mumble at once, "
|
||||
"make sure to use an alternative 'database' value in the config.")
|
||||
->option_text("<config>")
|
||||
->check(CLI::ExistingFile)
|
||||
->group(CLIOptions::CLI_GENERAL_SECTION);
|
||||
|
||||
app.add_option("--default-certificate-dir", options.defaultCertDir,
|
||||
"Specify an alternative default certificate path. "
|
||||
"This path is only used if there is no certificate loaded "
|
||||
"from the settings.")
|
||||
->option_text("<dir>")
|
||||
->check(CLI::ExistingDirectory)
|
||||
->group(CLIOptions::CLI_GENERAL_SECTION);
|
||||
|
||||
app.add_flag("-m,--multiple", options.allowMultiple, "Allow multiple instances of the client to be started.")
|
||||
->group(CLIOptions::CLI_GENERAL_SECTION);
|
||||
|
||||
app.add_flag("--no-identity", options.suppressIdentity, "Suppress loading of identity files (i.e., certificates).")
|
||||
->group(CLIOptions::CLI_GENERAL_SECTION);
|
||||
|
||||
app.add_option("--jack-name", options.jackClientName, "Set custom Jack client name.")
|
||||
->option_text("<name>")
|
||||
->group(CLIOptions::CLI_GENERAL_SECTION);
|
||||
|
||||
app.add_option("--window-title-ext", options.windowTitleExt, "Set a custom window title extension.")
|
||||
->option_text("<extension>")
|
||||
->group(CLIOptions::CLI_GENERAL_SECTION);
|
||||
|
||||
app.add_flag("--skip-settings-backup-prompt", options.skipSettingsBackupPrompt,
|
||||
"Don't show the settings recovery dialog on startup after a crash.")
|
||||
->group(CLIOptions::CLI_GENERAL_SECTION);
|
||||
|
||||
|
||||
|
||||
app.add_flag("--hidden", options.startHiddenInTray, "Start Mumble hidden in the system tray.")
|
||||
->group(CLIOptions::CLI_GENERAL_SECTION);
|
||||
|
||||
app.add_option("--locale", options.locale,
|
||||
"Overwrite the locale in Mumble's settings with a "
|
||||
"locale that corresponds to the given locale string. "
|
||||
"If the format is invalid, Mumble will error. "
|
||||
"Otherwise the locale will be permanently saved to "
|
||||
"Mumble's settings.")
|
||||
->option_text("<locale>")
|
||||
->group(CLIOptions::CLI_LANGUAGE_SECTION);
|
||||
app.add_option("--translation-dir", options.translationDir,
|
||||
"Specifies an additional translation directory <dir> "
|
||||
"in which Mumble will search for translation files that "
|
||||
"overwrite the bundled ones. "
|
||||
"Directories added this way have higher priority than "
|
||||
"the default locations used otherwise.")
|
||||
->option_text("<dir>")
|
||||
->check(CLI::ExistingDirectory)
|
||||
->group(CLIOptions::CLI_LANGUAGE_SECTION);
|
||||
app.add_flag("--print-translation-dirs", options.printTranslationDirs,
|
||||
"Print out the paths in which Mumble will search for "
|
||||
"translation files that overwrite the bundled ones. "
|
||||
"(Useful for translators testing their translations)")
|
||||
->group(CLIOptions::CLI_LANGUAGE_SECTION);
|
||||
|
||||
app.add_flag("--dump-input-streams", options.dumpInputStreams,
|
||||
"Dump PCM streams at various parts of the input chain "
|
||||
" - raw microphone input "
|
||||
" - speaker readback for echo cancelling "
|
||||
" - processed microphone input")
|
||||
->group(CLIOptions::CLI_DEBUG_SECTION);
|
||||
app.add_flag("--print-echocancel-queue", options.printEchoCancelQueue,
|
||||
"Print on stdout the echo cancellation queue state")
|
||||
->group(CLIOptions::CLI_DEBUG_SECTION);
|
||||
|
||||
app.add_option(
|
||||
"hyperlink", options.hyperlink,
|
||||
"<url> specifies a URL to connect to after startup instead of showing "
|
||||
"the connection window, and has the following form:\n"
|
||||
"mumble://[<username>[:<password>]@]<host>[:<port>][/<channel>[/"
|
||||
"<subchannel>...]][?version=<x.y.z>]\n"
|
||||
"\n"
|
||||
"<plugin_list> is a list of plugin files that shall be installed"
|
||||
"\n"
|
||||
"The version query parameter has to be set in order to invoke the\n"
|
||||
"correct client version. It currently defaults to 1.2.0.\n"
|
||||
"\n"
|
||||
"This allows setup of program associations with mumble to directly connect to servers or run with plugins.")
|
||||
->option_text("<url> | <plugin_list>")
|
||||
->group(CLIOptions::CLI_GENERAL_SECTION);
|
||||
|
||||
CLI::App *rpc = app.add_subcommand("rpc", "Remote control a running instance of Mumble");
|
||||
rpc->add_option("action", options.rpcCommand, "Action to perform")
|
||||
->required()
|
||||
->check(CLI::IsMember(CLIOptions::knownRpcCommands, CLI::ignore_case));
|
||||
|
||||
try {
|
||||
app.parse(argc, argv);
|
||||
} catch (const CLI::ParseError &e) {
|
||||
std::stringstream info_stream, error_stream;
|
||||
app.exit(e, info_stream, error_stream);
|
||||
|
||||
if (e.get_exit_code() != static_cast< int >(CLI::ExitCodes::Success)) {
|
||||
qWarning("%s", error_stream.str().c_str());
|
||||
} else {
|
||||
qInfo("%s", info_stream.str().c_str());
|
||||
}
|
||||
options.quit = true;
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int res = 0;
|
||||
|
||||
@ -239,25 +402,24 @@ int main(int argc, char **argv) {
|
||||
#endif
|
||||
|
||||
MumbleSSL::initialize();
|
||||
CLIOptions options = parseCLI(argc, argv);
|
||||
|
||||
if (options.quit) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This argument has to be parsed first, since it's value is needed to create the global struct,
|
||||
// which other switches are modifying. If it is parsed first, the order of the arguments does not matter.
|
||||
QString settingsFile;
|
||||
QStringList args = a.arguments();
|
||||
const auto index = std::max(args.lastIndexOf(QLatin1String("-c")), args.lastIndexOf(QLatin1String("--config")));
|
||||
if (index >= 0) {
|
||||
if (index + 1 < args.count()) {
|
||||
QFile inifile(args.at(index + 1));
|
||||
if (inifile.exists() && inifile.permissions().testFlag(QFile::WriteUser)) {
|
||||
Global::g_global_struct = new Global(args.at(index + 1));
|
||||
settingsFile = args.at(index + 1);
|
||||
} else {
|
||||
printf("%s", qPrintable(MainWindow::tr("Configuration file %1 does not exist or is not writable.\n")
|
||||
.arg(args.at(index + 1))));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (options.configFile) {
|
||||
QFile inifile(QString::fromStdString(*options.configFile));
|
||||
if (inifile.exists() && inifile.permissions().testFlag(QFile::WriteUser)) {
|
||||
Global::g_global_struct = new Global(inifile.fileName());
|
||||
settingsFile = inifile.fileName();
|
||||
} else {
|
||||
qCritical("Missing argument for --config!");
|
||||
printf("%s", qPrintable(MainWindow::tr("Configuration file %1 does not exist or is not writable.\n")
|
||||
.arg(inifile.fileName())));
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
@ -270,256 +432,88 @@ int main(int argc, char **argv) {
|
||||
|
||||
os_init();
|
||||
|
||||
bool bAllowMultiple = false;
|
||||
bool suppressIdentity = false;
|
||||
bool customJackClientName = false;
|
||||
bool bRpcMode = false;
|
||||
bool printTranslationDirs = false;
|
||||
bool startHiddenInTray = false;
|
||||
bool skipSettingsBackupPrompt = false;
|
||||
QString rpcCommand;
|
||||
QUrl url;
|
||||
QDir qdCert(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation));
|
||||
QStringList extraTranslationDirs;
|
||||
QString localeOverwrite;
|
||||
|
||||
QStringList pluginsToBeInstalled;
|
||||
if (a.arguments().count() > 1) {
|
||||
for (int i = 1; i < args.count(); ++i) {
|
||||
if (args.at(i) == QLatin1String("-h") || args.at(i) == QLatin1String("--help")
|
||||
#if defined(Q_OS_WIN)
|
||||
|| args.at(i) == QLatin1String("/?")
|
||||
#endif
|
||||
) {
|
||||
QString helpMessage =
|
||||
MainWindow::tr("Usage: mumble [options] [<url> | <plugin_list>]\n"
|
||||
"\n"
|
||||
"<url> specifies a URL to connect to after startup instead of showing\n"
|
||||
"the connection window, and has the following form:\n"
|
||||
"mumble://[<username>[:<password>]@]<host>[:<port>][/<channel>[/"
|
||||
"<subchannel>...]][?version=<x.y.z>]\n"
|
||||
"\n"
|
||||
"<plugin_list> is a list of plugin files that shall be installed"
|
||||
"\n"
|
||||
"The version query parameter has to be set in order to invoke the\n"
|
||||
"correct client version. It currently defaults to 1.2.0.\n"
|
||||
"\n"
|
||||
"Valid options are:\n"
|
||||
" -h, --help Show this help text and exit.\n"
|
||||
" --version Print version information and exit\n"
|
||||
" -m, --multiple\n"
|
||||
" Allow multiple instances of the client to be started.\n"
|
||||
" -c, --config\n"
|
||||
" Specify an alternative configuration file.\n"
|
||||
" If you use this to run multiple instances of Mumble at once,\n"
|
||||
" make sure to set an alternative 'database' value in the config.\n"
|
||||
" --default-certificate-dir <dir>\n"
|
||||
" Specify an alternative default certificate path.\n"
|
||||
" This path is only used if there is no certificate loaded\n"
|
||||
" from the settings.\n"
|
||||
" -n, --noidentity\n"
|
||||
" Suppress loading of identity files (i.e., certificates.)\n"
|
||||
" -jn, --jackname <arg>\n"
|
||||
" Set custom Jack client name.\n"
|
||||
" --license\n"
|
||||
" Show the Mumble license.\n"
|
||||
" --authors\n"
|
||||
" Show the Mumble authors.\n"
|
||||
" --third-party-licenses\n"
|
||||
" Show licenses for third-party software used by Mumble.\n"
|
||||
" --window-title-ext <arg>\n"
|
||||
" Sets a custom window title extension.\n"
|
||||
" --dump-input-streams\n"
|
||||
" Dump PCM streams at various parts of the input chain\n"
|
||||
" (useful for debugging purposes)\n"
|
||||
" - raw microphone input\n"
|
||||
" - speaker readback for echo cancelling\n"
|
||||
" - processed microphone input\n"
|
||||
" --print-echocancel-queue\n"
|
||||
" Print on stdout the echo cancellation queue state\n"
|
||||
" (useful for debugging purposes)\n"
|
||||
" --translation-dir <dir>\n"
|
||||
" Specifies an additional translation directory <dir>\n"
|
||||
" in which Mumble will search for translation files that\n"
|
||||
" overwrite the bundled ones\n"
|
||||
" Directories added this way have higher priority than\n"
|
||||
" the default locations used otherwise\n"
|
||||
" --print-translation-dirs\n"
|
||||
" Print out the paths in which Mumble will search for\n"
|
||||
" translation files that overwrite the bundled ones.\n"
|
||||
" (Useful for translators testing their translations)\n"
|
||||
" --locale <locale>\n"
|
||||
" Overwrite the locale in Mumble's settings with a\n"
|
||||
" locale that corresponds to the given locale string.\n"
|
||||
" If the format is invalid, Mumble will error.\n"
|
||||
" Otherwise the locale will be permanently saved to\n"
|
||||
" Mumble's settings.\n"
|
||||
" --hidden\n"
|
||||
" Start Mumble hidden in the system tray.\n"
|
||||
" --skip-settings-backup-prompt\n"
|
||||
" Don't show the settings recovery dialog on startup after a crash."
|
||||
"\n");
|
||||
QString rpcHelpBanner = MainWindow::tr("Remote controlling Mumble:\n"
|
||||
"\n");
|
||||
QString rpcHelpMessage =
|
||||
MainWindow::tr("Usage: mumble rpc <action> [options]\n"
|
||||
"\n"
|
||||
"It is possible to remote control a running instance of Mumble by using\n"
|
||||
"the 'mumble rpc' command.\n"
|
||||
"\n"
|
||||
"Valid actions are:\n"
|
||||
" mute\n"
|
||||
" Mute self\n"
|
||||
" unmute\n"
|
||||
" Unmute self\n"
|
||||
" togglemute\n"
|
||||
" Toggle self-mute status\n"
|
||||
" deaf\n"
|
||||
" Deafen self\n"
|
||||
" undeaf\n"
|
||||
" Undeafen self\n"
|
||||
" toggledeaf\n"
|
||||
" Toggle self-deafen status\n"
|
||||
" starttalking\n"
|
||||
" Start talking\n"
|
||||
" stoptalking\n"
|
||||
" Stop talking\n"
|
||||
"\n");
|
||||
|
||||
QString helpOutput = helpMessage + rpcHelpBanner + rpcHelpMessage;
|
||||
if (bRpcMode) {
|
||||
helpOutput = rpcHelpMessage;
|
||||
}
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
QMessageBox::information(nullptr, MainWindow::tr("Invocation"), helpOutput);
|
||||
#else
|
||||
printf("%s", qPrintable(helpOutput));
|
||||
#endif
|
||||
return 1;
|
||||
} else if (args.at(i) == QLatin1String("-m") || args.at(i) == QLatin1String("--multiple")) {
|
||||
bAllowMultiple = true;
|
||||
} else if (args.at(i) == QLatin1String("-n") || args.at(i) == QLatin1String("--noidentity")) {
|
||||
suppressIdentity = true;
|
||||
Global::get().s.bSuppressIdentity = true;
|
||||
} else if (args.at(i) == QLatin1String("-jn") || args.at(i) == QLatin1String("--jackname")) {
|
||||
if (i + 1 < args.count()) {
|
||||
Global::get().s.qsJackClientName = QString(args.at(i + 1));
|
||||
customJackClientName = true;
|
||||
++i;
|
||||
} else {
|
||||
qCritical("Missing argument for --jackname!");
|
||||
return 1;
|
||||
}
|
||||
} else if (args.at(i) == QLatin1String("--window-title-ext")) {
|
||||
if (i + 1 < args.count()) {
|
||||
Global::get().windowTitlePostfix = QString(args.at(i + 1));
|
||||
++i;
|
||||
} else {
|
||||
qCritical("Missing argument for --window-title-ext!");
|
||||
return 1;
|
||||
}
|
||||
} else if (args.at(i) == QLatin1String("-license") || args.at(i) == QLatin1String("--license")) {
|
||||
printf("%s\n", qPrintable(License::license()));
|
||||
return 0;
|
||||
} else if (args.at(i) == QLatin1String("-authors") || args.at(i) == QLatin1String("--authors")) {
|
||||
printf("%s\n",
|
||||
"For a list of authors, please see https://github.com/mumble-voip/mumble/graphs/contributors");
|
||||
return 0;
|
||||
} else if (args.at(i) == QLatin1String("-third-party-licenses")
|
||||
|| args.at(i) == QLatin1String("--third-party-licenses")) {
|
||||
printf("%s", qPrintable(License::printableThirdPartyLicenseInfo()));
|
||||
return 0;
|
||||
} else if (args.at(i) == QLatin1String("rpc")) {
|
||||
bRpcMode = true;
|
||||
if (args.count() - 1 > i) {
|
||||
rpcCommand = QString(args.at(i + 1));
|
||||
} else {
|
||||
QString rpcError = MainWindow::tr("Error: No RPC command specified");
|
||||
#if defined(Q_OS_WIN)
|
||||
QMessageBox::information(nullptr, MainWindow::tr("RPC"), rpcError);
|
||||
#else
|
||||
printf("%s\n", qPrintable(rpcError));
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
} else if (args.at(i) == QLatin1String("--dump-input-streams")) {
|
||||
Global::get().bDebugDumpInput = true;
|
||||
} else if (args.at(i) == QLatin1String("--print-echocancel-queue")) {
|
||||
Global::get().bDebugPrintQueue = true;
|
||||
} else if (args.at(i) == QLatin1String("-c") || args.at(i) == QLatin1String("--config")) {
|
||||
// We already parsed these arguments above, so just skip over them here
|
||||
++i;
|
||||
} else if (args.at(i) == QLatin1String("--default-certificate-dir")) {
|
||||
if (i + 1 < args.count()) {
|
||||
qdCert = QDir(args.at(i + 1));
|
||||
// I suppose we should really be checking whether the directory is writable here too,
|
||||
// but there are some subtleties with doing that:
|
||||
// (doc.qt.io/qt-5/qfile.html#platform-specific-issues)
|
||||
// so we can just let things fail down below when this directory is used.
|
||||
if (!qdCert.exists()) {
|
||||
printf("%s", qPrintable(MainWindow::tr("Directory %1 does not exist.\n").arg(args.at(i + 1))));
|
||||
return 1;
|
||||
}
|
||||
++i;
|
||||
} else {
|
||||
qCritical("Missing argument for --default-certificate-dir!");
|
||||
return 1;
|
||||
}
|
||||
} else if (args.at(i) == "--print-translation-dirs") {
|
||||
printTranslationDirs = true;
|
||||
} else if (args.at(i) == "--translation-dir") {
|
||||
if (i + 1 < args.count()) {
|
||||
extraTranslationDirs.append(args.at(i + 1));
|
||||
i++;
|
||||
} else {
|
||||
qCritical("Missing argument for --translation-dir!");
|
||||
return 1;
|
||||
}
|
||||
} else if (args.at(i) == "--locale") {
|
||||
if (i + 1 < args.count()) {
|
||||
localeOverwrite = args.at(i + 1);
|
||||
i++;
|
||||
} else {
|
||||
qCritical("Missing argument for --locale!");
|
||||
return 1;
|
||||
}
|
||||
} else if (args.at(i) == "--hidden") {
|
||||
if (options.suppressIdentity) {
|
||||
Global::get().s.bSuppressIdentity = true;
|
||||
}
|
||||
if (options.jackClientName) {
|
||||
Global::get().s.qsJackClientName = QString::fromStdString(*options.jackClientName);
|
||||
}
|
||||
if (options.windowTitleExt) {
|
||||
Global::get().windowTitlePostfix = QString::fromStdString(*options.windowTitleExt);
|
||||
}
|
||||
if (options.showLicense) {
|
||||
printf("%s\n", qPrintable(License::license()));
|
||||
return 0;
|
||||
}
|
||||
if (options.showAuthors) {
|
||||
printf("%s\n", "For a list of authors, please see https://github.com/mumble-voip/mumble/graphs/contributors");
|
||||
return 0;
|
||||
}
|
||||
if (options.showThirdPartyLicenses) {
|
||||
printf("%s", qPrintable(License::printableThirdPartyLicenseInfo()));
|
||||
return 0;
|
||||
}
|
||||
if (options.rpcCommand) {
|
||||
options.rpcMode = true;
|
||||
}
|
||||
if (options.dumpInputStreams) {
|
||||
Global::get().bDebugDumpInput = true;
|
||||
}
|
||||
if (options.printEchoCancelQueue) {
|
||||
Global::get().bDebugPrintQueue = true;
|
||||
}
|
||||
if (options.defaultCertDir) {
|
||||
qdCert = QDir(QString::fromStdString(*options.defaultCertDir));
|
||||
// I suppose we should really be checking whether the directory is writable here too,
|
||||
// but there are some subtleties with doing that:
|
||||
// (doc.qt.io/qt-5/qfile.html#platform-specific-issues)
|
||||
// so we can just let things fail down below when this directory is used.
|
||||
if (!qdCert.exists()) { // probably not reached since cli11 checks for existence
|
||||
printf("%s", qPrintable(MainWindow::tr("Directory %1 does not exist.\n").arg(qdCert.absolutePath())));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (options.translationDir) {
|
||||
extraTranslationDirs.append(QString::fromStdString(*options.translationDir));
|
||||
}
|
||||
if (options.locale) {
|
||||
localeOverwrite = QString::fromStdString(*options.locale);
|
||||
}
|
||||
if (options.startHiddenInTray) {
|
||||
#ifndef Q_OS_MAC
|
||||
startHiddenInTray = true;
|
||||
qInfo("Starting hidden in system tray");
|
||||
qInfo("Starting hidden in system tray");
|
||||
#else
|
||||
// When Qt addresses hide() on macOS to use native hiding, this can be fixed.
|
||||
qWarning("Can not start Mumble hidden in system tray on macOS");
|
||||
// When Qt addresses hide() on macOS to use native hiding, this can be fixed.
|
||||
qWarning("Can not start Mumble hidden in system tray on macOS");
|
||||
#endif
|
||||
} else if (args.at(i) == QLatin1String("--skip-settings-backup-prompt")) {
|
||||
skipSettingsBackupPrompt = true;
|
||||
} else if (args.at(i) == "--version") {
|
||||
// Print version and exit (print to regular std::cout to avoid adding any useless meta-information from
|
||||
// using e.g. qWarning
|
||||
std::cout << "Mumble version " << Version::getRelease().toStdString() << std::endl;
|
||||
return 0;
|
||||
} else {
|
||||
if (PluginInstaller::canBePluginFile(QFileInfo(args.at(i)))) {
|
||||
pluginsToBeInstalled << args.at(i);
|
||||
}
|
||||
if (options.hyperlink) {
|
||||
if (PluginInstaller::canBePluginFile(QFileInfo(QString::fromStdString(*options.hyperlink)))) {
|
||||
pluginsToBeInstalled << QString::fromStdString(*options.hyperlink);
|
||||
} else {
|
||||
if (!options.rpcMode) {
|
||||
QString qHyperlink = QString::fromStdString(*options.hyperlink);
|
||||
QUrl u = QUrl::fromEncoded(qHyperlink.toUtf8());
|
||||
if (u.isValid() && (u.scheme() == QLatin1String("mumble"))) {
|
||||
url = u;
|
||||
} else {
|
||||
if (!bRpcMode) {
|
||||
QUrl u = QUrl::fromEncoded(args.at(i).toUtf8());
|
||||
if (u.isValid() && (u.scheme() == QLatin1String("mumble"))) {
|
||||
url = u;
|
||||
} else {
|
||||
QFile f(args.at(i));
|
||||
if (f.exists()) {
|
||||
url = QUrl::fromLocalFile(f.fileName());
|
||||
}
|
||||
}
|
||||
QFile f(qHyperlink);
|
||||
if (f.exists()) {
|
||||
url = QUrl::fromLocalFile(f.fileName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (printTranslationDirs) {
|
||||
if (options.printTranslationDirs) {
|
||||
QString infoString = QObject::tr("The directories in which Mumble searches for extra translation files are:\n");
|
||||
|
||||
int counter = 1;
|
||||
@ -571,9 +565,10 @@ int main(int argc, char **argv) {
|
||||
# endif
|
||||
#endif
|
||||
|
||||
if (bRpcMode) {
|
||||
if (options.rpcMode) {
|
||||
bool sent = false;
|
||||
QMap< QString, QVariant > param;
|
||||
QString rpcCommand = QString::fromStdString(*options.rpcCommand);
|
||||
param.insert(rpcCommand, rpcCommand);
|
||||
sent = SocketRPC::send(QLatin1String("Mumble"), QLatin1String("self"), param);
|
||||
if (sent) {
|
||||
@ -583,7 +578,7 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!bAllowMultiple) {
|
||||
if (!options.allowMultiple) {
|
||||
if (url.isValid()) {
|
||||
#ifndef USE_DBUS
|
||||
QMap< QString, QVariant > param;
|
||||
@ -628,7 +623,7 @@ int main(int argc, char **argv) {
|
||||
// If another Mumble instance attempts to open the file, it will fail,
|
||||
// and that instance will know to terminate itself.
|
||||
UserLockFile userLockFile(Global::get().qdBasePath.filePath(QLatin1String("mumble.lock")));
|
||||
if (!bAllowMultiple) {
|
||||
if (!options.allowMultiple) {
|
||||
if (!userLockFile.acquire()) {
|
||||
qWarning("Another process has already acquired the lock file at '%s'. Terminating...",
|
||||
qPrintable(userLockFile.path()));
|
||||
@ -639,9 +634,9 @@ int main(int argc, char **argv) {
|
||||
|
||||
// Load preferences
|
||||
if (settingsFile.isEmpty()) {
|
||||
Global::get().s.load(skipSettingsBackupPrompt);
|
||||
Global::get().s.load();
|
||||
} else {
|
||||
Global::get().s.load(settingsFile, skipSettingsBackupPrompt);
|
||||
Global::get().s.load(settingsFile);
|
||||
}
|
||||
if (!Global::get().migratedDBPath.isEmpty()) {
|
||||
// We have migrated the DB to a new location. Make sure that the settings hold the correct (new) path and that
|
||||
@ -764,7 +759,7 @@ int main(int argc, char **argv) {
|
||||
|
||||
// Main Window
|
||||
Global::get().mw = new MainWindow(nullptr);
|
||||
if (!startHiddenInTray) {
|
||||
if (!options.startHiddenInTray) {
|
||||
Global::get().mw->showRaiseWindow();
|
||||
}
|
||||
|
||||
@ -881,7 +876,7 @@ int main(int argc, char **argv) {
|
||||
OpenURLEvent *oue = new OpenURLEvent(a.quLaunchURL);
|
||||
qApp->postEvent(Global::get().mw, oue);
|
||||
#endif
|
||||
} else if (!startHiddenInTray || Global::get().s.bAutoConnect) {
|
||||
} else if (!options.startHiddenInTray || Global::get().s.bAutoConnect) {
|
||||
Global::get().mw->on_qaServerConnect_triggered(true);
|
||||
}
|
||||
|
||||
@ -997,12 +992,12 @@ int main(int argc, char **argv) {
|
||||
if (res == MUMBLE_EXIT_CODE_RESTART) {
|
||||
QStringList arguments;
|
||||
|
||||
if (bAllowMultiple)
|
||||
if (options.allowMultiple)
|
||||
arguments << QLatin1String("--multiple");
|
||||
if (suppressIdentity)
|
||||
arguments << QLatin1String("--noidentity");
|
||||
if (customJackClientName)
|
||||
arguments << QLatin1String("--jackname ") + Global::get().s.qsJackClientName;
|
||||
if (options.suppressIdentity)
|
||||
arguments << QLatin1String("--no-identity");
|
||||
if (options.jackClientName)
|
||||
arguments << QLatin1String("--jack-name ") + Global::get().s.qsJackClientName;
|
||||
if (!url.isEmpty())
|
||||
arguments << url.toString();
|
||||
|
||||
|
||||
@ -58,7 +58,7 @@ else()
|
||||
add_executable(mumble-server "main.cpp")
|
||||
endif()
|
||||
|
||||
target_link_libraries(mumble-server mumble_server_object_lib)
|
||||
target_link_libraries(mumble-server mumble_server_object_lib CLI11::CLI11)
|
||||
|
||||
set_property(TARGET mumble-server PROPERTY INTERPROCEDURAL_OPTIMIZATION ${lto})
|
||||
set_property(TARGET mumble_server_object_lib PROPERTY INTERPROCEDURAL_OPTIMIZATION ${lto})
|
||||
@ -139,8 +139,8 @@ if(WIN32)
|
||||
|
||||
find_pkg(Qt6 COMPONENTS Widgets REQUIRED)
|
||||
|
||||
target_link_libraries(mumble_server_object_lib
|
||||
PUBLIC
|
||||
target_link_libraries(mumble_server_object_lib
|
||||
PUBLIC
|
||||
Qt6::Widgets
|
||||
dbghelp.lib
|
||||
shlwapi.lib
|
||||
|
||||
@ -38,6 +38,11 @@
|
||||
# include <sys/syslog.h>
|
||||
#endif
|
||||
|
||||
#include <optional>
|
||||
#include <tuple>
|
||||
|
||||
#include <CLI/CLI.hpp>
|
||||
|
||||
extern QFile *qfLog;
|
||||
|
||||
static bool bVerbose = false;
|
||||
@ -187,6 +192,126 @@ void cleanup(int signum) {
|
||||
exit(signum);
|
||||
}
|
||||
|
||||
struct CLIOptions {
|
||||
bool quit = false;
|
||||
std::optional< std::string > iniFile;
|
||||
std::optional< std::string > dbDumpPath;
|
||||
std::optional< std::string > dbImportPath;
|
||||
std::tuple< std::string, std::optional< unsigned int > > supwSrv;
|
||||
std::optional< unsigned int > disableSuSrv;
|
||||
bool verboseLogging = false;
|
||||
bool cliDetach = detach;
|
||||
bool wipeSsl = false;
|
||||
bool wipeLogs = false;
|
||||
bool logGroups = false;
|
||||
bool logAcls = false;
|
||||
|
||||
bool printAuthors = false;
|
||||
bool printLicense = false;
|
||||
bool printThirdPartyLicenses = false;
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
bool limits = false;
|
||||
std::optional< unsigned int > readSupwSrv;
|
||||
#endif
|
||||
|
||||
static constexpr const char *const CLI_ABOUT_SECTION = "About";
|
||||
static constexpr const char *const CLI_LOGGING_SECTION = "Logging";
|
||||
static constexpr const char *const CLI_ADMINISTRATION_SECTION = "Administration";
|
||||
static constexpr const char *const CLI_CONFIGURATION_SECTION = "Configuration";
|
||||
static constexpr const char *const CLI_TESTING_SECTION = "Testing";
|
||||
};
|
||||
|
||||
CLIOptions parseCLI(int argc, char **argv) {
|
||||
CLIOptions options;
|
||||
|
||||
CLI::App app;
|
||||
app.set_version_flag("--version", Version::getRelease().toStdString());
|
||||
|
||||
app.add_option("-i,--ini", options.iniFile, "Specify ini file to use.")
|
||||
->option_text("<inifile>")
|
||||
->check(CLI::ExistingFile)
|
||||
->group(CLIOptions::CLI_CONFIGURATION_SECTION);
|
||||
|
||||
app.add_option("--set-su-pw", options.supwSrv, "Set password for 'SuperUser' account on server srv.")
|
||||
->option_text("<pw> [srv]")
|
||||
->type_size(1, 2)
|
||||
->group(CLIOptions::CLI_ADMINISTRATION_SECTION);
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
app.add_option("--read-su-pw", options.readSupwSrv, "Reads password for server srv from standard input.")
|
||||
->option_text("[srv]")
|
||||
->default_str("0")
|
||||
->expected(0, 1)
|
||||
->group(CLIOptions::CLI_ADMINISTRATION_SECTION);
|
||||
|
||||
app.add_flag("--limits", options.limits,
|
||||
"Tests and shows how many file descriptors and threads can be created. "
|
||||
"The purpose of this option is to test how many clients Mumble server can handle. "
|
||||
"Mumble server will exit after this test.")
|
||||
->group(CLIOptions::CLI_TESTING_SECTION);
|
||||
#endif
|
||||
|
||||
app.add_option_no_stream("--disable-su", options.disableSuSrv,
|
||||
"Disable password for 'SuperUser' account on server srv.")
|
||||
->option_text("[srv]")
|
||||
->expected(0, 1)
|
||||
->group(CLIOptions::CLI_ADMINISTRATION_SECTION);
|
||||
app.add_flag("--wipe-ssl", options.wipeSsl, "Remove SSL certificates from database.")
|
||||
->group(CLIOptions::CLI_ADMINISTRATION_SECTION);
|
||||
app.add_option("--db-json-dump", options.dbDumpPath,
|
||||
"Requests a JSON dump of the database to be written to the given file")
|
||||
->option_text("<file>")
|
||||
->group(CLIOptions::CLI_ADMINISTRATION_SECTION);
|
||||
app.add_option("--db-json-import", options.dbImportPath,
|
||||
"Reads in the provide JSON file and imports its contents into the database")
|
||||
->option_text("<file>")
|
||||
->group(CLIOptions::CLI_ADMINISTRATION_SECTION);
|
||||
|
||||
app.add_flag("-v,--verbose", options.verboseLogging, "Use verbose logging (include debug-logs).")
|
||||
->group(CLIOptions::CLI_LOGGING_SECTION);
|
||||
app.add_flag("--detach,!--no-detach,--background,!--foreground", options.cliDetach,
|
||||
"Whether to run in detached/background mode. In this mode, the program will detach and run as an "
|
||||
"independent process in the background. Furthermore, logs will be written to the database instead of "
|
||||
"to the console.")
|
||||
->group(CLIOptions::CLI_LOGGING_SECTION);
|
||||
|
||||
app.add_flag("--wipe-logs", options.wipeLogs, "Remove all log entries from database.")
|
||||
->group(CLIOptions::CLI_LOGGING_SECTION);
|
||||
app.add_flag("--log-groups", options.logGroups, "Turns on logging for group changes for all servers.")
|
||||
->group(CLIOptions::CLI_LOGGING_SECTION);
|
||||
app.add_flag("--log-acls", options.logAcls, "Turns on logging for ACL changes for all servers.")
|
||||
->group(CLIOptions::CLI_LOGGING_SECTION);
|
||||
|
||||
|
||||
app.add_flag("--authors", options.printAuthors, "Show Mumble server's authors.")
|
||||
->group(CLIOptions::CLI_ABOUT_SECTION);
|
||||
app.add_flag("--license", options.printLicense, "Show Mumble server's license.")
|
||||
->group(CLIOptions::CLI_ABOUT_SECTION);
|
||||
app.add_flag("--third-party-licenses", options.printThirdPartyLicenses,
|
||||
"Show licenses for third-party software used by Mumble server.")
|
||||
->group(CLIOptions::CLI_ABOUT_SECTION);
|
||||
|
||||
|
||||
app.footer("If no inifile is provided, Mumble server will search for one in default locations.");
|
||||
|
||||
try {
|
||||
(app).parse(argc, argv);
|
||||
} catch (const CLI::ParseError &e) {
|
||||
std::stringstream info_stream, error_stream;
|
||||
app.exit(e, info_stream, error_stream);
|
||||
|
||||
if (e.get_exit_code() != static_cast< int >(CLI::ExitCodes::Success)) {
|
||||
qWarning("%s", error_stream.str().c_str());
|
||||
} else {
|
||||
qInfo("%s", info_stream.str().c_str());
|
||||
}
|
||||
options.quit = true;
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
try {
|
||||
// Check for SSE and MMX, but only in the windows binaries
|
||||
@ -236,180 +361,87 @@ int main(int argc, char **argv) {
|
||||
|
||||
MumbleSSL::initialize();
|
||||
|
||||
QString inifile;
|
||||
QString supw;
|
||||
QString dbDumpPath;
|
||||
QString dbImportPath;
|
||||
bool disableSu = false;
|
||||
bool wipeSsl = false;
|
||||
bool wipeLogs = false;
|
||||
unsigned int sunum = 0;
|
||||
#ifdef Q_OS_UNIX
|
||||
bool readPw = false;
|
||||
#endif
|
||||
bool logGroups = false;
|
||||
bool logACL = false;
|
||||
|
||||
|
||||
qInstallMessageHandler(murmurMessageOutputWithContext);
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
Tray tray(nullptr, &le);
|
||||
#endif
|
||||
CLIOptions cli_options = parseCLI(argc, argv);
|
||||
if (cli_options.quit)
|
||||
return 0;
|
||||
|
||||
QStringList args = a.arguments();
|
||||
for (int i = 1; i < args.size(); i++) {
|
||||
bool bLast = false;
|
||||
QString arg = args.at(i).toLower();
|
||||
if ((arg == "-supw")) {
|
||||
detach = false;
|
||||
if (i + 1 < args.size()) {
|
||||
i++;
|
||||
supw = args.at(i);
|
||||
if (i + 1 < args.size()) {
|
||||
i++;
|
||||
sunum = args.at(i).toUInt();
|
||||
}
|
||||
bLast = true;
|
||||
} else {
|
||||
#ifdef Q_OS_UNIX
|
||||
qFatal("-supw expects the password on the command line - maybe you meant -readsupw?");
|
||||
#else
|
||||
qFatal("-supw expects the password on the command line");
|
||||
#endif
|
||||
}
|
||||
#ifdef Q_OS_UNIX
|
||||
} else if ((arg == "-readsupw")) {
|
||||
// Note that it is essential to set detach = false here. If this is ever to be changed, the code part
|
||||
// handling the readPw = true part has to be moved up so that it is executed before fork is called on
|
||||
// Unix systems.
|
||||
detach = false;
|
||||
readPw = true;
|
||||
if (i + 1 < args.size()) {
|
||||
i++;
|
||||
sunum = args.at(i).toUInt();
|
||||
}
|
||||
bLast = true;
|
||||
#endif
|
||||
} else if ((arg == "-disablesu")) {
|
||||
detach = false;
|
||||
disableSu = true;
|
||||
if (i + 1 < args.size()) {
|
||||
i++;
|
||||
sunum = args.at(i).toUInt();
|
||||
}
|
||||
bLast = true;
|
||||
} else if ((arg == "-ini") && (i + 1 < args.size())) {
|
||||
i++;
|
||||
inifile = args.at(i);
|
||||
} else if ((arg == "-wipessl")) {
|
||||
wipeSsl = true;
|
||||
} else if ((arg == "-wipelogs")) {
|
||||
wipeLogs = true;
|
||||
} else if ((arg == "-fg")) {
|
||||
detach = false;
|
||||
} else if ((arg == "-v")) {
|
||||
bVerbose = true;
|
||||
} else if ((arg == "-version") || (arg == "--version")) {
|
||||
// Print version and exit (print to regular std::cout to avoid adding any useless meta-information from
|
||||
// using e.g. qWarning
|
||||
std::cout << "Mumble server version " << Version::getRelease().toStdString() << std::endl;
|
||||
return 0;
|
||||
} else if (args.at(i) == QLatin1String("-license") || args.at(i) == QLatin1String("--license")) {
|
||||
if (cli_options.printLicense) {
|
||||
#ifdef Q_OS_WIN
|
||||
AboutDialog ad(nullptr, AboutDialogOptionsShowLicense);
|
||||
ad.exec();
|
||||
return 0;
|
||||
AboutDialog ad(nullptr, AboutDialogOptionsShowLicense);
|
||||
ad.exec();
|
||||
return 0;
|
||||
#else
|
||||
qInfo("%s\n", qPrintable(License::license()));
|
||||
return 0;
|
||||
qInfo("%s\n", qPrintable(License::license()));
|
||||
return 0;
|
||||
#endif
|
||||
} else if (args.at(i) == QLatin1String("-authors") || args.at(i) == QLatin1String("--authors")) {
|
||||
} else if (cli_options.printAuthors) {
|
||||
#ifdef Q_OS_WIN
|
||||
AboutDialog ad(nullptr, AboutDialogOptionsShowAuthors);
|
||||
ad.exec();
|
||||
return 0;
|
||||
AboutDialog ad(nullptr, AboutDialogOptionsShowAuthors);
|
||||
ad.exec();
|
||||
return 0;
|
||||
#else
|
||||
qInfo("%s\n",
|
||||
"For a list of authors, please see https://github.com/mumble-voip/mumble/graphs/contributors");
|
||||
return 0;
|
||||
qInfo("%s\n",
|
||||
"For a list of authors, please see https://github.com/mumble-voip/mumble/graphs/contributors");
|
||||
return 0;
|
||||
#endif
|
||||
} else if (args.at(i) == QLatin1String("-third-party-licenses")
|
||||
|| args.at(i) == QLatin1String("--third-party-licenses")) {
|
||||
} else if (cli_options.printThirdPartyLicenses) {
|
||||
#ifdef Q_OS_WIN
|
||||
AboutDialog ad(nullptr, AboutDialogOptionsShowThirdPartyLicenses);
|
||||
ad.exec();
|
||||
return 0;
|
||||
AboutDialog ad(nullptr, AboutDialogOptionsShowThirdPartyLicenses);
|
||||
ad.exec();
|
||||
return 0;
|
||||
#else
|
||||
qInfo("%s", qPrintable(License::printableThirdPartyLicenseInfo()));
|
||||
return 0;
|
||||
qInfo("%s", qPrintable(License::printableThirdPartyLicenseInfo()));
|
||||
return 0;
|
||||
#endif
|
||||
} else if (arg == "--db-json-dump") {
|
||||
++i;
|
||||
dbDumpPath = args.at(i);
|
||||
} else if (arg == "--db-json-import") {
|
||||
++i;
|
||||
dbImportPath = args.at(i);
|
||||
} else if ((arg == "-h") || (arg == "-help") || (arg == "--help")) {
|
||||
detach = false;
|
||||
qInfo(
|
||||
"Usage: %s [-ini <inifile>] [-supw <password>]\n"
|
||||
" --version Print version information and exit\n"
|
||||
" -ini <inifile> Specify ini file to use.\n"
|
||||
" -supw <pw> [srv] Set password for 'SuperUser' account on server srv.\n"
|
||||
}
|
||||
|
||||
detach = cli_options.cliDetach;
|
||||
QString inifile = QString::fromStdString(cli_options.iniFile.value_or(""));
|
||||
QString supw;
|
||||
bool disableSu = false;
|
||||
bool wipeSsl = cli_options.wipeSsl;
|
||||
bool wipeLogs = cli_options.wipeLogs;
|
||||
unsigned int sunum = 0;
|
||||
#ifdef Q_OS_UNIX
|
||||
" -readsupw [srv] Reads password for server srv from standard input.\n"
|
||||
bool readPw = false;
|
||||
#endif
|
||||
" -disablesu [srv] Disable password for 'SuperUser' account on server srv.\n"
|
||||
bool logGroups = cli_options.logGroups;
|
||||
bool logACL = cli_options.logAcls;
|
||||
|
||||
bVerbose = cli_options.verboseLogging;
|
||||
|
||||
if (cli_options.disableSuSrv) {
|
||||
detach = false;
|
||||
disableSu = true;
|
||||
sunum = *cli_options.disableSuSrv;
|
||||
}
|
||||
|
||||
if (!std::get< 0 >(cli_options.supwSrv).empty()) {
|
||||
supw = QString::fromStdString(std::get< 0 >(cli_options.supwSrv));
|
||||
sunum = std::get< 1 >(cli_options.supwSrv).value_or< unsigned int >(0);
|
||||
#ifdef Q_OS_UNIX
|
||||
" -limits Tests and shows how many file descriptors and threads can be created.\n"
|
||||
" The purpose of this option is to test how many clients Murmur can "
|
||||
"handle.\n"
|
||||
" Murmur will exit after this test.\n"
|
||||
} else if (cli_options.readSupwSrv) {
|
||||
// Note that it is essential to set detach = false here. If this is ever to be changed, the code part
|
||||
// handling the readPw = true part has to be moved up so that it is executed before fork is called on Unix
|
||||
// systems.
|
||||
|
||||
detach = false;
|
||||
readPw = true;
|
||||
sunum = *cli_options.readSupwSrv;
|
||||
}
|
||||
|
||||
if (cli_options.limits) {
|
||||
detach = false;
|
||||
Meta::mp->read(inifile);
|
||||
unixhandler.setuid();
|
||||
unixhandler.finalcap();
|
||||
LimitTest::testLimits(a);
|
||||
#endif
|
||||
" -v Use verbose logging (include debug-logs).\n"
|
||||
#ifdef Q_OS_UNIX
|
||||
" -fg Don't detach from console.\n"
|
||||
#else
|
||||
" -fg Don't write to the log file.\n"
|
||||
#endif
|
||||
" -wipessl Remove SSL certificates from database.\n"
|
||||
" -wipelogs Remove all log entries from database.\n"
|
||||
" -loggroups Turns on logging for group changes for all servers.\n"
|
||||
" -logacls Turns on logging for ACL changes for all servers.\n"
|
||||
" -version Show version information.\n"
|
||||
" --db-json-dump [file] Requests a JSON dump of the database to be written to the given file\n"
|
||||
" --db-json-import [file] Reads in the provide JSON file and imports its contents into the "
|
||||
"database\n"
|
||||
"\n"
|
||||
" -license Show Murmur's license.\n"
|
||||
" -authors Show Murmur's authors.\n"
|
||||
" -third-party-licenses Show licenses for third-party software used by Murmur.\n"
|
||||
"\n"
|
||||
"If no inifile is provided, murmur will search for one in \n"
|
||||
"default locations.",
|
||||
qPrintable(args.at(0)));
|
||||
return 0;
|
||||
#ifdef Q_OS_UNIX
|
||||
} else if (arg == "-limits") {
|
||||
detach = false;
|
||||
Meta::mp->read(inifile);
|
||||
unixhandler.setuid();
|
||||
unixhandler.finalcap();
|
||||
LimitTest::testLimits(a);
|
||||
#endif
|
||||
} else if (arg == "-loggroups") {
|
||||
logGroups = true;
|
||||
} else if (arg == "-logacls") {
|
||||
logACL = true;
|
||||
} else {
|
||||
detach = false;
|
||||
qFatal("Unknown argument %s", qPrintable(args.at(i)));
|
||||
}
|
||||
if (bLast && (i + 1 != args.size())) {
|
||||
detach = false;
|
||||
qFatal("Password arguments must be last.");
|
||||
}
|
||||
}
|
||||
|
||||
if (QSslSocket::supportsSsl()) {
|
||||
@ -424,22 +456,22 @@ int main(int argc, char **argv) {
|
||||
|
||||
Meta::mp->read(inifile);
|
||||
|
||||
if (!dbDumpPath.isEmpty()) {
|
||||
if (cli_options.dbDumpPath) {
|
||||
DBWrapper wrapper(Meta::getConnectionParameter());
|
||||
|
||||
std::ofstream file(dbDumpPath.toStdString());
|
||||
std::ofstream file(*cli_options.dbDumpPath);
|
||||
file << wrapper.exportDBToJSON().dump(2);
|
||||
|
||||
qInfo("Dumped JSON representation of database contents to '%s'", qPrintable(dbDumpPath));
|
||||
qInfo("Dumped JSON representation of database contents to '%s'", cli_options.dbDumpPath->c_str());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dbImportPath.isEmpty()) {
|
||||
qInfo("Importing contents of '%s' into database", qPrintable(dbImportPath));
|
||||
if (cli_options.dbImportPath) {
|
||||
qInfo("Importing contents of '%s' into database", cli_options.dbImportPath->c_str());
|
||||
DBWrapper wrapper(Meta::getConnectionParameter());
|
||||
|
||||
std::ifstream file(dbImportPath.toStdString());
|
||||
std::ifstream file(*cli_options.dbImportPath);
|
||||
|
||||
nlohmann::json json;
|
||||
file >> json;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user