<commit_before>// Copyright (c) 2009-2010 <NAME>
// Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifdef _MSC_VER
    #include <stdint.h>

    #include <stdio.h>
    #include "msvc_warnings.push.h"
#else
    #ifndef BITCOIN_UTIL_H
        #include "util.h"
    #endif
#endif

#ifndef BITCOIN_TXDB_H
 #include "txdb.h"
#endif

#ifndef _BITCOINRPC_H_
 #include "bitcoinrpc.h"
#endif

#ifndef BITCOIN_INIT_H
 #include "init.h"
#endif

#include <boost/format.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/filesystem/convenience.hpp>
#include <boost/interprocess/sync/file_lock.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <openssl/crypto.h>

#ifndef WIN32
#include <signal.h>
#endif

bool fNewerOpenSSL = false; // for key.cpp's benefit


using namespace boost;

using std::string;
using std::max;
using std::map;

CWallet* pwalletMain;
CClientUIInterface uiInterface;
std::string strWalletFileName;
bool fConfChange;
unsigned int nNodeLifespan;
unsigned int nMinerSleep;
bool fUseFastIndex;
bool fUseFastStakeMiner;
bool fUseMemoryLog;
enum Checkpoints::CPMode CheckpointsMode;

// Ping and address broadcast intervals
extern ::int64_t nPingInterval;
extern ::int64_t nBroadcastInterval;

//////////////////////////////////////////////////////////////////////////////
//
// Shutdown
//

void ExitTimeout(void* parg)
{
#ifdef WIN32
  //Sleep(5000);
    Sleep(2 * 1000);
//    ExitProcess(0);
#endif
}

#ifndef TESTS_ENABLED
void StartShutdown()
{
#ifdef QT_GUI
    // ensure we leave the Qt main loop for a clean GUI exit (Shutdown() is called in bitcoin.cpp afterwards)
    uiInterface.QueueShutdown();
#else
    // Without UI, Shutdown() can simply be started in a new thread
    NewThread(Shutdown, NULL);
#endif
}
static bool 
    fExit;

void Shutdown(void* parg)
{
    if (fDebug)
        printf("Shutdown : In progress...\n");
    
    static CCriticalSection 
        cs_Shutdown;

    static bool 
        fTaken;

    // Make this thread recognisable as the shutdown thread
    RenameThread("yacoin-shutoff");

    bool 
        fFirstThread = false;
    {
        TRY_LOCK(cs_Shutdown, lockShutdown);
        if (lockShutdown)
        {
            fFirstThread = !fTaken;
            fTaken = true;
        }
    }
    if (fFirstThread)
    {
        fShutdown = true;
        fRequestShutdown = true;
        ++nTransactionsUpdated;
//        CTxDB().Close();
        bitdb.Flush(false);
        StopNode();
        {
            LOCK(cs_main);
            if (pwalletMain)
                pwalletMain->SetBestChain(CBlockLocator(pindexBest));
        }
        bitdb.Flush(true);
#if !defined(WIN32) && !defined(QT_GUI)
    if (fDaemon)
    {
        boost::filesystem::remove(GetPidFile());
    }
#endif
        UnregisterWallet(pwalletMain);
        delete pwalletMain;
        NewThread(ExitTimeout, NULL);
        Sleep(50);
        if (fDebug)
            printf("Yacoin exited\n\n");
        fExit = true;
#ifndef QT_GUI
        // ensure non-UI client gets exited here, but let yacoin-qt reach 'return 0;' in bitcoin.cpp
    #ifdef _MSC_VER
        return;
    #else
        exit(0);
    #endif        
#endif
    }
    else
    {
        while (!fExit)
            Sleep(500);
        Sleep(100);
        ExitThread(0);
    }
}
#endif

