changeset 2547:cf79ecb22152 draft

Merge pull request #1284 from laanwj/2012_05_helpmessage Move help message out of AppInit2
author Wladimir J. van der Laan <laanwj@gmail.com>
date Sun, 13 May 2012 12:39:35 -0700
parents 7b5d66ba66bd (current diff) fb589632c674 (diff)
children c7049fd91250
files
diffstat 3 files changed, 185 insertions(+), 131 deletions(-) [+]
line wrap: on
line diff
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -100,14 +100,52 @@
 
     return 1;
 }
-#endif
 
 bool AppInit(int argc, char* argv[])
 {
     bool fRet = false;
     try
     {
-        fRet = AppInit2(argc, argv);
+        //
+        // Parameters
+        //
+        // If Qt is used, parameters/bitcoin.conf are parsed in qt/bitcoin.cpp's main()
+        ParseParameters(argc, argv);
+        if (!boost::filesystem::is_directory(GetDataDir(false)))
+        {
+            fprintf(stderr, "Error: Specified directory does not exist\n");
+            Shutdown(NULL);
+        }
+        ReadConfigFile(mapArgs, mapMultiArgs);
+
+        if (mapArgs.count("-?") || mapArgs.count("--help"))
+        {
+            // First part of help message is specific to bitcoind / RPC client
+            std::string strUsage = _("Bitcoin version") + " " + FormatFullVersion() + "\n\n" +
+                _("Usage:") + "\n" +
+                  "  bitcoind [options]                     " + "\n" +
+                  "  bitcoind [options] <command> [params]  " + _("Send command to -server or bitcoind") + "\n" +
+                  "  bitcoind [options] help                " + _("List commands") + "\n" +
+                  "  bitcoind [options] help <command>      " + _("Get help for a command") + "\n";
+
+            strUsage += "\n" + HelpMessage();
+
+            fprintf(stderr, "%s", strUsage.c_str());
+            return false;
+        }
+
+        // Command-line RPC
+        for (int i = 1; i < argc; i++)
+            if (!IsSwitchChar(argv[i][0]) && !(strlen(argv[i]) > 7 && strncasecmp(argv[i], "bitcoin:", 8) == 0))
+                fCommandLine = true;
+
+        if (fCommandLine)
+        {
+            int ret = CommandLineRPC(argc, argv);
+            exit(ret);
+        }
+
+        fRet = AppInit2();
     }
     catch (std::exception& e) {
         PrintException(&e, "AppInit()");
@@ -118,6 +156,7 @@
         Shutdown(NULL);
     return fRet;
 }
+#endif
 
 bool static InitError(const std::string &str)
 {
@@ -142,7 +181,89 @@
     return true;
 }
 
-bool AppInit2(int argc, char* argv[])
+// Core-specific options shared between UI and daemon
+std::string HelpMessage()
+{
+    string strUsage = _("Options:") + "\n" +
+        "  -conf=<file>           " + _("Specify configuration file (default: bitcoin.conf)") + "\n" +
+        "  -pid=<file>            " + _("Specify pid file (default: bitcoind.pid)") + "\n" +
+        "  -gen                   " + _("Generate coins") + "\n" +
+        "  -gen=0                 " + _("Don't generate coins") + "\n" +
+        "  -datadir=<dir>         " + _("Specify data directory") + "\n" +
+        "  -dbcache=<n>           " + _("Set database cache size in megabytes (default: 25)") + "\n" +
+        "  -dblogsize=<n>         " + _("Set database disk log size in megabytes (default: 100)") + "\n" +
+        "  -timeout=<n>           " + _("Specify connection timeout (in milliseconds)") + "\n" +
+        "  -proxy=<ip:port>       " + _("Connect through socks proxy") + "\n" +
+        "  -socks=<n>             " + _("Select the version of socks proxy to use (4 or 5, 5 is default)") + "\n" +
+        "  -noproxy=<net>         " + _("Do not use proxy for connections to network <net> (IPv4 or IPv6)") + "\n" +
+        "  -dns                   " + _("Allow DNS lookups for -addnode, -seednode and -connect") + "\n" +
+        "  -proxydns              " + _("Pass DNS requests to (SOCKS5) proxy") + "\n" +
+        "  -port=<port>           " + _("Listen for connections on <port> (default: 8333 or testnet: 18333)") + "\n" +
+        "  -maxconnections=<n>    " + _("Maintain at most <n> connections to peers (default: 125)") + "\n" +
+        "  -addnode=<ip>          " + _("Add a node to connect to and attempt to keep the connection open") + "\n" +
+        "  -connect=<ip>          " + _("Connect only to the specified node") + "\n" +
+        "  -seednode=<ip>         " + _("Connect to a node to retrieve peer addresses, and disconnect") + "\n" +
+        "  -externalip=<ip>       " + _("Specify your own public address") + "\n" +
+        "  -blocknet=<net>        " + _("Do not connect to addresses in network <net> (IPv4 or IPv6)") + "\n" +
+        "  -discover              " + _("Try to discover public IP address (default: 1)") + "\n" +
+        "  -irc                   " + _("Find peers using internet relay chat (default: 0)") + "\n" +
+        "  -listen                " + _("Accept connections from outside (default: 1)") + "\n" +
+        "  -bind=<addr>           " + _("Bind to given address. Use [host]:port notation for IPv6") + "\n" +
+        "  -dnsseed               " + _("Find peers using DNS lookup (default: 1)") + "\n" +
+        "  -banscore=<n>          " + _("Threshold for disconnecting misbehaving peers (default: 100)") + "\n" +
+        "  -bantime=<n>           " + _("Number of seconds to keep misbehaving peers from reconnecting (default: 86400)") + "\n" +
+        "  -maxreceivebuffer=<n>  " + _("Maximum per-connection receive buffer, <n>*1000 bytes (default: 10000)") + "\n" +
+        "  -maxsendbuffer=<n>     " + _("Maximum per-connection send buffer, <n>*1000 bytes (default: 10000)") + "\n" +
+#ifdef USE_UPNP
+#if USE_UPNP
+        "  -upnp                  " + _("Use Universal Plug and Play to map the listening port (default: 1)") + "\n" +
+#else
+        "  -upnp                  " + _("Use Universal Plug and Play to map the listening port (default: 0)") + "\n" +
+#endif
+#endif
+        "  -detachdb              " + _("Detach block and address databases. Increases shutdown time (default: 0)") + "\n" +
+        "  -paytxfee=<amt>        " + _("Fee per KB to add to transactions you send") + "\n" +
+#ifdef QT_GUI
+        "  -server                " + _("Accept command line and JSON-RPC commands") + "\n" +
+#endif
+#if !defined(WIN32) && !defined(QT_GUI)
+        "  -daemon                " + _("Run in the background as a daemon and accept commands") + "\n" +
+#endif
+        "  -testnet               " + _("Use the test network") + "\n" +
+        "  -debug                 " + _("Output extra debugging information") + "\n" +
+        "  -logtimestamps         " + _("Prepend debug output with timestamp") + "\n" +
+        "  -printtoconsole        " + _("Send trace/debug info to console instead of debug.log file") + "\n" +
+#ifdef WIN32
+        "  -printtodebugger       " + _("Send trace/debug info to debugger") + "\n" +
+#endif
+        "  -rpcuser=<user>        " + _("Username for JSON-RPC connections") + "\n" +
+        "  -rpcpassword=<pw>      " + _("Password for JSON-RPC connections") + "\n" +
+        "  -rpcport=<port>        " + _("Listen for JSON-RPC connections on <port> (default: 8332)") + "\n" +
+        "  -rpcallowip=<ip>       " + _("Allow JSON-RPC connections from specified IP address") + "\n" +
+        "  -rpcconnect=<ip>       " + _("Send commands to node running on <ip> (default: 127.0.0.1)") + "\n" +
+        "  -blocknotify=<cmd>     " + _("Execute command when the best block changes (%s in cmd is replaced by block hash)") + "\n" +
+        "  -upgradewallet         " + _("Upgrade wallet to latest format") + "\n" +
+        "  -keypool=<n>           " + _("Set key pool size to <n> (default: 100)") + "\n" +
+        "  -rescan                " + _("Rescan the block chain for missing wallet transactions") + "\n" +
+        "  -checkblocks=<n>       " + _("How many blocks to check at startup (default: 2500, 0 = all)") + "\n" +
+        "  -checklevel=<n>        " + _("How thorough the block verification is (0-6, default: 1)") + "\n" +
+        "  -loadblock=<file>      " + _("Imports blocks from external blk000?.dat file") + "\n" +
+        "  -?                     " + _("This help message") + "\n";
+
+    strUsage += string() +
+        _("\nSSL options: (see the Bitcoin Wiki for SSL setup instructions)") + "\n" +
+        "  -rpcssl                                  " + _("Use OpenSSL (https) for JSON-RPC connections") + "\n" +
+        "  -rpcsslcertificatechainfile=<file.cert>  " + _("Server certificate file (default: server.cert)") + "\n" +
+        "  -rpcsslprivatekeyfile=<file.pem>         " + _("Server private key (default: server.pem)") + "\n" +
+        "  -rpcsslciphers=<ciphers>                 " + _("Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH)") + "\n";
+
+    return strUsage;
+}
+
+/** Initialize bitcoin.
+ *  @pre Parameters should be parsed and config file should be read.
+ */
+bool AppInit2()
 {
 #ifdef _MSC_VER
     // Turn off microsoft heap dump noise
@@ -167,120 +288,6 @@
     sigaction(SIGHUP, &sa, NULL);
 #endif
 
-    //
-    // Parameters
-    //
-    // If Qt is used, parameters/bitcoin.conf are parsed in qt/bitcoin.cpp's main()
-#if !defined(QT_GUI)
-    ParseParameters(argc, argv);
-    if (!boost::filesystem::is_directory(GetDataDir(false)))
-    {
-        fprintf(stderr, "Error: Specified directory does not exist\n");
-        Shutdown(NULL);
-    }
-    ReadConfigFile(mapArgs, mapMultiArgs);
-#endif
-
-    if (mapArgs.count("-?") || mapArgs.count("--help"))
-    {
-        string strUsage = string() +
-          _("Bitcoin version") + " " + FormatFullVersion() + "\n\n" +
-          _("Usage:") + "\t\t\t\t\t\t\t\t\t\t\n" +
-            "  bitcoind [options]                   \t  " + "\n" +
-            "  bitcoind [options] <command> [params]\t  " + _("Send command to -server or bitcoind") + "\n" +
-            "  bitcoind [options] help              \t\t  " + _("List commands") + "\n" +
-            "  bitcoind [options] help <command>    \t\t  " + _("Get help for a command") + "\n" +
-          _("Options:") + "\n" +
-            "  -conf=<file>     \t\t  " + _("Specify configuration file (default: bitcoin.conf)") + "\n" +
-            "  -pid=<file>      \t\t  " + _("Specify pid file (default: bitcoind.pid)") + "\n" +
-            "  -gen             \t\t  " + _("Generate coins") + "\n" +
-            "  -gen=0           \t\t  " + _("Don't generate coins") + "\n" +
-            "  -min             \t\t  " + _("Start minimized") + "\n" +
-            "  -splash          \t\t  " + _("Show splash screen on startup (default: 1)") + "\n" +
-            "  -datadir=<dir>   \t\t  " + _("Specify data directory") + "\n" +
-            "  -dbcache=<n>     \t\t  " + _("Set database cache size in megabytes (default: 25)") + "\n" +
-            "  -dblogsize=<n>   \t\t  " + _("Set database disk log size in megabytes (default: 100)") + "\n" +
-            "  -timeout=<n>     \t  "   + _("Specify connection timeout (in milliseconds)") + "\n" +
-            "  -proxy=<ip:port> \t  "   + _("Connect through socks proxy") + "\n" +
-            "  -socks=<n>       \t  "   + _("Select the version of socks proxy to use (4 or 5, 5 is default)") + "\n" +
-            "  -noproxy=<net>   \t  "   + _("Do not use proxy for connections to network <net> (IPv4 or IPv6)") + "\n" +
-            "  -dns             \t  "   + _("Allow DNS lookups for -addnode, -seednode and -connect") + "\n" +
-            "  -proxydns        \t  "   + _("Pass DNS requests to (SOCKS5) proxy") + "\n" +
-            "  -port=<port>     \t\t  " + _("Listen for connections on <port> (default: 8333 or testnet: 18333)") + "\n" +
-            "  -maxconnections=<n>\t  " + _("Maintain at most <n> connections to peers (default: 125)") + "\n" +
-            "  -addnode=<ip>    \t  "   + _("Add a node to connect to and attempt to keep the connection open") + "\n" +
-            "  -connect=<ip>    \t\t  " + _("Connect only to the specified node") + "\n" +
-            "  -seednode=<ip>   \t\t  " + _("Connect to a node to retrieve peer addresses, and disconnect") + "\n" +
-            "  -externalip=<ip> \t  "   + _("Specify your own public address") + "\n" +
-            "  -blocknet=<net>  \t  "   + _("Do not connect to addresses in network <net> (IPv4 or IPv6)") + "\n" +
-            "  -discover        \t  "   + _("Try to discover public IP address (default: 1)") + "\n" +
-            "  -irc             \t  "   + _("Find peers using internet relay chat (default: 0)") + "\n" +
-            "  -listen          \t  "   + _("Accept connections from outside (default: 1)") + "\n" +
-            "  -bind=<addr>     \t  "   + _("Bind to given address. Use [host]:port notation for IPv6") + "\n" +
-#ifdef QT_GUI
-            "  -lang=<lang>     \t\t  " + _("Set language, for example \"de_DE\" (default: system locale)") + "\n" +
-#endif
-            "  -dnsseed         \t  "   + _("Find peers using DNS lookup (default: 1)") + "\n" +
-            "  -banscore=<n>    \t  "   + _("Threshold for disconnecting misbehaving peers (default: 100)") + "\n" +
-            "  -bantime=<n>     \t  "   + _("Number of seconds to keep misbehaving peers from reconnecting (default: 86400)") + "\n" +
-            "  -maxreceivebuffer=<n>\t  " + _("Maximum per-connection receive buffer, <n>*1000 bytes (default: 10000)") + "\n" +
-            "  -maxsendbuffer=<n>\t  "   + _("Maximum per-connection send buffer, <n>*1000 bytes (default: 10000)") + "\n" +
-#ifdef USE_UPNP
-#if USE_UPNP
-            "  -upnp            \t  "   + _("Use Universal Plug and Play to map the listening port (default: 1)") + "\n" +
-#else
-            "  -upnp            \t  "   + _("Use Universal Plug and Play to map the listening port (default: 0)") + "\n" +
-#endif
-            "  -detachdb        \t  "   + _("Detach block and address databases. Increases shutdown time (default: 0)") + "\n" +
-#endif
-            "  -paytxfee=<amt>  \t  "   + _("Fee per KB to add to transactions you send") + "\n" +
-#ifdef QT_GUI
-            "  -server          \t\t  " + _("Accept command line and JSON-RPC commands") + "\n" +
-#endif
-#if !defined(WIN32) && !defined(QT_GUI)
-            "  -daemon          \t\t  " + _("Run in the background as a daemon and accept commands") + "\n" +
-#endif
-            "  -testnet         \t\t  " + _("Use the test network") + "\n" +
-            "  -debug           \t\t  " + _("Output extra debugging information") + "\n" +
-            "  -logtimestamps   \t  "   + _("Prepend debug output with timestamp") + "\n" +
-            "  -printtoconsole  \t  "   + _("Send trace/debug info to console instead of debug.log file") + "\n" +
-#ifdef WIN32
-            "  -printtodebugger \t  "   + _("Send trace/debug info to debugger") + "\n" +
-#endif
-            "  -rpcuser=<user>  \t  "   + _("Username for JSON-RPC connections") + "\n" +
-            "  -rpcpassword=<pw>\t  "   + _("Password for JSON-RPC connections") + "\n" +
-            "  -rpcport=<port>  \t\t  " + _("Listen for JSON-RPC connections on <port> (default: 8332)") + "\n" +
-            "  -rpcallowip=<ip> \t\t  " + _("Allow JSON-RPC connections from specified IP address") + "\n" +
-            "  -rpcconnect=<ip> \t  "   + _("Send commands to node running on <ip> (default: 127.0.0.1)") + "\n" +
-            "  -blocknotify=<cmd> "     + _("Execute command when the best block changes (%s in cmd is replaced by block hash)") + "\n" +
-            "  -upgradewallet   \t  "   + _("Upgrade wallet to latest format") + "\n" +
-            "  -keypool=<n>     \t  "   + _("Set key pool size to <n> (default: 100)") + "\n" +
-            "  -rescan          \t  "   + _("Rescan the block chain for missing wallet transactions") + "\n" +
-            "  -checkblocks=<n> \t\t  " + _("How many blocks to check at startup (default: 2500, 0 = all)") + "\n" +
-            "  -checklevel=<n>  \t\t  " + _("How thorough the block verification is (0-6, default: 1)") + "\n" +
-            "  -loadblock=<file>\t  "   + _("Imports blocks from external blk000?.dat file") + "\n";
-
-        strUsage += string() +
-            _("\nSSL options: (see the Bitcoin Wiki for SSL setup instructions)") + "\n" +
-            "  -rpcssl                                \t  " + _("Use OpenSSL (https) for JSON-RPC connections") + "\n" +
-            "  -rpcsslcertificatechainfile=<file.cert>\t  " + _("Server certificate file (default: server.cert)") + "\n" +
-            "  -rpcsslprivatekeyfile=<file.pem>       \t  " + _("Server private key (default: server.pem)") + "\n" +
-            "  -rpcsslciphers=<ciphers>               \t  " + _("Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH)") + "\n";
-
-        strUsage += string() +
-            "  -?               \t\t  " + _("This help message") + "\n";
-
-        // Remove tabs
-        strUsage.erase(std::remove(strUsage.begin(), strUsage.end(), '\t'), strUsage.end());
-#if defined(QT_GUI) && defined(WIN32)
-        // On windows, show a message box, as there is no stderr
-        ThreadSafeMessageBox(strUsage, _("Usage"), wxOK | wxMODAL);
-#else
-        fprintf(stderr, "%s", strUsage.c_str());
-#endif
-        return false;
-    }
-
     fTestNet = GetBoolArg("-testnet");
     if (fTestNet)
     {
@@ -309,18 +316,6 @@
     fPrintToDebugger = GetBoolArg("-printtodebugger");
     fLogTimestamps = GetBoolArg("-logtimestamps");
 
-#ifndef QT_GUI
-    for (int i = 1; i < argc; i++)
-        if (!IsSwitchChar(argv[i][0]) && !(strlen(argv[i]) > 7 && strncasecmp(argv[i], "bitcoin:", 8) == 0))
-            fCommandLine = true;
-
-    if (fCommandLine)
-    {
-        int ret = CommandLineRPC(argc, argv);
-        exit(ret);
-    }
-#endif
-
 #if !defined(WIN32) && !defined(QT_GUI)
     if (fDaemon)
     {
@@ -660,6 +655,8 @@
         CreateThread(ThreadRPCServer, NULL);
 
 #if !defined(QT_GUI)
+    // Loop until process is exit()ed from shutdown() function,
+    // called from ThreadRPCServer thread when a "stop" command is received.
     while (1)
         Sleep(5000);
 #endif
--- a/src/init.h
+++ b/src/init.h
@@ -11,6 +11,7 @@
 
 void Shutdown(void* parg);
 bool AppInit(int argc, char* argv[]);
-bool AppInit2(int argc, char* argv[]);
+bool AppInit2();
+std::string HelpMessage();
 
 #endif
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -129,6 +129,53 @@
     exit(1);
 }
 
+/** Help message for Bitcoin-Qt, shown with --help. */
+class HelpMessageBox: public QMessageBox
+{
+public:
+    HelpMessageBox(QWidget *parent = 0);
+
+    void exec();
+private:
+    QString header;
+    QString coreOptions;
+    QString uiOptions;
+};
+#include <QSpacerItem>
+#include <QGridLayout>
+HelpMessageBox::HelpMessageBox(QWidget *parent):
+    QMessageBox(parent)
+{
+    header = tr("Bitcoin-Qt") + " " + tr("version") + " " +
+            QString::fromStdString(FormatFullVersion()) + "\n\n" +
+        tr("Usage:") + "\n" +
+          "  bitcoin-qt [options]                     " + "\n";
+    coreOptions = QString::fromStdString(HelpMessage());
+    uiOptions = tr("UI options") + ":\n" +
+            "  -lang=<lang>           " + tr("Set language, for example \"de_DE\" (default: system locale)") + "\n" +
+            "  -min                   " + tr("Start minimized") + "\n" +
+            "  -splash                " + tr("Show splash screen on startup (default: 1)") + "\n";
+
+    setWindowTitle(tr("Bitcoin-Qt"));
+    setTextFormat(Qt::PlainText);
+    // setMinimumWidth is ignored for QMessageBox so put in nonbreaking spaces to make it wider.
+    QChar em_space(0x2003);
+    setText(header + QString(em_space).repeated(40));
+    setDetailedText(coreOptions + "\n" + uiOptions);
+}
+
+void HelpMessageBox::exec()
+{
+#if defined(WIN32)
+    // On windows, show a message box, as there is no stderr in windowed applications
+    QMessageBox::exec();
+#else
+    // On other operating systems, the expected action is to print the message to the console.
+    QString strUsage = header + "\n" + coreOptions + "\n" + uiOptions;
+    fprintf(stderr, "%s", strUsage.toStdString().c_str());
+#endif
+}
+
 #ifdef WIN32
 #define strncasecmp strnicmp
 #endif
@@ -218,6 +265,15 @@
     if (translator.load(lang_territory, ":/translations/"))
         app.installTranslator(&translator);
 
+    // Show help message immediately after parsing command-line options (for "-lang") and setting locale,
+    // but before showing splash screen.
+    if (mapArgs.count("-?") || mapArgs.count("--help"))
+    {
+        HelpMessageBox help;
+        help.exec();
+        return 1;
+    }
+
     QSplashScreen splash(QPixmap(":/images/splash"), 0);
     if (GetBoolArg("-splash", true) && !GetBoolArg("-min"))
     {
@@ -238,7 +294,7 @@
 
         BitcoinGUI window;
         guiref = &window;
-        if(AppInit2(argc, argv))
+        if(AppInit2())
         {
             {
                 // Put this in a block, so that the Model objects are cleaned up before