1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
crate::ix!();
pub fn app_init(
node: &mut NodeContext,
argc: i32,
argv: &[*mut u8]) -> bool {
todo!();
/*
bool fRet = false;
util::ThreadSetInternalName("init");
// If Qt is used, parameters/bitcoin.conf are parsed in qt/bitcoin.cpp's main()
ArgsManager& args = *Assert(node.args);
SetupServerArgs(args);
std::string error;
if (!args.ParseParameters(argc, argv, error)) {
return InitError(Untranslated(strprintf("Error parsing command line arguments: %s\n", error)));
}
// Process help and version before taking care about datadir
if (HelpRequested(args) || args.IsArgSet("-version")) {
std::string strUsage = PACKAGE_NAME " version " + FormatFullVersion() + "\n";
if (!args.IsArgSet("-version")) {
strUsage += FormatParagraph(LicenseInfo()) + "\n"
"\nUsage: bitcoind [options] Start " PACKAGE_NAME "\n"
"\n";
strUsage += args.GetHelpMessage();
}
tfm::format(std::cout, "%s", strUsage);
return true;
}
#if HAVE_DECL_FORK
// Communication with parent after daemonizing. This is used for signalling in the following ways:
// - a boolean token is sent when the initialization process (all the Init* functions) have finished to indicate
// that the parent process can quit, and whether it was successful/unsuccessful.
// - an unexpected shutdown of the child process creates an unexpected end of stream at the parent
// end, which is interpreted as failure to start.
TokenPipeEnd daemon_ep;
#endif
std::any context{&node};
try
{
if (!CheckDataDirOption()) {
return InitError(Untranslated(strprintf("Specified data directory \"%s\" does not exist.\n", args.GetArg("-datadir", ""))));
}
if (!args.ReadConfigFiles(error, true)) {
return InitError(Untranslated(strprintf("Error reading configuration file: %s\n", error)));
}
// Check for chain settings (Params() calls are only valid after this clause)
try {
SelectParams(args.GetChainName());
} catch (const std::exception& e) {
return InitError(Untranslated(strprintf("%s\n", e.what())));
}
// Error out when loose non-argument tokens are encountered on command line
for (int i = 1; i < argc; i++) {
if (!IsSwitchChar(argv[i][0])) {
return InitError(Untranslated(strprintf("Command line contains unexpected token '%s', see bitcoind -h for a list of options.\n", argv[i])));
}
}
if (!args.InitSettings(error)) {
InitError(Untranslated(error));
return false;
}
// -server defaults to true for bitcoind but not for the GUI so do this here
args.SoftSetBoolArg("-server", true);
// Set this early so that parameter interactions go to console
InitLogging(args);
InitParameterInteraction(args);
if (!AppInitBasicSetup(args)) {
// InitError will have been called with detailed error, which ends up on console
return false;
}
if (!AppInitParameterInteraction(args)) {
// InitError will have been called with detailed error, which ends up on console
return false;
}
if (!AppInitSanityChecks())
{
// InitError will have been called with detailed error, which ends up on console
return false;
}
if (args.GetBoolArg("-daemon", DEFAULT_DAEMON) || args.GetBoolArg("-daemonwait", DEFAULT_DAEMONWAIT)) {
#if HAVE_DECL_FORK
tfm::format(std::cout, PACKAGE_NAME " starting\n");
// Daemonize
switch (fork_daemon(1, 0, daemon_ep)) { // don't chdir (1), do close FDs (0)
case 0: // Child: continue.
// If -daemonwait is not enabled, immediately send a success token the parent.
if (!args.GetBoolArg("-daemonwait", DEFAULT_DAEMONWAIT)) {
daemon_ep.TokenWrite(1);
daemon_ep.Close();
}
break;
case -1: // Error happened.
return InitError(Untranslated(strprintf("fork_daemon() failed: %s\n", strerror(errno))));
default: { // Parent: wait and exit.
int token = daemon_ep.TokenRead();
if (token) { // Success
exit(EXIT_SUCCESS);
} else { // fRet = false or token read error (premature exit).
tfm::format(std::cerr, "Error during initializaton - check debug.log for details\n");
exit(EXIT_FAILURE);
}
}
}
#else
return InitError(Untranslated("-daemon is not supported on this operating system\n"));
#endif // HAVE_DECL_FORK
}
// Lock data directory after daemonization
if (!AppInitLockDataDirectory())
{
// If locking the data directory failed, exit immediately
return false;
}
fRet = AppInitInterfaces(node) && AppInitMain(node);
}
catch (const std::exception& e) {
PrintExceptionContinue(&e, "AppInit()");
} catch (...) {
PrintExceptionContinue(nullptr, "AppInit()");
}
#if HAVE_DECL_FORK
if (daemon_ep.IsOpen()) {
// Signal initialization status to parent, then close pipe.
daemon_ep.TokenWrite(fRet);
daemon_ep.Close();
}
#endif
SetSyscallSandboxPolicy(SyscallSandboxPolicy::SHUTOFF);
if (fRet) {
WaitForShutdown();
}
Interrupt(node);
Shutdown(node);
return fRet;
*/
}