void HandleSIGTERM(int)
{
    fRequestShutdown = true;
}
#ifdef WIN32
//_____________________________________________________________________________
// this works for Windows gcc & MSVC++
static int WindowsHandleSigterm( unsigned long the_signal )
    {
    bool
        fIWillHandleIt = false;

    switch( the_signal )
        {
        case CTRL_C_EVENT:          //A CTRL+c signal was received,
            //either from keyboard input
            //or from a signal generated by the GenerateConsoleCtrlEvent function

        case CTRL_BREAK_EVENT:      //A CTRL+BREAK signal was received,
            //either from keyboard input
            //or from a signal generated by the GenerateConsoleCtrlEvent function

        case CTRL_LOGOFF_EVENT:     //A signal that the system sends to all console
            // processes when a user is logging off. This signal does not 
            // indicate which user is logging off, so no assumptions can be made.

        case CTRL_SHUTDOWN_EVENT:   // a system shutdown has occured
            HandleSIGTERM( ( int )the_signal );
            fIWillHandleIt = true;  // tell Windows we will take care of this
            break;      // It may not listen, but we will shutdown in any event

        case CTRL_CLOSE_EVENT:      // A signal that the system sends to all processes
            // attached to a console when the user closes
            // the console (either by choosing the Close
            // command from the console window's System menu,
            // or by choosing the End Task command from the Task List).
            HandleSIGTERM( ( int )the_signal );
            fIWillHandleIt = true;  // tell Windows we will take care of this
            // not on WIndows > XP :(
            // so can we hang here? Perhaps
            while( true )
            {
                Sleep( 1000 );
            }
            break;      // It may not listen, but we will shutdown in any event

        default:                    // any other (strange) signal we pass on
            break;                  // and just let it happen?
        }
    return fIWillHandleIt;
    }
//_____________________________________________________________________________
#endif
void HandleSIGHUP(int)
{
    fReopenDebugLog = true;
}





//////////////////////////////////////////////////////////////////////////////
//
// Start
//
#if !defined(QT_GUI) && !defined(TESTS_ENABLED)
bool AppInit(int argc, char* argv[])
{
    bool fRet = false;
    try
    {
        //
        // Parameters
        //
        // If Qt is used, parameters/bitcoin.conf are parsed in qt/bitcoin.cpp's main()
        ParseParameters(argc, argv);
        bool 
            fTest_or_Main_Net_is_decided = false;

        if (!boost::filesystem::is_directory(GetDataDir(fTest_or_Main_Net_is_decided)))
        {
            fprintf(stderr, "Error: Specified directory does not exist\n");
            Shutdown(NULL);
        }
        ReadConfigFile(mapArgs, mapMultiArgs);  // now two things have happened:
                                                // testnet/mainnet has been decided, and
                                                // the 'data directory' has been set
                                                // either by command line arguments or in
                                                // the configuration file.
                                                // this means that fTestNet should be tested 
                                                // first, before GetDataDir() is called next
                                                
                                                // this is documentation!

        if(mapArgs.count("--version") || mapArgs.count("-v")){
            std::string msg = "Yacoin version: " + FormatFullVersion() + "\n\n";
            fprintf(stdout, "%s", msg.c_str());
            exit(0);
        } else if (mapArgs.count("-?") || mapArgs.count("-h") || mapArgs.count("--help"))
        {
            // First part of help message is specific to yacoind / RPC client
            std::string strUsage = _("Yacoin version") + " " + FormatFullVersion() + "\n\n" +
                _("Usage:") + "\n" +
                  "  yacoind [options]                     " + "\n" +
                  "  yacoind [options] <command> [params]  " + _("Send command to -server or yacoind") + "\n" +
                  "  yacoind [options] help                " + _("List commands") + "\n" +
                  "  yacoind [options] help <command>      " + _("Get help for a command") + "\n";

            strUsage += "\n" + HelpMessage();

            fprintf(stdout, "%s", strUsage.c_str());
#ifdef _MSC_VER
            fRet = false;
            //Shutdown(NULL);
#else            
            exit(0);
#endif
        }
        else
        {
            bool 
                fCommandLine = false;
            // Command-line RPC
            for (int i = 1; i < argc; ++i)
            {
                if (!IsSwitchChar(argv[i][0]) && !boost::algorithm::istarts_with(argv[i], "yacoin:"))
                {
                    fCommandLine = true;
                }
            }
            if (fCommandLine)
            {
                int ret = CommandLineRPC(argc, argv);
#ifdef _MSC_VER
                if( 0 == ret )  // signifies a successful RPC call
                {
                    fRet = false;
                }
#else
                exit(ret);
#endif
            }
            else
                fRet = AppInit2();
        }
    }
    catch(std::exception& e) 
    {
        PrintException(&e, "AppInit()");
    } 
    catch(...)
    {
        PrintException(NULL, "AppInit()");
    }
    if (!fRet)
        Shutdown(NULL);
    return fRet;
}

