tripwire-open-source/src/tw/twinit.cpp

348 lines
12 KiB
C++

//
// The developer of the original code and/or files is Tripwire, Inc.
// Portions created by Tripwire, Inc. are copyright (C) 2000-2017 Tripwire,
// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights
// reserved.
//
// This program is free software. The contents of this file are subject
// to the terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2 of the License, or (at your
// option) any later version. You may redistribute it and/or modify it
// only in compliance with the GNU General Public License.
//
// This program is distributed in the hope that it will be useful.
// However, this program is distributed AS-IS WITHOUT ANY
// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS
// FOR A PARTICULAR PURPOSE. Please see the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
//
// Nothing in the GNU General Public License or any other license to use
// the code or files shall permit you to use Tripwire's trademarks,
// service marks, or other intellectual property without Tripwire's
// prior written consent.
//
// If you have any questions, please contact Tripwire, Inc. at either
// info@tripwire.org or www.tripwire.org.
//
///////////////////////////////////////////////////////////////////////////////
// twinit.cpp
//
// cTWInit -- initializes global objects for tw executables
//
#include "stdtw.h"
#include "twinit.h"
#include "fco/genreswitcher.h"
#include "core/fsservices.h"
#include "core/usernotifystdout.h"
#include "core/errorbucketimpl.h"
#include "core/timeconvert.h"
#include "fco/fconame.h"
#include "tw/systeminfo.h"
#include "core/twlocale.h"
#include "core/codeconvert.h"
//////////////////
// the headers for objects we will need to register in RegisterAllSerializable() below.
#include "core/serializerimpl.h"
#include "fs/fsobject.h"
#include "fco/fcospecimpl.h"
#include "fco/fconame.h"
#include "tw/fcoreport.h"
#include "fco/fcosetimpl.h"
#include "fco/fcospechelper.h"
#include "fco/fcospecattr.h"
#include "fs/fspropdisplayer.h"
#include "tw/fcodatabasefile.h"
#include "core/fileheader.h"
#include "core/serstring.h"
#include "tw/headerinfo.h"
#include "fs/fspropset.h"
/////////////////
// Used for package initialization
//
#include "core/package.h"
#include "tw/tw.h"
#include "fco/fconame.h"
#include "fs/fs.h" // object initialization
#include "core/unixfsservices.h"
#include "core/tw_signal.h" // to ignore SIGPIPE
#if IS_AROS
#include <errno.h>
#include <proto/exec.h>
#include <proto/bsdsocket.h>
#include <bsdsocket/socketbasetags.h>
static bool aros_socketbase_init();
#endif
//=============================================================================
// cTWInit_i
//=============================================================================
class cTWInit_i
{
public:
cTWInit_i();
~cTWInit_i();
// both shouldn't throw exceptions
iFSServices* pFSServices;
cUserNotifyStdout unStdout;
cErrorTracer et;
cErrorReporter er;
};
cTWInit_i::cTWInit_i()
: pFSServices( NULL )
{
// package initialization
//
TSS_Dependency( cFS );
}
cTWInit_i::~cTWInit_i()
{
delete pFSServices;
}
///////////////////////////////////////////////////////////////////////////////
// RegisterAllSerializable() -- Register all serializable objects
///////////////////////////////////////////////////////////////////////////////
static void RegisterAllSerializable()
{
// Reference count objects
cSerializerImpl::RegisterSerializableRefCt (CLASS_TYPE(cFSObject), cFSObject::Create);
cSerializerImpl::RegisterSerializableRefCt (CLASS_TYPE(cFCOSpecImpl), cFCOSpecImpl::Create);
cSerializerImpl::RegisterSerializableRefCt (CLASS_TYPE(cFCOSpecAttr), cFCOSpecAttr::Create);
// Non-reference count objects
cSerializerImpl::RegisterSerializable (CLASS_TYPE(cFCODatabaseFile), cFCODatabaseFile::Create);
cSerializerImpl::RegisterSerializable (CLASS_TYPE(cErrorQueue), cErrorQueue::Create);
cSerializerImpl::RegisterSerializable (CLASS_TYPE(cFCOName), cFCOName::Create);
cSerializerImpl::RegisterSerializable (CLASS_TYPE(cFCOReport), cFCOReport::Create);
cSerializerImpl::RegisterSerializable (CLASS_TYPE(cFCOSetImpl), cFCOSetImpl::Create);
cSerializerImpl::RegisterSerializable (CLASS_TYPE(cFCOSpecStopPointSet), cFCOSpecStopPointSet::Create);
cSerializerImpl::RegisterSerializable (CLASS_TYPE(cFCOSpecNoChildren), cFCOSpecNoChildren::Create);
cSerializerImpl::RegisterSerializable (CLASS_TYPE(cSerializableNString), cSerializableNString::Create);
cSerializerImpl::RegisterSerializable (CLASS_TYPE(cSerializableWString), cSerializableWString::Create);
cSerializerImpl::RegisterSerializable (CLASS_TYPE(cHeaderInfo), cHeaderInfo::Create);
cSerializerImpl::RegisterSerializable (CLASS_TYPE(cFCODbHeader), cFCODbHeader::Create);
cSerializerImpl::RegisterSerializable (CLASS_TYPE(cFCOReportHeader), cFCOReportHeader::Create);
cSerializerImpl::RegisterSerializable (CLASS_TYPE(cFSPropSet), cFSPropSet::Create);
// prop displayers
cSerializerImpl::RegisterSerializable (CLASS_TYPE(cFSPropDisplayer), cFSPropDisplayer::Create);
}
///////////////////////////////////////////////////////////////////////////////
// SetExeDir
///////////////////////////////////////////////////////////////////////////////
static bool SetExeDir( const TSTRING& strArgv0 )
{
ASSERT( ! strArgv0.empty() );
// record executable directory
TSTRING strFullPath;
if( iFSServices::GetInstance()->GetExecutableFilename( strFullPath, strArgv0 ) && !strFullPath.empty() )
{
#if USES_DEVICE_PATH
strFullPath = cDevicePath::AsPosix(strFullPath);
#endif
cSystemInfo::SetExePath(strFullPath);
TSTRING::size_type s = strFullPath.find_last_of( _T('/') );
// paths will always come back from GetExecutableFilename delimited with a forward slash
ASSERT( TSTRING::npos != s );
if( TSTRING::npos != s )
strFullPath.resize( s );
cSystemInfo::SetExeDir(strFullPath);
}
else // error
{
ASSERT( false );
cSystemInfo::SetExeDir(_T(""));
return false;
}
return true;
}
///////////////////////////////////////////////////////////////////////////////
// ctor
///////////////////////////////////////////////////////////////////////////////
cTWInit::cTWInit()
{
mpData = new cTWInit_i();
}
///////////////////////////////////////////////////////////////////////////////
// dtor
///////////////////////////////////////////////////////////////////////////////
cTWInit::~cTWInit()
{
delete mpData;
//
// clear out the fco name tbl
// this helps the mem leak quest...
//
cFCOName::ClearNameTable();
}
///////////////////////////////////////////////////////////////////////////////
// Init
///////////////////////////////////////////////////////////////////////////////
void cTWInit::Init( const TSTRING& strArgv0 )
{
// package initialization...
//
TSS_Dependency( cTW ); // initialize all packages on program startup (exes
// should call this function (cTWInit::Init) on startup
// we require 8-bit bytes for some functionality
ASSERT( sizeof( byte ) == sizeof( uint8 ) );
//
// set debug level
// NOTE:BAM -- this is also being set in cCore::cCore() because
// things in that constructor need to have a debug output as well.
// so this code here is redundant.
//
cDebug::SetDebugLevel( cDebug::D_DEBUG );
cDebug::AddOutTarget( cDebug::OUT_STDOUT );
// ------------------------------------------------------------
// BEG:RAD -- Does not belong here, moved to cCore::cCore!
// ------------------------------------------------------------
//
// initialize locale
//
// cTWLocale::InitGlobalLocale();
// ------------------------------------------------------------
// END:RAD
// ------------------------------------------------------------
// ------------------------------------------------------------
// BEG:RAD -- Does not belong here, moved to cCore::cCore!
// ------------------------------------------------------------
// initialize code converter ( inits itself on creation,
// but initializing it here lets us see any errors immediately )
//
// iCodeConverter::GetInstance();
// ------------------------------------------------------------
// END:RAD
// ------------------------------------------------------------
#if IS_AROS
aros_socketbase_init();
#endif
//
// set up the file system services
//
mpData->pFSServices = new cUnixFSServices;
ASSERT( mpData->pFSServices != 0 );
iFSServices::SetInstance( mpData->pFSServices );
//
// save directory in which this executable resides
//
SetExeDir( strArgv0 );
//
// save current time
//
cSystemInfo::SetExeStartTime( cTimeUtil::GetTime() );
// assure that a default genre has been set and...
ASSERT( cGenre::GENRE_INVALID != cGenreSwitcher::GetInstance()->GetDefaultGenre() );
// ...switch to it
cGenreSwitcher::GetInstance()->SelectGenre( cGenreSwitcher::GetInstance()->GetDefaultGenre() );
// initialize iUserNotify
iUserNotify::SetInstance( &mpData->unStdout );
iUserNotify::GetInstance()->SetVerboseLevel(iUserNotify::V_NORMAL);
// register serializable objects
RegisterAllSerializable();
// set up an error bucket that will spit things to stderr
mpData->et.SetChild( &mpData->er );
errorQueue.SetChild( &mpData->et );
#if SUPPORTS_POSIX_SIGNALS
// ignore SIGPIPE
tw_sigign(SIGPIPE); //TODO: somebody add comment here!
// We'll install handlers for each signal that would cause a core dump.
// the disposition will still be to exit, just without producing a core file.
// I'll emit an error statement that indicates the interrupt before the exit
// call.
tw_HandleSignal( SIGBUS ); // Handle Bus error signals without dumping core...
tw_HandleSignal( SIGSEGV ); // Segmentation fault
tw_HandleSignal( SIGQUIT ); // Quit signal - issued from terminal (CTRL-\)
tw_HandleSignal( SIGILL ); // Illegal instruction - probably won't be an issue.
#ifndef DEBUG
tw_HandleSignal( SIGTRAP ); // We don't want to mess up the debugger in debug builds...
#endif
tw_HandleSignal( SIGABRT ); // Supposedly we can only get this signal by calling abort()
// ourselves, but to be on the safe side...
#ifdef SIGEMT
tw_HandleSignal( SIGEMT ); // Emulator trap.
#endif
#ifdef SIGSYS
tw_HandleSignal( SIGSYS ); // Bad system call.
#endif
tw_HandleSignal( SIGFPE ); // Floating point exception.
#ifdef SIGXCPU
tw_HandleSignal( SIGXCPU ); // CPU time exceeded. Might very well be an issue for us.
#endif
#ifdef SIGXFSZ
tw_HandleSignal( SIGXFSZ ); // File size limit exceeded.
#endif
#endif
}
#if IS_AROS
struct Library* SocketBase=0;
bool aros_socketbase_init()
{
if (!(SocketBase = OpenLibrary("bsdsocket.library", 4)))
{
printf("Failed to load socket library");
return 0;
}
if (SocketBaseTags(
SBTM_SETVAL(SBTC_ERRNOPTR(sizeof(errno))), (IPTR)&errno,
SBTM_SETVAL(SBTC_HERRNOLONGPTR), (IPTR)&errno,
TAG_DONE))
{
printf("Failed to init socket library");
return 0;
}
return 1;
}
#endif