|
|
|
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|
|
|
// Copyright (c) 2009-2013 The Bitcoin developers
|
|
|
|
// Distributed under the MIT/X11 software license, see the accompanying
|
|
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
|
|
|
|
#include "clientversion.h"
|
|
|
|
#include "rpcserver.h"
|
|
|
|
#include "init.h"
|
|
|
|
#include "main.h"
|
|
|
|
#include "noui.h"
|
|
|
|
#include "ui_interface.h"
|
|
|
|
#include "util.h"
|
|
|
|
|
|
|
|
#include <boost/algorithm/string/predicate.hpp>
|
|
|
|
#include <boost/filesystem.hpp>
|
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
10 years ago
|
|
|
#include <boost/thread.hpp>
|
|
|
|
|
|
|
|
/* Introduction text for doxygen: */
|
|
|
|
|
|
|
|
/*! \mainpage Developer documentation
|
|
|
|
*
|
|
|
|
* \section intro_sec Introduction
|
|
|
|
*
|
|
|
|
* This is the developer documentation of the reference client for an experimental new digital currency called Bitcoin (http://www.bitcoin.org/),
|
|
|
|
* which enables instant payments to anyone, anywhere in the world. Bitcoin uses peer-to-peer technology to operate
|
|
|
|
* with no central authority: managing transactions and issuing money are carried out collectively by the network.
|
|
|
|
*
|
|
|
|
* The software is a community-driven open source project, released under the MIT license.
|
|
|
|
*
|
|
|
|
* \section Navigation
|
|
|
|
* Use the buttons <code>Namespaces</code>, <code>Classes</code> or <code>Files</code> at the top of the page to start navigating the code.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static bool fDaemon;
|
|
|
|
|
|
|
|
void DetectShutdownThread(boost::thread_group* threadGroup)
|
|
|
|
{
|
|
|
|
bool fShutdown = ShutdownRequested();
|
|
|
|
// Tell the main threads to shutdown.
|
|
|
|
while (!fShutdown)
|
|
|
|
{
|
|
|
|
MilliSleep(200);
|
|
|
|
fShutdown = ShutdownRequested();
|
|
|
|
}
|
|
|
|
if (threadGroup)
|
|
|
|
{
|
|
|
|
threadGroup->interrupt_all();
|
|
|
|
threadGroup->join_all();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Start
|
|
|
|
//
|
|
|
|
bool AppInit(int argc, char* argv[])
|
|
|
|
{
|
|
|
|
boost::thread_group threadGroup;
|
|
|
|
boost::thread* detectShutdownThread = NULL;
|
|
|
|
|
|
|
|
bool fRet = false;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Parameters
|
|
|
|
//
|
|
|
|
// If Qt is used, parameters/bitcoin.conf are parsed in qt/bitcoin.cpp's main()
|
|
|
|
ParseParameters(argc, argv);
|
|
|
|
|
|
|
|
// Process help and version before taking care about datadir
|
|
|
|
if (mapArgs.count("-?") || mapArgs.count("-help") || mapArgs.count("-version"))
|
|
|
|
{
|
|
|
|
std::string strUsage = _("Bitcoin Core Daemon") + " " + _("version") + " " + FormatFullVersion() + "\n";
|
|
|
|
|
|
|
|
if (mapArgs.count("-version"))
|
|
|
|
{
|
|
|
|
strUsage += LicenseInfo();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
strUsage += "\n" + _("Usage:") + "\n" +
|
|
|
|
" bitcoind [options] " + _("Start Bitcoin Core Daemon") + "\n";
|
|
|
|
|
|
|
|
strUsage += "\n" + HelpMessage(HMM_BITCOIND);
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(stdout, "%s", strUsage.c_str());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
if (!boost::filesystem::is_directory(GetDataDir(false)))
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", mapArgs["-datadir"].c_str());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
try
|
|
|
|
{
|
|
|
|
ReadConfigFile(mapArgs, mapMultiArgs);
|
|
|
|
} catch(std::exception &e) {
|
|
|
|
fprintf(stderr,"Error reading configuration file: %s\n", e.what());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
// Check for -testnet or -regtest parameter (Params() calls are only valid after this clause)
|
|
|
|
if (!SelectParamsFromCommandLine()) {
|
|
|
|
fprintf(stderr, "Error: Invalid combination of -regtest and -testnet.\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Command-line RPC
|
|
|
|
bool fCommandLine = false;
|
|
|
|
for (int i = 1; i < argc; i++)
|
|
|
|
if (!IsSwitchChar(argv[i][0]) && !boost::algorithm::istarts_with(argv[i], "bitcoin:"))
|
|
|
|
fCommandLine = true;
|
|
|
|
|
|
|
|
if (fCommandLine)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Error: There is no RPC client functionality in bitcoind anymore. Use the bitcoin-cli utility instead.\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
#ifndef WIN32
|
|
|
|
fDaemon = GetBoolArg("-daemon", false);
|
|
|
|
if (fDaemon)
|
|
|
|
{
|
|
|
|
fprintf(stdout, "Bitcoin server starting\n");
|
|
|
|
|
|
|
|
// Daemonize
|
|
|
|
pid_t pid = fork();
|
|
|
|
if (pid < 0)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Error: fork() returned %d errno %d\n", pid, errno);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (pid > 0) // Parent process, pid is child process id
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
// Child process falls through to rest of initialization
|
|
|
|
|
|
|
|
pid_t sid = setsid();
|
|
|
|
if (sid < 0)
|
|
|
|
fprintf(stderr, "Error: setsid() returned %d errno %d\n", sid, errno);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
SoftSetBoolArg("-server", true);
|
|
|
|
|
|
|
|
detectShutdownThread = new boost::thread(boost::bind(&DetectShutdownThread, &threadGroup));
|
|
|
|
fRet = AppInit2(threadGroup);
|
|
|
|
}
|
|
|
|
catch (std::exception& e) {
|
|
|
|
PrintExceptionContinue(&e, "AppInit()");
|
|
|
|
} catch (...) {
|
|
|
|
PrintExceptionContinue(NULL, "AppInit()");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!fRet)
|
|
|
|
{
|
|
|
|
if (detectShutdownThread)
|
|
|
|
detectShutdownThread->interrupt();
|
|
|
|
|
|
|
|
threadGroup.interrupt_all();
|
|
|
|
// threadGroup.join_all(); was left out intentionally here, because we didn't re-test all of
|
|
|
|
// the startup-failure cases to make sure they don't result in a hang due to some
|
|
|
|
// thread-blocking-waiting-for-another-thread-during-startup case
|
|
|
|
}
|
|
|
|
|
|
|
|
if (detectShutdownThread)
|
|
|
|
{
|
|
|
|
detectShutdownThread->join();
|
|
|
|
delete detectShutdownThread;
|
|
|
|
detectShutdownThread = NULL;
|
|
|
|
}
|
|
|
|
Shutdown();
|
|
|
|
|
|
|
|
return fRet;
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char* argv[])
|
|
|
|
{
|
|
|
|
SetupEnvironment();
|
|
|
|
|
|
|
|
// Connect bitcoind signal handlers
|
|
|
|
noui_connect();
|
|
|
|
|
|
|
|
return (AppInit(argc, argv) ? 0 : 1);
|
|
|
|
}
|