extern void noui_connect();
int main(int argc, char* argv[])
{
    bool fRet = false;

    // Connect yacoind signal handlers
    noui_connect();

    fRet = AppInit(argc, argv);

    if (fRet && fDaemon)
        return 0;

    return 1;
}
#endif

bool static InitError(const std::string &str)
{
    uiInterface.ThreadSafeMessageBox(str, _("Yacoin"), CClientUIInterface::OK | CClientUIInterface::MODAL);
    return false;
}

bool static InitWarning(const std::string &str)
{
    uiInterface.ThreadSafeMessageBox(str, _("Yacoin"), CClientUIInterface::OK | CClientUIInterface::ICON_EXCLAMATION | CClientUIInterface::MODAL);
    return true;
}


bool static Bind(const CService &addr, bool fError = true) 
{
    if (IsLimited(addr))
        return false;

    std::string <commit_msg>Fix shutdown rpc (#9)<commit_after>// Copyright (c) 2009-2010 <NAME>
// Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifdef _MSC_VER
    #include <stdint.h>

    #include <stdio.h>
    #include "msvc_warnings.push.h"
#else
    #ifndef BITCOIN_UTIL_H
        #include "util.h"
    #endif
#endif

#ifndef BITCOIN_TXDB_H
 #include "txdb.h"
#endif

#ifndef _BITCOINRPC_H_
 #include "bitcoinrpc.h"
#endif

#ifndef BITCOIN_INIT_H
 #include "init.h"
#endif

#include <boost/format.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/filesystem/convenience.hpp>
#include <boost/interprocess/sync/file_lock.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <openssl/crypto.h>

#ifndef WIN32
#include <signal.h>
#endif

bool fNewerOpenSSL = false; // for key.cpp's benefit


using namespace boost;

using std::string;
using std::max;
using std::map;

CWallet* pwalletMain;
CClientUIInterface uiInterface;
std::string strWalletFileName;
bool fConfChange;
unsigned int nNodeLifespan;
unsigned int nMinerSleep;
bool fUseFastIndex;
bool fUseFastStakeMiner;
bool fUseMemoryLog;
enum Checkpoints::CPMode CheckpointsMode;

// Ping and address broadcast intervals
extern ::int64_t nPingInterval;
extern ::int64_t nBroadcastInterval;

//////////////////////////////////////////////////////////////////////////////
//
// Shutdown
//

void ExitTimeout(void* parg)
{
#ifdef WIN32
  //Sleep(5000);
    Sleep(2 * 1000);
//    ExitProcess(0);
#endif
}

#ifndef TESTS_ENABLED
void StartShutdown()
{
#ifdef QT_GUI
    // ensure we leave the Qt main loop for a clean GUI exit (Shutdown() is called in bitcoin.cpp afterwards)
    uiInterface.QueueShutdown();
#else
    // Without UI, Shutdown() can simply be started in a new thread
    NewThread(Shutdown, NULL);
#endif
}
static bool 
    fExit;

void Shutdown(void* parg)
{
    if (fDebug)
        printf("Shutdown : In progress...\n");
    
    static CCriticalSection 
        cs_Shutdown;

    static bool 
        fTaken;

    // Make this thread recognisable as the shutdown thread
    RenameThread("yacoin-shutoff");

    bool 
        fFirstThread = false;
    {
        TRY_LOCK(cs_Shutdown, lockShutdown);
        if (lockShutdown)
        {
            fFirstThread = !fTaken;
            fTaken = true;
        }
    }
    if (fFirstThread)
    {
        fShutdown = true;
        fRequestShutdown = true;
        ++nTransactionsUpdated;
//        CTxDB().Close();
        bitdb.Flush(false);
        StopNode();
        {
            LOCK(cs_main);
            if (pwalletMain)
                pwalletMain->SetBestChain(CBlockLocator(pindexBest));
        }
        bitdb.Flush(true);
#if !defined(WIN32) && !defined(QT_GUI)
    if (fDaemon)
    {
        boost::filesystem::remove(GetPidFile());
    }
#endif
        UnregisterWallet(pwalletMain);
        delete pwalletMain;
        NewThread(ExitTimeout, NULL);
        Sleep(50);
        if (fDebug)
            printf("Yacoin exited\n\n");
        fExit = true;
#ifndef QT_GUI
        // ensure non-UI client gets exited here, but let yacoin-qt reach 'return 0;' in bitcoin.cpp
    #ifdef _MSC_VER
        return;
    #else
        exit(0);
    #endif        
#endif
    }
    else
    {
        while (!fExit)
            Sleep(500);
        Sleep(100);
        ExitThread(0);
    }
}
#endif

void HandleSIGTERM(int)
{
    fRequestShutdown = true;
}
#ifdef WIN32
//_____________________________________________________________________________
// this works for Windows gcc & MSVC++
static int WindowsHandleSigterm( unsigned long the_signal )
    {
    bool
        fIWillHandleIt = false;

    switch( the_signal )
        {
        case CTRL_C_EVENT:          //A CTRL+c signal was received,
            //either from keyboard input
            //or from a signal generated by the GenerateConsoleCtrlEvent function

        case CTRL_BREAK_EVENT:      //A CTRL+BREAK signal was received,
            //either from keyboard input
            //or from a signal generated by the GenerateConsoleCtrlEvent function

        case CTRL_LOGOFF_EVENT:     //A signal that the system sends to all console
            // processes when a user is logging off. This signal does not 
            // indicate which user is logging off, so no assumptions can be made.

        case CTRL_SHUTDOWN_EVENT:   // a system shutdown has occured
            HandleSIGTERM( ( int )the_signal );
            fIWillHandleIt = true;  // tell Windows we will take care of this
            break;      // It may not listen, but we will shutdown in any event

        case CTRL_CLOSE_EVENT:      // A signal that the system sends to all processes
            // attached to a console when the user closes
            // the console (either by choosing the Close
            // command from the console window's System menu,
            // or by choosing the End Task command from the Task List).
            HandleSIGTERM( ( int )the_signal );
            fIWillHandleIt = true;  // tell Windows we will take care of this
            // not on WIndows > XP :(
            // so can we hang here? Perhaps
            while( true )
            {
                Sleep( 1000 );
            }
            break;      // It may not listen, but we will shutdown in any event

        default:                    // any other (strange) signal we pass on
            break;                  // and just let it happen?
        }
    return fIWillHandleIt;
    }
//_____________________________________________________________________________
#endif
void HandleSIGHUP(int)
{
    fReopenDebugLog = true;
}





//////////////////////////////////////////////////////////////////////////////
//
// Start
//
#if !defined(QT_GUI) && !defined(TESTS_ENABLED)
bool AppInit(int argc, char* argv[])
{
    bool fRet = false;
    try
    {
        //
        // Parameters
        //
        // If Qt is used, parameters/bitcoin.conf are parsed in qt/bitcoin.cpp's main()
        ParseParameters(argc, argv);
        bool 
            fTest_or_Main_Net_is_decided = false;

        if (!boost::filesystem::is_directory(GetDataDir(fTest_or_Main_Net_is_decided)))
        {
            fprintf(stderr, "Error: Specified directory does not exist\n");
            Shutdown(NULL);
        }
        ReadConfigFile(mapArgs, mapMultiArgs);  // now two things have happened:
                                                // testnet/mainnet has been decided, and
                                                // the 'data directory' has been set
                                                // either by command line arguments or in
                                                // the configuration file.
                                                // this means that fTestNet should be tested 
                                                // first, before GetDataDir() is called next
                                                
                                                // this is documentation!

        if(mapArgs.count("--version") || mapArgs.count("-v")){
            std::string msg = "Yacoin version: " + FormatFullVersion() + "\n\n";
            fprintf(stdout, "%s", msg.c_str());
            exit(0);
        } else if (mapArgs.count("-?") || mapArgs.count("-h") || mapArgs.count("--help"))
        {
            // First part of help message is specific to yacoind / RPC client
            std::string strUsage = _("Yacoin version") + " " + FormatFullVersion() + "\n\n" +
                _("Usage:") + "\n" +
                  "  yacoind [options]                     " + "\n" +
                  "  yacoind [options] <command> [params]  " + _("Send command to -server or yacoind") + "\n" +
                  "  yacoind [options] help                " + _("List commands") + "\n" +
                  "  yacoind [options] help <command>      " + _("Get help for a command") + "\n";

            strUsage += "\n" + HelpMessage();

            fprintf(stdout, "%s", strUsage.c_str());
#ifdef _MSC_VER
            fRet = false;
            //Shutdown(NULL);
#else            
            exit(0);
#endif
        }
        else
        {
            bool 
                fCommandLine = false;
            // Command-line RPC
            for (int i = 1; i < argc; ++i)
            {
                if (!IsSwitchChar(argv[i][0]) && !boost::algorithm::istarts_with(argv[i], "yacoin:"))
                {
                    fCommandLine = true;
                }
            }
            if (fCommandLine)
            {
                int ret = CommandLineRPC(argc, argv);
#ifdef _MSC_VER
                if( 0 == ret )  // signifies a successful RPC call
                {
                    fRet = false;
                }
#else
                exit(ret);
#endif
            }
            else
                fRet = AppInit2();
        }
    }
    catch(std::exception& e) 
    {
        PrintException(&e, "AppInit()");
    } 
    catch(...)
    {
        PrintException(NULL, "AppInit()");
    }
    if (!fRet)
        Shutdown(NULL);
    return fRet;
}

extern void noui_connect();
int main(int argc, char* argv[])
{
    bool fRet = false;

    // Connect yacoind signal handlers
    noui_connect();

    fRet = AppInit(argc, argv);

    if (fRet)
        return 0;

    return 1;
}
#endif

bool static InitError(const std::string &str)
{
    uiInterface.ThreadSafeMessageBox(str, _("Yacoin"), CClientUIInterface::OK | CClientUIInterface::MODAL);
    return false;
}

bool static InitWarning(const std::string &str)
{
    uiInterface.ThreadSafeMessageBox(str, _("Yacoin"), CClientUIInterface::OK | CClientUIInterface::ICON_EXCLAMATION | CClientUIInterface::MODAL);
    return true;
}


bool static Bind(const CService &addr, bool fError = true) 
{
    if (IsLimited(addr))
        return false;

    std::string 
{'fraction_non_alphanumeric': 0.11743201963042717, 'fraction_numerical': 0.0063598577795583155, 'mean_word_length': 1.7567642186637218, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 32, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1620228', 'n_tokens_mistral': 5844, 'n_tokens_neox': 5568, 'n_words': 1578}