Improve command line parsing.

This commit is contained in:
Vladimir Golovnev (Glassez) 2014-12-21 10:40:38 +03:00
parent 33fe829eb4
commit 5200999007

View file

@ -101,29 +101,34 @@ void sigsegvHandler(int);
void sigabrtHandler(int); void sigabrtHandler(int);
#endif #endif
struct QbtCommandLineParameters
{
bool showVersion;
bool showHelp;
#ifndef DISABLE_GUI
bool noSplash;
#else
bool shouldDaemonize;
#endif
int webUiPort;
QStringList torrents;
};
QbtCommandLineParameters parseCommandLine();
#ifndef DISABLE_GUI #ifndef DISABLE_GUI
void showSplashScreen(); void showSplashScreen();
void parseCommandLine(bool& showVersion, bool& showUsage, bool& noSplash, QStringList& torrents);
#else
void parseCommandLine(bool& showVersion, bool& showUsage, bool& shouldDaemonize, QStringList& torrents);
#endif #endif
void displayVersion(); void displayVersion();
void displayUsage(const char *prg_name); void displayUsage(const char *prg_name);
bool userAgreesWithLegalNotice(); bool userAgreesWithLegalNotice();
void displayBadArgMessage(const QString& message);
// Main // Main
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
// We must save it here because QApplication constructor may change it // We must save it here because QApplication constructor may change it
bool isOneArg = (argc == 2); bool isOneArg = (argc == 2);
bool showVersion;
bool showUsage;
#ifndef DISABLE_GUI
bool noSplash;
#else
bool shouldDaemonize;
#endif
QStringList torrents;
// Create Application // Create Application
QScopedPointer<Application> app(new Application("qBittorrent-" + misc::getUserIDString(), argc, argv)); QScopedPointer<Application> app(new Application("qBittorrent-" + misc::getUserIDString(), argc, argv));
@ -132,22 +137,40 @@ int main(int argc, char *argv[])
QObject::connect(app.data(), SIGNAL(messageReceived(const QString &)), QObject::connect(app.data(), SIGNAL(messageReceived(const QString &)),
messagesCollector, SLOT(collectMessage(const QString &))); messagesCollector, SLOT(collectMessage(const QString &)));
#ifndef DISABLE_GUI const QbtCommandLineParameters params = parseCommandLine();
parseCommandLine(showVersion, showUsage, noSplash, torrents);
#else
parseCommandLine(showVersion, showUsage, shouldDaemonize, torrents);
#endif
if (showVersion) if (params.showVersion) {
displayVersion(); if (isOneArg) {
displayVersion();
return EXIT_SUCCESS;
}
else {
displayBadArgMessage(QObject::tr("%1 must be the single command line parameter.")
.arg(QLatin1String("-v (or --version)")));
return EXIT_FAILURE;
}
}
if (showUsage) if (params.showHelp) {
displayUsage(argv[0]); if (isOneArg) {
displayUsage(argv[0]);
return EXIT_SUCCESS;
}
else {
displayBadArgMessage(QObject::tr("%1 must be the single command line parameter.")
.arg(QLatin1String("-h (or --help)")));
return EXIT_FAILURE;
}
}
// If only one parameter is present and it is "--version" if ((params.webUiPort > 0) && (params.webUiPort <= 65535)) {
// or "--help", program exits after printing appropriate message. Preferences::instance()->setWebUiPort(params.webUiPort);
if (isOneArg && (showVersion || showUsage)) }
return EXIT_SUCCESS; else {
displayBadArgMessage(QObject::tr("%1 must specify the correct port (1 to 65535).")
.arg(QLatin1String("--webui-port")));
return EXIT_FAILURE;
}
// Set environment variable // Set environment variable
if (!qputenv("QBITTORRENT", QByteArray(VERSION))) if (!qputenv("QBITTORRENT", QByteArray(VERSION)))
@ -158,7 +181,15 @@ int main(int argc, char *argv[])
// Check if qBittorrent is already running for this user // Check if qBittorrent is already running for this user
if (app->isRunning()) { if (app->isRunning()) {
#ifdef DISABLE_GUI
if (params.shouldDaemonize) {
displayBadArgMessage(QObject::tr("You cannot use %1: qBittorrent is already running for this user.")
.arg(QLatin1String("-d (or --daemon)")));
return EXIT_FAILURE;
}
#else
qDebug("qBittorrent is already running for this user."); qDebug("qBittorrent is already running for this user.");
#endif
misc::msleep(300); misc::msleep(300);
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
DWORD pid = (DWORD)app->getRunningPid(); DWORD pid = (DWORD)app->getRunningPid();
@ -167,8 +198,8 @@ int main(int argc, char *argv[])
qDebug("AllowSetForegroundWindow() returns %s", b ? "TRUE" : "FALSE"); qDebug("AllowSetForegroundWindow() returns %s", b ? "TRUE" : "FALSE");
} }
#endif #endif
if (!torrents.isEmpty()) { if (!params.torrents.isEmpty()) {
QString message = torrents.join("|"); QString message = params.torrents.join("|");
qDebug("Passing program parameters to running instance..."); qDebug("Passing program parameters to running instance...");
qDebug("Message: %s", qPrintable(message)); qDebug("Message: %s", qPrintable(message));
app->sendMessage(message); app->sendMessage(message);
@ -182,7 +213,7 @@ int main(int argc, char *argv[])
srand(time(0)); srand(time(0));
#ifdef DISABLE_GUI #ifdef DISABLE_GUI
if (shouldDaemonize) { if (params.shouldDaemonize) {
app.reset(); // Destroy current application app.reset(); // Destroy current application
if ((daemon(1, 0) == 0)) { if ((daemon(1, 0) == 0)) {
app.reset(new Application("qBittorrent-" + misc::getUserIDString(), argc, argv)); app.reset(new Application("qBittorrent-" + misc::getUserIDString(), argc, argv));
@ -197,7 +228,7 @@ int main(int argc, char *argv[])
} }
} }
#else #else
if (!noSplash) if (!(params.noSplash || Preferences::instance()->isSlashScreenDisabled()))
showSplashScreen(); showSplashScreen();
#endif #endif
@ -209,7 +240,7 @@ int main(int argc, char *argv[])
#endif #endif
#ifndef DISABLE_GUI #ifndef DISABLE_GUI
MainWindow window(0, torrents); MainWindow window(0, params.torrents);
QObject::connect(app.data(), SIGNAL(messageReceived(const QString &)), QObject::connect(app.data(), SIGNAL(messageReceived(const QString &)),
&window, SLOT(processParams(const QString &))); &window, SLOT(processParams(const QString &)));
QObject::disconnect(app.data(), SIGNAL(messageReceived(const QString &)), QObject::disconnect(app.data(), SIGNAL(messageReceived(const QString &)),
@ -222,7 +253,7 @@ int main(int argc, char *argv[])
#endif // Q_OS_MAC #endif // Q_OS_MAC
#else #else
// Load Headless class // Load Headless class
HeadlessLoader loader(torrents); HeadlessLoader loader(params.torrents);
QObject::connect(app.data(), SIGNAL(messageReceived(const QString &)), QObject::connect(app.data(), SIGNAL(messageReceived(const QString &)),
&loader, SLOT(processParams(const QString &))); &loader, SLOT(processParams(const QString &)));
QObject::disconnect(app.data(), SIGNAL(messageReceived(const QString &)), QObject::disconnect(app.data(), SIGNAL(messageReceived(const QString &)),
@ -236,6 +267,48 @@ int main(int argc, char *argv[])
return ret; return ret;
} }
QbtCommandLineParameters parseCommandLine()
{
QbtCommandLineParameters result = {0};
QStringList appArguments = qApp->arguments();
for (int i = 1; i < appArguments.size(); ++i) {
const QString& arg = appArguments[i];
if ((arg == QLatin1String("-v")) || (arg == QLatin1String("--version"))) {
result.showVersion = true;
}
else if ((arg == QLatin1String("-h")) || (arg == QLatin1String("--help"))) {
result.showHelp = true;
}
else if (arg.startsWith(QLatin1String("--webui-port="))) {
QStringList parts = arg.split(QLatin1Char('='));
if (parts.size() == 2)
result.webUiPort = parts.last().toInt();
}
#ifndef DISABLE_GUI
else if (arg == QLatin1String("--no-splash")) {
result.noSplash = true;
}
#else
else if ((arg == QLatin1String("-d")) || (arg == QLatin1String("--daemon"))) {
result.shouldDaemonize = true;
}
#endif
else {
QFileInfo torrentPath;
torrentPath.setFile(arg);
if (torrentPath.exists())
result.torrents += torrentPath.absoluteFilePath();
else
result.torrents += arg;
}
}
return result;
}
#if defined(Q_OS_UNIX) || defined(STACKTRACE_WIN) #if defined(Q_OS_UNIX) || defined(STACKTRACE_WIN)
void sigintHandler(int) void sigintHandler(int)
{ {
@ -314,74 +387,17 @@ void displayVersion()
void displayUsage(const char *prg_name) void displayUsage(const char *prg_name)
{ {
std::cout << qPrintable(QObject::tr("Usage:")) << std::endl; std::cout << qPrintable(QObject::tr("Usage:")) << std::endl;
std::cout << '\t' << prg_name << " --version: " << qPrintable(QObject::tr("displays program version")) << std::endl; std::cout << '\t' << prg_name << " -v | --version: " << qPrintable(QObject::tr("displays program version")) << std::endl;
#ifndef DISABLE_GUI #ifndef DISABLE_GUI
std::cout << '\t' << prg_name << " --no-splash: " << qPrintable(QObject::tr("disable splash screen")) << std::endl; std::cout << '\t' << prg_name << " --no-splash: " << qPrintable(QObject::tr("disable splash screen")) << std::endl;
#else #else
std::cout << '\t' << prg_name << " -d | --daemon: " << qPrintable(QObject::tr("run in daemon-mode (background)")) << std::endl; std::cout << '\t' << prg_name << " -d | --daemon: " << qPrintable(QObject::tr("run in daemon-mode (background)")) << std::endl;
#endif #endif
std::cout << '\t' << prg_name << " --help: " << qPrintable(QObject::tr("displays this help message")) << std::endl; std::cout << '\t' << prg_name << " -h | --help: " << qPrintable(QObject::tr("displays this help message")) << std::endl;
std::cout << '\t' << prg_name << " --webui-port=x: " << qPrintable(QObject::tr("changes the webui port (current: %1)").arg(QString::number(Preferences::instance()->getWebUiPort()))) << std::endl; std::cout << '\t' << prg_name << " --webui-port=x: " << qPrintable(QObject::tr("changes the webui port (current: %1)").arg(QString::number(Preferences::instance()->getWebUiPort()))) << std::endl;
std::cout << '\t' << prg_name << " " << qPrintable(QObject::tr("[files or urls]: downloads the torrents passed by the user (optional)")) << std::endl; std::cout << '\t' << prg_name << " " << qPrintable(QObject::tr("[files or urls]: downloads the torrents passed by the user (optional)")) << std::endl;
} }
#ifndef DISABLE_GUI
void parseCommandLine(bool& showVersion, bool& showUsage, bool& noSplash, QStringList& torrents)
#else
void parseCommandLine(bool& showVersion, bool& showUsage, bool& shouldDaemonize, QStringList& torrents)
#endif
{
// Default values
showVersion = false;
showUsage = false;
#ifndef DISABLE_GUI
noSplash = Preferences::instance()->isSlashScreenDisabled();
#else
shouldDaemonize = false;
#endif
torrents.clear();
QStringList appArguments = qApp->arguments();
for (int i = 1; i < appArguments.size(); ++i) {
QString& arg = appArguments[i];
if (arg == "--version") {
showVersion = true;
}
else if (arg == "--usage") {
showUsage = true;
}
else if (arg.startsWith("--webui-port=")) {
QStringList parts = arg.split("=");
if (parts.size() == 2) {
bool ok = false;
int new_port = parts.last().toInt(&ok);
if (ok && (new_port > 0) && (new_port <= 65535))
Preferences::instance()->setWebUiPort(new_port);
}
}
#ifndef DISABLE_GUI
else if (arg == "--no-splash") {
noSplash = true;
}
#else
else if ((arg == "-d") || (arg == "--daemon")) {
shouldDaemonize = true;
}
#endif
else if (!arg.startsWith("--")) {
QFileInfo torrentPath;
torrentPath.setFile(arg);
if (torrentPath.exists())
torrents += torrentPath.absoluteFilePath();
else
torrents += arg;
}
}
}
bool userAgreesWithLegalNotice() bool userAgreesWithLegalNotice()
{ {
Preferences* const pref = Preferences::instance(); Preferences* const pref = Preferences::instance();
@ -416,3 +432,9 @@ bool userAgreesWithLegalNotice()
return false; return false;
} }
void displayBadArgMessage(const QString& message)
{
std::cerr << qPrintable(QObject::tr("Bad command line: "));
std::cerr << qPrintable(message) << std::endl;
}