Fix CRLF
[VerusCoin.git] / init.cpp
CommitLineData
8bd66202
GA
1// Copyright (c) 2009-2010 Satoshi Nakamoto
2// Distributed under the MIT/X11 software license, see the accompanying
3// file license.txt or http://www.opensource.org/licenses/mit-license.php.
4
5#include "headers.h"
6
7
8
9
10void ExitTimeout(void* parg)
11{
12#ifdef __WXMSW__
13 Sleep(5000);
14 ExitProcess(0);
15#endif
16}
17
18void Shutdown(void* parg)
19{
20 static CCriticalSection cs_Shutdown;
21 static bool fTaken;
22 bool fFirstThread;
23 CRITICAL_BLOCK(cs_Shutdown)
24 {
25 fFirstThread = !fTaken;
26 fTaken = true;
27 }
28 static bool fExit;
29 if (fFirstThread)
30 {
31 fShutdown = true;
32 nTransactionsUpdated++;
33 DBFlush(false);
34 StopNode();
35 DBFlush(true);
36 CreateThread(ExitTimeout, NULL);
37 Sleep(50);
38 printf("Bitcoin exiting\n\n");
39 fExit = true;
40 exit(0);
41 }
42 else
43 {
44 while (!fExit)
45 Sleep(500);
46 Sleep(100);
47 ExitThread(0);
48 }
49}
50
51
52
53
54
55
56//////////////////////////////////////////////////////////////////////////////
57//
58// Startup folder
59//
60
61#ifdef __WXMSW__
62string StartupShortcutPath()
63{
64 return MyGetSpecialFolderPath(CSIDL_STARTUP, true) + "\\Bitcoin.lnk";
65}
66
67bool GetStartOnSystemStartup()
68{
69 return filesystem::exists(StartupShortcutPath().c_str());
70}
71
72void SetStartOnSystemStartup(bool fAutoStart)
73{
74 // If the shortcut exists already, remove it for updating
75 remove(StartupShortcutPath().c_str());
76
77 if (fAutoStart)
78 {
79 CoInitialize(NULL);
80
81 // Get a pointer to the IShellLink interface.
82 IShellLink* psl = NULL;
83 HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL,
84 CLSCTX_INPROC_SERVER, IID_IShellLink,
85 reinterpret_cast<void**>(&psl));
86
87 if (SUCCEEDED(hres))
88 {
89 // Get the current executable path
90 TCHAR pszExePath[MAX_PATH];
91 GetModuleFileName(NULL, pszExePath, sizeof(pszExePath));
92
93 // Set the path to the shortcut target
94 psl->SetPath(pszExePath);
95 PathRemoveFileSpec(pszExePath);
96 psl->SetWorkingDirectory(pszExePath);
97 psl->SetShowCmd(SW_SHOWMINNOACTIVE);
98
99 // Query IShellLink for the IPersistFile interface for
100 // saving the shortcut in persistent storage.
101 IPersistFile* ppf = NULL;
102 hres = psl->QueryInterface(IID_IPersistFile,
103 reinterpret_cast<void**>(&ppf));
104 if (SUCCEEDED(hres))
105 {
106 WCHAR pwsz[MAX_PATH];
107 // Ensure that the string is ANSI.
108 MultiByteToWideChar(CP_ACP, 0, StartupShortcutPath().c_str(), -1, pwsz, MAX_PATH);
109 // Save the link by calling IPersistFile::Save.
110 hres = ppf->Save(pwsz, TRUE);
111 ppf->Release();
112 }
113 psl->Release();
114 }
115 CoUninitialize();
116 }
117}
118
119#elif defined(__WXGTK__)
120
121//
122// Follow the Desktop Application Autostart Spec:
123// http://standards.freedesktop.org/autostart-spec/autostart-spec-latest.html
124//
125
126boost::filesystem::path GetAutostartDir()
127{
128 namespace fs = boost::filesystem;
129
130 char* pszConfigHome = getenv("XDG_CONFIG_HOME");
131 if (pszConfigHome) return fs::path(pszConfigHome) / fs::path("autostart");
132 char* pszHome = getenv("HOME");
133 if (pszHome) return fs::path(pszHome) / fs::path(".config/autostart");
134 return fs::path();
135}
136
137boost::filesystem::path GetAutostartFilePath()
138{
139 return GetAutostartDir() / boost::filesystem::path("bitcoin.desktop");
140}
141
142bool GetStartOnSystemStartup()
143{
144 boost::filesystem::ifstream optionFile(GetAutostartFilePath());
145 if (!optionFile.good())
146 return false;
147 // Scan through file for "Hidden=true":
148 string line;
149 while (!optionFile.eof())
150 {
151 getline(optionFile, line);
152 if (line.find("Hidden") != string::npos &&
153 line.find("true") != string::npos)
154 return false;
155 }
156 optionFile.close();
157
158 return true;
159}
160
161void SetStartOnSystemStartup(bool fAutoStart)
162{
163 if (!fAutoStart)
164 {
165 unlink(GetAutostartFilePath().native_file_string().c_str());
166 }
167 else
168 {
169 boost::filesystem::create_directories(GetAutostartDir());
170
171 boost::filesystem::ofstream optionFile(GetAutostartFilePath(), ios_base::out|ios_base::trunc);
172 if (!optionFile.good())
173 {
174 wxMessageBox(_("Cannot write autostart/bitcoin.desktop file"), "Bitcoin");
175 return;
176 }
177 // Write a bitcoin.desktop file to the autostart directory:
178 char pszExePath[MAX_PATH+1];
179 memset(pszExePath, 0, sizeof(pszExePath));
180 readlink("/proc/self/exe", pszExePath, sizeof(pszExePath)-1);
181 optionFile << "[Desktop Entry]\n";
182 optionFile << "Type=Application\n";
183 optionFile << "Name=Bitcoin\n";
184 optionFile << "Exec=" << pszExePath << "\n";
185 optionFile << "Terminal=false\n";
186 optionFile << "Hidden=false\n";
187 optionFile.close();
188 }
189}
190#else
191
192// TODO: OSX startup stuff; see:
193// http://developer.apple.com/mac/library/documentation/MacOSX/Conceptual/BPSystemStartup/Articles/CustomLogin.html
194
195bool GetStartOnSystemStartup() { return false; }
196void SetStartOnSystemStartup(bool fAutoStart) { }
197
198#endif
199
200
201
202
203
204
205
206//////////////////////////////////////////////////////////////////////////////
207//
208// CMyApp
209//
210
211// Define a new application
212class CMyApp : public wxApp
213{
214public:
215 wxLocale m_locale;
216
217 CMyApp(){};
218 ~CMyApp(){};
219 bool OnInit();
220 bool OnInit2();
221 int OnExit();
222
223 // Hook Initialize so we can start without GUI
224 virtual bool Initialize(int& argc, wxChar** argv);
225
226 // 2nd-level exception handling: we get all the exceptions occurring in any
227 // event handler here
228 virtual bool OnExceptionInMainLoop();
229
230 // 3rd, and final, level exception handling: whenever an unhandled
231 // exception is caught, this function is called
232 virtual void OnUnhandledException();
233
234 // and now for something different: this function is called in case of a
235 // crash (e.g. dereferencing null pointer, division by 0, ...)
236 virtual void OnFatalException();
237};
238
239IMPLEMENT_APP(CMyApp)
240
241bool CMyApp::Initialize(int& argc, wxChar** argv)
242{
243 if (argc > 1 && argv[1][0] != '-' && (!fWindows || argv[1][0] != '/') &&
244 wxString(argv[1]) != "start")
245 {
246 fCommandLine = true;
247 }
248 else if (!fGUI)
249 {
250 fDaemon = true;
251 }
252 else
253 {
254 // wxApp::Initialize will remove environment-specific parameters,
255 // so it's too early to call ParseParameters yet
256 for (int i = 1; i < argc; i++)
257 {
258 wxString str = argv[i];
259 #ifdef __WXMSW__
260 if (str.size() >= 1 && str[0] == '/')
261 str[0] = '-';
262 char pszLower[MAX_PATH];
263 strlcpy(pszLower, str.c_str(), sizeof(pszLower));
264 strlwr(pszLower);
265 str = pszLower;
266 #endif
267 // haven't decided which argument to use for this yet
268 if (str == "-daemon" || str == "-d" || str == "start")
269 fDaemon = true;
270 }
271 }
272
273#ifdef __WXGTK__
274 if (fDaemon || fCommandLine)
275 {
276 // Call the original Initialize while suppressing error messages
277 // and ignoring failure. If unable to initialize GTK, it fails
278 // near the end so hopefully the last few things don't matter.
279 {
280 wxLogNull logNo;
281 wxApp::Initialize(argc, argv);
282 }
283
284 if (fDaemon)
285 {
286 // Daemonize
287 pid_t pid = fork();
288 if (pid < 0)
289 {
290 fprintf(stderr, "Error: fork() returned %d errno %d\n", pid, errno);
291 return false;
292 }
293 if (pid > 0)
294 pthread_exit((void*)0);
295 }
296
297 return true;
298 }
299#endif
300
301 return wxApp::Initialize(argc, argv);
302}
303
304bool CMyApp::OnInit()
305{
306 bool fRet = false;
307 try
308 {
309 fRet = OnInit2();
310 }
311 catch (std::exception& e) {
312 PrintException(&e, "OnInit()");
313 } catch (...) {
314 PrintException(NULL, "OnInit()");
315 }
316 if (!fRet)
317 Shutdown(NULL);
318 return fRet;
319}
320
321extern int g_isPainting;
322
323bool CMyApp::OnInit2()
324{
325#ifdef _MSC_VER
326 // Turn off microsoft heap dump noise
327 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
328 _CrtSetReportFile(_CRT_WARN, CreateFileA("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
329#endif
330#if _MSC_VER >= 1400
331 // Disable confusing "helpful" text message on abort, ctrl-c
332 _set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
333#endif
334#if defined(__WXMSW__) && defined(__WXDEBUG__) && wxUSE_GUI
335 // Disable malfunctioning wxWidgets debug assertion
336 g_isPainting = 10000;
337#endif
338#if wxUSE_GUI
339 wxImage::AddHandler(new wxPNGHandler);
340#endif
341#if defined(__WXMSW__ ) || defined(__WXMAC__)
342 SetAppName("Bitcoin");
343#else
344 SetAppName("bitcoin");
345#endif
346#ifndef __WXMSW__
347 umask(077);
348#endif
349#ifdef __WXMSW__
350#if wxUSE_UNICODE
351 // Hack to set wxConvLibc codepage to UTF-8 on Windows,
352 // may break if wxMBConv_win32 implementation in strconv.cpp changes.
353 class wxMBConv_win32 : public wxMBConv
354 {
355 public:
356 long m_CodePage;
357 size_t m_minMBCharWidth;
358 };
359 if (((wxMBConv_win32*)&wxConvLibc)->m_CodePage == CP_ACP)
360 ((wxMBConv_win32*)&wxConvLibc)->m_CodePage = CP_UTF8;
361#endif
362#endif
363
364 // Load locale/<lang>/LC_MESSAGES/bitcoin.mo language file
365 m_locale.Init(wxLANGUAGE_DEFAULT, 0);
366 m_locale.AddCatalogLookupPathPrefix("locale");
367 if (!fWindows)
368 {
369 m_locale.AddCatalogLookupPathPrefix("/usr/share/locale");
370 m_locale.AddCatalogLookupPathPrefix("/usr/local/share/locale");
371 }
372 m_locale.AddCatalog("wxstd"); // wxWidgets standard translations, if any
373 m_locale.AddCatalog("bitcoin");
374
375 //
376 // Parameters
377 //
378 if (fCommandLine)
379 {
380 int ret = CommandLineRPC(argc, argv);
381 exit(ret);
382 }
383
384 ParseParameters(argc, argv);
385 if (mapArgs.count("-?") || mapArgs.count("--help"))
386 {
387 wxString strUsage = string() +
388 _("Usage:") + "\t\t\t\t\t\t\t\t\t\t\n" +
389 " bitcoin [options] \t" + "\n" +
390 " bitcoin [command] \t" + _("Send command to bitcoin running with -server or -daemon\n") +
391 " bitcoin [command] -? \t" + _("Get help for a command\n") +
392 " bitcoin help \t" + _("List commands\n") +
393 _("Options:\n") +
394 " -gen \t " + _("Generate coins\n") +
395 " -gen=0 \t " + _("Don't generate coins\n") +
396 " -min \t " + _("Start minimized\n") +
397 " -datadir=<dir> \t " + _("Specify data directory\n") +
398 " -proxy=<ip:port>\t " + _("Connect through socks4 proxy\n") +
399 " -addnode=<ip> \t " + _("Add a node to connect to\n") +
400 " -connect=<ip> \t " + _("Connect only to the specified node\n") +
401 " -server \t " + _("Accept command line and JSON-RPC commands\n") +
402 " -daemon \t " + _("Run in the background as a daemon and accept commands\n") +
403 " -? \t " + _("This help message\n");
404
405#if defined(__WXMSW__) && wxUSE_GUI
406 // Tabs make the columns line up in the message box
407 wxMessageBox(strUsage, "Bitcoin", wxOK);
408#else
409 // Remove tabs
410 strUsage.Replace("\t", "");
411 fprintf(stderr, "%s", ((string)strUsage).c_str());
412#endif
413 return false;
414 }
415
416 if (mapArgs.count("-datadir"))
417 strlcpy(pszSetDataDir, mapArgs["-datadir"].c_str(), sizeof(pszSetDataDir));
418
419 if (mapArgs.count("-debug"))
420 fDebug = true;
421
422 if (mapArgs.count("-printtodebugger"))
423 fPrintToDebugger = true;
424
425 if (!fDebug && !pszSetDataDir[0])
426 ShrinkDebugFile();
427 printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
428 printf("Bitcoin version %d.%d.%d%s beta, OS version %s\n", VERSION/10000, (VERSION/100)%100, VERSION%100, pszSubVer, ((string)wxGetOsDescription()).c_str());
429 printf("System default language is %d %s\n", m_locale.GetSystemLanguage(), ((string)m_locale.GetSysName()).c_str());
430 printf("Language file %s (%s)\n", (string("locale/") + (string)m_locale.GetCanonicalName() + "/LC_MESSAGES/bitcoin.mo").c_str(), ((string)m_locale.GetLocale()).c_str());
431 printf("Default data directory %s\n", GetDefaultDataDir().c_str());
432
433 if (mapArgs.count("-loadblockindextest"))
434 {
435 CTxDB txdb("r");
436 txdb.LoadBlockIndex();
437 PrintBlockTree();
438 return false;
439 }
440
441 //
442 // Limit to single instance per user
443 // Required to protect the database files if we're going to keep deleting log.*
444 //
445#ifdef __WXMSW__
446 // todo: wxSingleInstanceChecker wasn't working on Linux, never deleted its lock file
447 // maybe should go by whether successfully bind port 8333 instead
448 wxString strMutexName = wxString("bitcoin_running.") + getenv("HOMEPATH");
449 for (int i = 0; i < strMutexName.size(); i++)
450 if (!isalnum(strMutexName[i]))
451 strMutexName[i] = '.';
452 wxSingleInstanceChecker* psingleinstancechecker = new wxSingleInstanceChecker(strMutexName);
453 if (psingleinstancechecker->IsAnotherRunning())
454 {
455 printf("Existing instance found\n");
456 unsigned int nStart = GetTime();
457 loop
458 {
459 // TODO: find out how to do this in Linux, or replace with wxWidgets commands
460 // Show the previous instance and exit
461 HWND hwndPrev = FindWindowA("wxWindowClassNR", "Bitcoin");
462 if (hwndPrev)
463 {
464 if (IsIconic(hwndPrev))
465 ShowWindow(hwndPrev, SW_RESTORE);
466 SetForegroundWindow(hwndPrev);
467 return false;
468 }
469
470 if (GetTime() > nStart + 60)
471 return false;
472
473 // Resume this instance if the other exits
474 delete psingleinstancechecker;
475 Sleep(1000);
476 psingleinstancechecker = new wxSingleInstanceChecker(strMutexName);
477 if (!psingleinstancechecker->IsAnotherRunning())
478 break;
479 }
480 }
481#endif
482
483 // Bind to the port early so we can tell if another instance is already running.
484 // This is a backup to wxSingleInstanceChecker, which doesn't work on Linux.
485 string strErrors;
486 if (!BindListenPort(strErrors))
487 {
488 wxMessageBox(strErrors, "Bitcoin");
489 return false;
490 }
491
492 //
493 // Load data files
494 //
495 if (fDaemon)
496 fprintf(stdout, "bitcoin server starting\n");
497 strErrors = "";
498 int64 nStart;
499
500 printf("Loading addresses...\n");
501 nStart = GetTimeMillis();
502 if (!LoadAddresses())
503 strErrors += _("Error loading addr.dat \n");
504 printf(" addresses %15"PRI64d"ms\n", GetTimeMillis() - nStart);
505
506 printf("Loading block index...\n");
507 nStart = GetTimeMillis();
508 if (!LoadBlockIndex())
509 strErrors += _("Error loading blkindex.dat \n");
510 printf(" block index %15"PRI64d"ms\n", GetTimeMillis() - nStart);
511
512 printf("Loading wallet...\n");
513 nStart = GetTimeMillis();
514 bool fFirstRun;
515 if (!LoadWallet(fFirstRun))
516 strErrors += _("Error loading wallet.dat \n");
517 printf(" wallet %15"PRI64d"ms\n", GetTimeMillis() - nStart);
518
519 printf("Done loading\n");
520
521 //// debug print
522 printf("mapBlockIndex.size() = %d\n", mapBlockIndex.size());
523 printf("nBestHeight = %d\n", nBestHeight);
524 printf("mapKeys.size() = %d\n", mapKeys.size());
525 printf("mapPubKeys.size() = %d\n", mapPubKeys.size());
526 printf("mapWallet.size() = %d\n", mapWallet.size());
527 printf("mapAddressBook.size() = %d\n", mapAddressBook.size());
528
529 if (!strErrors.empty())
530 {
531 wxMessageBox(strErrors, "Bitcoin");
532 return false;
533 }
534
535 // Add wallet transactions that aren't already in a block to mapTransactions
536 ReacceptWalletTransactions();
537
538 //
539 // Parameters
540 //
541 if (mapArgs.count("-printblockindex") || mapArgs.count("-printblocktree"))
542 {
543 PrintBlockTree();
544 return false;
545 }
546
547 if (mapArgs.count("-printblock"))
548 {
549 string strMatch = mapArgs["-printblock"];
550 int nFound = 0;
551 for (map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi)
552 {
553 uint256 hash = (*mi).first;
554 if (strncmp(hash.ToString().c_str(), strMatch.c_str(), strMatch.size()) == 0)
555 {
556 CBlockIndex* pindex = (*mi).second;
557 CBlock block;
558 block.ReadFromDisk(pindex);
559 block.BuildMerkleTree();
560 block.print();
561 printf("\n");
562 nFound++;
563 }
564 }
565 if (nFound == 0)
566 printf("No blocks matching %s were found\n", strMatch.c_str());
567 return false;
568 }
569
570 if (mapArgs.count("-gen"))
571 {
572 if (mapArgs["-gen"].empty())
573 fGenerateBitcoins = true;
574 else
575 fGenerateBitcoins = (atoi(mapArgs["-gen"].c_str()) != 0);
576 }
577
578 if (mapArgs.count("-proxy"))
579 {
580 fUseProxy = true;
581 addrProxy = CAddress(mapArgs["-proxy"]);
582 if (!addrProxy.IsValid())
583 {
584 wxMessageBox(_("Invalid -proxy address"), "Bitcoin");
585 return false;
586 }
587 }
588
589 if (mapArgs.count("-addnode"))
590 {
591 foreach(string strAddr, mapMultiArgs["-addnode"])
592 {
593 CAddress addr(strAddr, NODE_NETWORK);
594 addr.nTime = 0; // so it won't relay unless successfully connected
595 if (addr.IsValid())
596 AddAddress(addr);
597 }
598 }
599
600 //
601 // Create the main window and start the node
602 //
603 if (!fDaemon)
604 CreateMainWindow();
605
606 if (!CheckDiskSpace())
607 return false;
608
609 RandAddSeedPerfmon();
610
611 if (!CreateThread(StartNode, NULL))
612 wxMessageBox("Error: CreateThread(StartNode) failed", "Bitcoin");
613
614 if (mapArgs.count("-server") || fDaemon)
615 CreateThread(ThreadRPCServer, NULL);
616
617 if (fFirstRun)
618 SetStartOnSystemStartup(true);
619
620 return true;
621}
622
623int CMyApp::OnExit()
624{
625 Shutdown(NULL);
626 return wxApp::OnExit();
627}
628
629bool CMyApp::OnExceptionInMainLoop()
630{
631 try
632 {
633 throw;
634 }
635 catch (std::exception& e)
636 {
637 PrintException(&e, "CMyApp::OnExceptionInMainLoop()");
638 wxLogWarning("Exception %s %s", typeid(e).name(), e.what());
639 Sleep(1000);
640 throw;
641 }
642 catch (...)
643 {
644 PrintException(NULL, "CMyApp::OnExceptionInMainLoop()");
645 wxLogWarning("Unknown exception");
646 Sleep(1000);
647 throw;
648 }
649 return true;
650}
651
652void CMyApp::OnUnhandledException()
653{
654 // this shows how we may let some exception propagate uncaught
655 try
656 {
657 throw;
658 }
659 catch (std::exception& e)
660 {
661 PrintException(&e, "CMyApp::OnUnhandledException()");
662 wxLogWarning("Exception %s %s", typeid(e).name(), e.what());
663 Sleep(1000);
664 throw;
665 }
666 catch (...)
667 {
668 PrintException(NULL, "CMyApp::OnUnhandledException()");
669 wxLogWarning("Unknown exception");
670 Sleep(1000);
671 throw;
672 }
673}
674
675void CMyApp::OnFatalException()
676{
677 wxMessageBox(_("Program has crashed and will terminate. "), "Bitcoin", wxOK | wxICON_ERROR);
678}
This page took 0.090233 seconds and 4 git commands to generate.