pax_global_header00006660000000000000000000000064114054414750014517gustar00rootroot0000000000000052 comment=f274161f663f1216e81021bd99b84906df8e0ac6 libguytools2-2.0.1/000077500000000000000000000000001140544147500141555ustar00rootroot00000000000000libguytools2-2.0.1/create_version_file.sh000077500000000000000000000003051140544147500205210ustar00rootroot00000000000000#!/bin/bash TOOLS_VERSION=`head -n 1 debian/changelog` TOOLS_VERSION="${TOOLS_VERSION%%)*}" TOOLS_VERSION="${TOOLS_VERSION##*(}" echo "VERSION = ${TOOLS_VERSION%%-*}" >libguytools_version.pro.inc libguytools2-2.0.1/include/000077500000000000000000000000001140544147500156005ustar00rootroot00000000000000libguytools2-2.0.1/include/toolcfg.h000066400000000000000000000175631140544147500174220ustar00rootroot00000000000000// **************************************************************************** // Project: libguytools // **************************************************************************** // Programmer: Guy Voncken // Police Grand-Ducale // Service de Police Judiciaire // Section Nouvelles Technologies // **************************************************************************** // Module: Configuration utility // **************************************************************************** #ifndef __TOOLCFG_H__ #define __TOOLCFG_H__ /* ------------------------------ */ /* Type & structure definitions */ /* ------------------------------ */ typedef enum { CFGTYPE_PRESENCE, CFGTYPE_INTEGER, CFGTYPE_DOUBLE, CFGTYPE_STRING, CFGTYPE_SET, CFGTYPE_HMS, CFGTYPE_NULL } t_ToolCfgType; typedef enum { CFGASN_SOURCE = 0x0000000F, CFGASN_CMD = 0x00000001, CFGASN_CFG = 0x00000002, CFGASN_COUNT = 0x000000F0, CFGASN_ONCE = 0x00000010, CFGASN_TWICE = 0x00000020, CFGASN_MULTIPLE = 0x00000030, CFGASN_OPTIONAL = 0x00000100 } t_ToolCfgAssignment; #define CFGASSIGN_CMD ((t_ToolCfgAssignment)(CFGASN_CMD | CFGASN_MULTIPLE )) #define CFGASSIGN_CFG_ONCE ((t_ToolCfgAssignment)(CFGASN_CFG | CFGASN_ONCE )) #define CFGASSIGN_CFG_MULTIPLE ((t_ToolCfgAssignment)(CFGASN_CFG | CFGASN_MULTIPLE )) #define CFGASSIGN_BOTH_ONCE ((t_ToolCfgAssignment)(CFGASN_CMD | CFGASN_CFG | CFGASN_ONCE )) #define CFGASSIGN_BOTH_TWICE ((t_ToolCfgAssignment)(CFGASN_CMD | CFGASN_CFG | CFGASN_TWICE )) #define CFGASSIGN_BOTH_MULTIPLE ((t_ToolCfgAssignment)(CFGASN_CMD | CFGASN_CFG | CFGASN_MULTIPLE )) #define CFGASSIGN_OPTIONAL ((t_ToolCfgAssignment)(CFGASN_CMD | CFGASN_CFG | CFGASN_MULTIPLE | CFGASN_OPTIONAL)) typedef struct { t_pcchar pSetString; t_int SetValue; } t_ToolCfgSet, *t_pToolCfgSet; typedef struct { t_pcchar pName; /* The last one in the table must have pName set to NULL */ t_ToolCfgType CfgType; long DestAddr; /* For Params: the destination address: For table columns: the offset from the baseaddress */ t_int DestLen; /* for strings, this length DOES NOT include the trailing '\0' */ t_double MinValue; t_double MaxValue; t_pToolCfgSet pSetArray; } t_ToolCfgDataDesc, *t_pToolCfgDataDesc; /* ------------------------------------- */ /* Structure to describe one parameter */ /* ------------------------------------- */ typedef struct _t_ToolCfgParamDesc *t_pToolCfgParamDesc; typedef APIRET (* t_pToolCfgCallOnInitFn)(t_pToolCfgParamDesc pCfgParamDesc, t_pchar *ppErrorText); typedef struct _t_ToolCfgParamDesc { t_ToolCfgAssignment Assign; t_pToolCfgCallOnInitFn pCallOnInitFn; t_ToolCfgDataDesc DataDesc; /* The following two elements will be filled by the configuration scanner CfgScanConfiguration */ /* and do not need to be set by the calling function. */ t_int CmdAssignments; t_int CfgAssignments; } t_ToolCfgParamDesc; #define CFG_FILLUP_FORLINT 0,0 /* ------------------------------- */ /* Structure to describe a table */ /* ------------------------------- */ typedef APIRET (* t_pTableStartFn )(t_pchar pTableName, long *pBaseAddr, t_pcchar *ppErrorText); typedef APIRET (* t_pTableSaveAndNextFn)( long *pBaseAddr, t_pcchar *ppErrorText); typedef APIRET (* t_pTableEndFn )( t_pcchar *ppErrorText); typedef struct { t_pcchar pTableType; t_pTableStartFn pStartFn; t_pTableSaveAndNextFn pSaveAndNextFn; t_pTableEndFn pEndFn; t_pToolCfgDataDesc pDataDescArray; /* Pointer to array of data descriptors (one for each column) */ } t_ToolCfgTableDesc, *t_pToolCfgTableDesc; /* Prototype of the user's logfunction */ typedef void (* t_pToolCfgUserLogFn)(t_pcchar pFileName, t_pcchar pFunction, t_int LineNr, t_pcchar pFormat, va_list pArguments); /* ----------------- */ /* Prototypes */ /* ----------------- */ #ifdef __cplusplus #define EXTERN extern "C" #elif __STDC__ #define EXTERN extern #else #error Unknown C compiler mode #endif EXTERN APIRET ToolCfgInit (int argc, char *argv[]); EXTERN APIRET ToolCfgDeInit (void); EXTERN APIRET ToolCfgUseAdjustedCommandLine (int argc, char *argv[]); EXTERN APIRET ToolCfgSetLogFn (t_pToolCfgUserLogFn pUserLogFn); EXTERN APIRET ToolCfgGetCmdLineOption (t_pcchar pParamName, t_pcchar *ppValue); EXTERN APIRET ToolCfgAddGlobalSectionName (t_pcchar pSectionName); EXTERN APIRET ToolCfgDelGlobalSectionName (t_pcchar pSectionName); EXTERN APIRET ToolCfgScanConfiguration (t_pcchar pFileName, t_pcchar pSectionName, t_ToolCfgParamDesc *pParamDescArray, t_ToolCfgTableDesc *pTableDescArray); EXTERN APIRET ToolCfgBuildTemplate (t_pcchar pFileName, t_pcchar pComment, t_pcchar pSectionName, t_ToolCfgParamDesc *pParamDescArray, t_ToolCfgTableDesc *pTableDescArray); EXTERN APIRET ToolCfgLogConfiguration (t_pToolCfgParamDesc pParamDescArray); EXTERN APIRET ToolCfgPrintParamContents (t_pToolCfgParamDesc pParamDescArray, t_pchar pName, t_pchar pBuff); EXTERN APIRET ToolCfgGetSetString (t_pToolCfgSet pSetArray, int SetValue, const char **ppSetString); /* CfgGetCommandLineOption is usefull to the params that cannot be contained in the configuration file */ /* file itself, as for example the name of the cfg file. */ /* Use CfgScanConfiguration to read a certain section of the cfg file. The two arrays pParamDescArray */ /* and pTableDescArray specify the expected parameters and tables found in the indicated section. */ /* ------------------------------ */ /* Error codes */ /* ------------------------------ */ static const APIRET TOOLCFG_ERROR_OPEN_FAILED = ERROR_BASE_TOOL_CFG + 1; static const APIRET TOOLCFG_ERROR_READ_FAILED = ERROR_BASE_TOOL_CFG + 2; static const APIRET TOOLCFG_ERROR_CLOSE_FAILED = ERROR_BASE_TOOL_CFG + 3; static const APIRET TOOLCFG_ERROR_FILE_NOT_FOUND = ERROR_BASE_TOOL_CFG + 4; static const APIRET TOOLCFG_ERROR_SEEKEND_FAILED = ERROR_BASE_TOOL_CFG + 5; static const APIRET TOOLCFG_ERROR_SEEKSET_FAILED = ERROR_BASE_TOOL_CFG + 6; static const APIRET TOOLCFG_ERROR_INVALID_STATE = ERROR_BASE_TOOL_CFG + 7; static const APIRET TOOLCFG_ERROR_NAME_TOO_LONG = ERROR_BASE_TOOL_CFG + 8; static const APIRET TOOLCFG_ERROR_INCLUDE_NESTING_OVERFLOW = ERROR_BASE_TOOL_CFG + 9; static const APIRET TOOLCFG_ERROR_CONFIG_ERROR = ERROR_BASE_TOOL_CFG + 10; static const APIRET TOOLCFG_ERROR_INVALID_ASSIGNMENT_OPTION = ERROR_BASE_TOOL_CFG + 11; static const APIRET TOOLCFG_ERROR_INVALID_CFGTYPE = ERROR_BASE_TOOL_CFG + 12; static const APIRET TOOLCFG_ERROR_TEMPLATE_OPEN_FAILED = ERROR_BASE_TOOL_CFG + 13; static const APIRET TOOLCFG_ERROR_FPRINTF_FAILED = ERROR_BASE_TOOL_CFG + 14; static const APIRET TOOLCFG_ERROR_CMDLINE_OPTION_NOT_FOUND = ERROR_BASE_TOOL_CFG + 15; static const APIRET TOOLCFG_ERROR_SETBUF_FAILED = ERROR_BASE_TOOL_CFG + 16; static const APIRET TOOLCFG_ERROR_MALLOC_FAILED = ERROR_BASE_TOOL_CFG + 17; static const APIRET TOOLCFG_ERROR_SECTIONNAME_TOO_LONG = ERROR_BASE_TOOL_CFG + 18; static const APIRET TOOLCFG_ERROR_TOO_MANY_SECTIONNAMES = ERROR_BASE_TOOL_CFG + 19; static const APIRET TOOLCFG_ERROR_SECTIONNAME_NOTFOUND = ERROR_BASE_TOOL_CFG + 20; static const APIRET TOOLCFG_ERROR_UNKNOWN_PARAMETER = ERROR_BASE_TOOL_CFG + 21; #endif libguytools2-2.0.1/include/toolconstants.h000066400000000000000000000057361140544147500206760ustar00rootroot00000000000000// **************************************************************************** // Project: libguytools // **************************************************************************** // Programmer: Guy Voncken // Police Grand-Ducale // Service de Police Judiciaire // Section Nouvelles Technologies // **************************************************************************** // Module: Different useful constants // **************************************************************************** #ifndef __TOOLCONSTANTS_H__ #define __TOOLCONSTANTS_H__ /* --------------------------------------------------------------------------------------------- */ /* Attention */ /* This files only defines general, never-changing constants. Do not add application dependant */ /* definitions, such as string lengths, stack sizes etc. */ /* --------------------------------------------------------------------------------------------- */ /* ---------------- */ /* Time constants */ /* ---------------- */ #define MSEC_PER_SECOND 1000 #define USEC_PER_MSEC 1000 #define SECONDS_PER_DAY 86400 #define SECONDS_PER_HOUR 3600 #define SECONDS_PER_MINUTE 60 #define MSEC_PER_DAY (MS_PER_S * S_PER_DAY ) #define MSEC_PER_HOUR (MS_PER_S * S_PER_HOUR ) #define MSEC_PER_MINUTE (MS_PER_S * S_PER_MINUTE) #define DAYS_PER_WEEK 7 #define SECONDS_PER_WEEK (DAYS_PER_WEEK*SECONDS_PER_DAY) #define DAYS_PER_YEAR 365 // Attention, this is of #define SECONDS_PER_YEAR (SECONDS_PER_DAY * DAYS_PER_YEAR) // course just an estimation #define MONTHS_PER_YEAR 12 /* ---------------------- */ /* Weights and measures */ /* ---------------------- */ static const double LBS_PER_KG = 2.204623; static const double MM_PER_INCH = 25.4; #define UM_PER_M 1000000 #define UM_PER_MM 1000 #define MM_PER_M 1000 /* ---------------------- */ /* Mathematics */ /* ---------------------- */ static const double PI = 3.141592654; /* ---------------------- */ /* Computer stuff */ /* ---------------------- */ #define BYTES_PER_KILOBYTE 1024 #define BYTES_PER_MEGABYTE 1048576 #define CLIB_YEAROFFSET 1900 // Fixed year offset for struct tm (by ANSI) #define TCPIP_ADDRESS_LEN 15 // Address format: XXX.XXX.XXX.XXX -> 15 -- do not forget to add +1 if using C strings #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif /* ------------------ */ /* ASCII characters */ /* ------------------ */ static const char ASCII_ESC = 27; static const char ASCII_BS = 0x08; static const char ASCII_LF = 0x0A; static const char ASCII_CR = 0x0D; static const char ASCII_ENTER = ASCII_CR; static const char ASCII_EOF = 0x1A; #endif libguytools2-2.0.1/include/toolerror.h000066400000000000000000000073371140544147500200120ustar00rootroot00000000000000// **************************************************************************** // Project: libguytools // **************************************************************************** // Programmer: Guy Voncken // Police Grand-Ducale // Service de Police Judiciaire // Section Nouvelles Technologies // **************************************************************************** // Module: Error handling // **************************************************************************** #ifndef __TOOLERROR_H__ #define __TOOLERROR_H__ #ifndef __FFL__ #define __FFL__ (char *) __FILE__, (char *)__FUNCTION__, __LINE__ #endif // ----------- // Constants // ----------- #define NO_ERROR 0 // --------------------------------------- // Macros for comfortable error checking // --------------------------------------- #define CHK(Func) \ /*lint -save -e506 -e774*/ /*Warning 506: Constant value Boolean; Info 774: Boolean within 'if' always evaluates to True */ \ { \ APIRET ec; \ if ((ec = Func) != NO_ERROR) \ { \ (void)ToolErrorCheck (__FFL__, ec); \ return ec; \ } \ } \ /*lint -restore*/ #define CHK_CONST(ec) \ { \ (void)ToolErrorCheck (__FFL__, ec); \ return ec; \ } \ #define CHK_RET(Func) \ { \ APIRET ec; \ if ((ec = Func) != NO_ERROR) \ return ec; \ } #define CHK_NORET(Func) \ { \ APIRET ec; \ if ((ec = Func) != NO_ERROR) \ (void)ToolErrorCheck (__FFL__, ec); \ } #define TOOL_CHK(Fn) \ { \ APIRET ec; \ if ((ec=Fn) != NO_ERROR) \ return ec; \ } // ------------------ // Type definitions // ------------------ typedef long APIRET; typedef long * pAPIRET; // ----------------------------- // ToolError's own error codes // ----------------------------- enum { TOOL_ERROR_ENTRY_NOT_FOUND = ERROR_BASE_TOOL_ERROR + 1, TOOL_ERROR_DUPLICATE_ENTRY , TOOL_ERROR_NOT_INITIALISED , TOOL_ERROR_ALREADY_INITIALISED }; // ------------------------------- // Prototypes and wrapper macros // ------------------------------- typedef void (* t_pToolErrorLogFn)(const char *pFileName, const char *pFunctionName, int LineNr, const char *pFormat, va_list pArguments); APIRET ToolErrorSetLogFn (t_pToolErrorLogFn pLogFn); APIRET ToolErrorRegisterError (int ErrorCode, const char *pErrorMsg); APIRET ToolErrorGetMessage (int ErrorCode, const char **ppMessage); const char *ToolErrorMessage (int ErrorCode); const char *ToolErrorTranslateErrno (int Errno); APIRET ToolErrorInit (int MaxErrors); APIRET ToolErrorDeInit (void); APIRET ToolErrorCheck (char const *pFileName, char const *pFunctionName, int LineNr, int ErrorCode); APIRET ToolErrorLog (char const *pFileName, char const *pFunctionName, int LineNr, const char * pFormat, ...) __attribute__ ((format (printf, 4, 5))); #define TOOL_ERROR_REGISTER_CODE(ErrorCode) ToolErrorRegisterError(ErrorCode, #ErrorCode) #endif libguytools2-2.0.1/include/toolglobalid.h000066400000000000000000000047641140544147500204370ustar00rootroot00000000000000// **************************************************************************** // Project: libguytools // **************************************************************************** // Programmer: Guy Voncken // Police Grand-Ducale // Service de Police Judiciaire // Section Nouvelles Technologies // **************************************************************************** // Module: Unique IDs for tools and applications // **************************************************************************** #ifndef __TOOLGLOBALID_H__ #define __TOOLGLOBALID_H__ /* ------------------------------- */ /* Constants */ /* ------------------------------- */ /* ------------------------------- */ /* Base id's */ /* ------------------------------- */ const unsigned int ID_BASE = 0; const unsigned int ID_OFFSET_PROJECT =10000000; /* 100 projects */ const unsigned int ID_OFFSET_SUBPROJECT = 100000; /* 100 subprojects */ const unsigned int ID_OFFSET_SUBSUBPROJECT = 1000; /* 1st possibility -- 100 subsubprojects (=100 C-files with max. 1000 IDs) */ const unsigned int ID_OFFSET_SUBSUBSUBPROJECT = 100; /* 2nd possibility -- 100 subsubprojects (=100 subdir's) */ /* each of the 100 subsubprojects has max. 10 subsubsubprojects (=10 C-files with max. 100 IDs) */ #define CREATE_BASE_ID(ProjectName, x) \ const unsigned int ID_BASE_ ## ProjectName = x; #define CREATE_IDS(ModulName, x) \ const int ERROR_BASE_ ## ModulName = x; \ const int MEMID_BASE_ ## ModulName = x; /* ========================== TOOLS ================================ */ CREATE_BASE_ID (TOOLS, ID_BASE + 0*ID_OFFSET_PROJECT) CREATE_IDS (TOOL_CFG , ID_BASE_TOOLS + 0*ID_OFFSET_SUBPROJECT) CREATE_IDS (TOOL_ERROR , ID_BASE_TOOLS + 1*ID_OFFSET_SUBPROJECT) CREATE_IDS (TOOL_LOG , ID_BASE_TOOLS + 2*ID_OFFSET_SUBPROJECT) CREATE_IDS (TOOL_SIGNAL , ID_BASE_TOOLS + 3*ID_OFFSET_SUBPROJECT) CREATE_IDS (TOOL_SYSINFO , ID_BASE_TOOLS + 4*ID_OFFSET_SUBPROJECT) /* ========================= GUYMAGER ============================== */ CREATE_BASE_ID (GUYMAGER, ID_BASE + 1*ID_OFFSET_PROJECT) CREATE_IDS (GUYMAGER_MAIN , ID_BASE_GUYMAGER + 0*ID_OFFSET_SUBPROJECT) #endif libguytools2-2.0.1/include/toollog.h000066400000000000000000000042211140544147500174270ustar00rootroot00000000000000// **************************************************************************** // Project: libguytools // **************************************************************************** // Programmer: Guy Voncken // Police Grand-Ducale // Service de Police Judiciaire // Section Nouvelles Technologies // **************************************************************************** // Module: Log utility // **************************************************************************** #ifndef __LOG_H__ #define __LOG_H__ class t_Log { public: typedef enum { Debug=0, Info, Error, Entries // must always be the last element in the list } t_Level; t_Log (const char* pFileName, APIRET &rc); ~t_Log (void); static bool IsInitialised (void); static void GetLibGuyToolsVersion (const char **pVersion); static void vEntry (t_Level Level, const char *pFileName, const char *pFunctionName, int LineNr, const char *pFormat, va_list pArguments); static void Entry (t_Level Level, const char *pFileName, const char *pFunctionName, int LineNr, const char *pFormat, ...) __attribute__ ((format (printf, 5, 6))); static void vEntryDebug (const char *pFileName, const char *pFunctionName, int LineNr, const char *pFormat, va_list pArguments); static void vEntryInfo (const char *pFileName, const char *pFunctionName, int LineNr, const char *pFormat, va_list pArguments); static void vEntryError (const char *pFileName, const char *pFunctionName, int LineNr, const char *pFormat, va_list pArguments); #define LOG_DEBUG(...) t_Log::Entry (t_Log::Debug, __FFL__, __VA_ARGS__); #define LOG_INFO(...) t_Log::Entry (t_Log::Info , __FFL__, __VA_ARGS__); #define LOG_ERROR(...) t_Log::Entry (t_Log::Error, __FFL__, __VA_ARGS__); // Possible error codes // -------------------- static const APIRET TOOLLOG_ERROR_INITIALISED_TWICE = ERROR_BASE_TOOL_LOG + 1; static const APIRET TOOLLOG_ERROR_HOSTNAME_TOO_LONG = ERROR_BASE_TOOL_LOG + 2; }; #endif libguytools2-2.0.1/include/toolsignal.h000066400000000000000000000051031140544147500201230ustar00rootroot00000000000000// **************************************************************************** // Project: libguytools // **************************************************************************** // Programmer: Guy Voncken // Police Grand-Ducale // Service de Police Judiciaire // Section Nouvelles Technologies // **************************************************************************** // Module: Signal handler with backtrace // **************************************************************************** #ifndef __TOOLSIGNAL_H__ #define __TOOLSIGNAL_H__ // Description of module ToolSignal // -------------------------------- // This module does all the standard signal handling work for an application. When catching a standard // signal (Kill, Hup, Break...) it calls the function that has been indicated in param pFnLog. // If ever a segment violation occurs, a stack trace is done in order to log the function call sequence // before exiting the program. // // All logging is done via the function indicated in param pFnLog. If that one is NULL, the module writes // its log outputs to stdout. Its first parameter (Error) indicates whether a normal log output (info) or // whether an error log entry should be done. // // It might be important to know for the application, that ToolSignalInit starts a new thread. The function // indicated in param pFnSig is called from that thread, if pFnSig is not NULL. The ID of the new thread is // written to where pThreadId points, if pThreadId is not NULL. typedef void (* t_pToolSignalLogFn )(bool Error, int ThreadNr, const char *pFileName, const char *pFunction, int LineNr, const char *pFormat, va_list pArguments); typedef void (* t_pToolSignalHandler)(int Signal); int ToolSignalInit (t_pToolSignalLogFn pFnLog, t_pToolSignalHandler pFnSig, int *pThreadId); int ToolSignalDeInit (void); // class t_ToolSignal: public QThread // { // public: // t_ToolSignal (int Err, int *pThreadId); // ~t_ToolSignal(); // void run(); // static void BacktraceSignalHandler (int signalHandled, siginfo_t *signalInfo, void *secret); // // static APIRET SetLogFn (t_pToolSignalLogFn pFn); // static APIRET SetSignalHandlerFn (t_pToolSignalHandler pFn); // }; // typedef t_ToolSignal *t_pToolSignal; // ------------------------------- // Error codes // ------------------------------- enum { ERROR_TOOLSIGNAL_ALREADY_INITIALISED = ERROR_BASE_TOOL_SIGNAL + 1, ERROR_TOOLSIGNAL_NOT_INITIALISED, ERROR_TOOLSIGNAL_STARTTHREAD_FAILED }; #endif libguytools2-2.0.1/include/toolsysinfo.h000066400000000000000000000030071140544147500203410ustar00rootroot00000000000000// **************************************************************************** // Project: libguytools // **************************************************************************** // Programmer: Guy Voncken // Police Grand-Ducale // Service de Police Judiciaire // Section Nouvelles Technologies // **************************************************************************** // Module: System information // **************************************************************************** #ifndef __TOOLSYSINFO_H__ #define __TOOLSYSINFO_H__ // ------------------------------ // Constants and Structures // ------------------------------ const int TOOLSYSINFO_MACADDRLEN_VAL = 6; const int TOOLSYSINFO_MACADDRLEN_STR = 2*TOOLSYSINFO_MACADDRLEN_VAL; typedef struct { unsigned char AddrVal [TOOLSYSINFO_MACADDRLEN_VAL ]; char AddrStr [TOOLSYSINFO_MACADDRLEN_STR+1]; } t_ToolSysInfoMacAddr, *t_pToolSysInfoMacAddr; // ------------------------------ // Functions // ------------------------------ APIRET ToolSysInfoGetMacAddr (t_pToolSysInfoMacAddr pMacAddr); APIRET ToolSysInfoUname (QString &Uname); APIRET ToolSysInfoInit (void); APIRET ToolSysInfoDeInit (void); // ------------------------------ // Error codes // ------------------------------ enum { TOOLSYSINFO_ALREADY_INITIALISED = ERROR_BASE_TOOL_SYSINFO + 1, TOOLSYSINFO_ERROR_SOCKET, TOOLSYSINFO_ERROR_NO_ADDR, TOOLSYSINFO_ERROR_UNAME }; #endif libguytools2-2.0.1/include/tooltarget.h000066400000000000000000000003711140544147500201360ustar00rootroot00000000000000/* ------------------------------------------------------------------ */ /* This file specifies the target compilation for the whole TOOLBOX */ /* ------------------------------------------------------------------ */ #define TOOL_MAX_THREADS 500 libguytools2-2.0.1/include/tooltypes.h000066400000000000000000000017111140544147500200130ustar00rootroot00000000000000 #ifndef __TOOLTYPES_H__ #define __TOOLTYPES_H__ #ifndef NO_ERROR #define NO_ERROR 0 #endif // Remember, char, signed char and unsigned char are 3 different types // as stated by ANSI-C, but there are only two representations !!! typedef char t_char; typedef char * t_pchar; typedef const char * t_pcchar; typedef signed char t_schar; typedef signed char * t_pschar; typedef unsigned char t_uchar; typedef unsigned char * t_puchar; typedef short t_short; typedef short * t_pshort; typedef unsigned short t_ushort; typedef unsigned short * t_pushort; typedef int t_int; typedef int * t_pint; typedef unsigned int t_uint; typedef unsigned int * t_puint; typedef void t_void; typedef void * t_pvoid; typedef float t_float; typedef float * t_pfloat; typedef double t_double; typedef double * t_pdouble; #endif libguytools2-2.0.1/toolcfg.cpp000066400000000000000000002560641140544147500163330ustar00rootroot00000000000000// **************************************************************************** // Project: libguytools // **************************************************************************** // Programmer: Guy Voncken // Police Grand-Ducale // Service de Police Judiciaire // Section Nouvelles Technologies // **************************************************************************** // Module: Configuration utility // **************************************************************************** /* ------------------------------ */ /* Includes */ /* ------------------------------ */ #include #include #include #include #include #include #include #include #include #include "tooltypes.h" #include "toolglobalid.h" #include "toolconstants.h" #include "toolerror.h" #include "toolcfg.h" /* ------------------------------ */ /* Constants */ /* ------------------------------ */ const t_char CHAR_LF = 0x0A; const t_char CHAR_CR = 0x0D; const t_char CHAR_EOF = 0x1A; const t_char CHAR_APPEND_LINE = '\\'; const t_char STRING_DELIMITER = '\''; const t_int MAX_CFG_NESTING_LEVEL = 6; /* maximum number of nested INCLUDE directives */ /* reserved keywords */ static t_pcchar KEYWORD_TABLESTART = "TABLE"; static t_pcchar KEYWORD_TABLEEND = "ENDTABLE"; static t_pcchar KEYWORD_SECTIONSTART = "SECTION"; static t_pcchar KEYWORD_SECTIONEND = "ENDSECTION"; static t_pcchar KEYWORD_INCLUDE = "INCLUDE"; static t_pcchar KEYWORD_INCLUDE_OPT = "INCLUDE_OPTIONAL"; static t_pcchar KEYWORD_REMARK = "REM"; static t_pcchar KEYWORD_DEFINE = "DEFINE"; static t_pcchar KEYWORD_UNDEFINE = "UNDEFINE"; // static t_pcchar MINUS_LINE = "------------------------------------------------------------------------------" // "------------------------------------------------------------------------------" // "------------------------------------------------------------------------------"; /* ------------ */ /* Memory IDs */ /* ------------ */ static const t_int MemIdCfgBuffer = MEMID_BASE_TOOL_CFG + 0; static const t_int MemIdCfgErrorHeader = MEMID_BASE_TOOL_CFG + 1; static const t_int MemIdCfgContextStack = MEMID_BASE_TOOL_CFG + 2; static const t_int MemIdCfgTemplateHeader = MEMID_BASE_TOOL_CFG + 3; static const t_int MemIdCfgHelpBuff = MEMID_BASE_TOOL_CFG + 4; static const t_int MemIdCfgHelpString = MEMID_BASE_TOOL_CFG + 5; static const t_int MemIdCfgHelpInt = MEMID_BASE_TOOL_CFG + 6; static const t_int MemIdCfgHelpTable = MEMID_BASE_TOOL_CFG + 7; static const t_int MemIdCfgTableType = MEMID_BASE_TOOL_CFG + 8; static const t_int MemIdCfgTableName = MEMID_BASE_TOOL_CFG + 9; static const t_int MemIdCfgLogConfiguration = MEMID_BASE_TOOL_CFG + 10; /* ------------------------------ */ /* Type & structure definitions */ /* ------------------------------ */ typedef enum { /*! \brief Command line parameter priority */ PRIORITY_HIGH, /*!< Command line parameters have high priority */ PRIORITY_LOW /*!< Command line parameters have low priority */ } t_Priority; typedef enum /*! \brief States for CFG parser state machine */ { CFGSTATE_INCLUDENEWFILE, CFGSTATE_INCLUDENEWFILE_OPT, CFGSTATE_GETNEWLINE, CFGSTATE_CHECKINCLUDE, CFGSTATE_CHECKSECTION, CFGSTATE_LINEREAD, CFGSTATE_COMPLETED, CFGSTATE_CHECKEOF, CFGSTATE_SEARCHSECTIONEND, CFGSTATE_CHECKSECTIONEND } t_ToolCfgState; #define MAX_SECTIONNAME_LEN 63 #define MAX_FILENAME_LEN 4095 #define MAX_SECTIONNAMES 16 #define MAX_GLOBALSECTIONNAMES 16 typedef char t_ToolCfgSectionName[MAX_SECTIONNAME_LEN+1]; typedef struct { t_int BufferLen; t_int ActLineLen; t_int ActLineNr; t_pchar pActLine; t_pchar pBuffer; t_char FileName [MAX_FILENAME_LEN +1]; t_ToolCfgSectionName SectionNameArr[MAX_SECTIONNAMES]; // These section names are only valid during the the scanning of one include file t_int SectionNesting; t_ToolCfgState State; } t_ToolCfgContext, *t_pToolCfgContext; typedef struct { int argc; char **argv; t_Priority Priority; t_pToolCfgUserLogFn pUserLogFn; t_pToolCfgContext pCfgContextStack; t_pToolCfgContext pActCfgContext; t_int IncludeNestingLevel; t_int MaxIncludeNestingLevel; t_char TempFileName[MAX_FILENAME_LEN+1]; t_ToolCfgSectionName GlobalSectionNameArr[MAX_GLOBALSECTIONNAMES]; // These section names remain defined during the whole cfg sanning time } t_ToolCfgLocal; #define max(a,b) (((a) > (b)) ? (a) : (b)) #define min(a,b) (((a) < (b)) ? (a) : (b)) /* ------------------------------ */ /* Variables */ /* ------------------------------ */ t_ToolCfgLocal ToolCfgLocal; /* ------------------------------ */ /* Functions */ /* ------------------------------ */ /* -------------------------------------- */ /* Memory access with / without ToolMem */ /* -------------------------------------- */ #ifdef TOCFG_COMPILE_FOR_USE_WITHOUT_TOOLBOX #define MEM_OPT_NONE 0 #define MEM_REGISTER_MEMID(MemId) NO_ERROR #endif static APIRET ToolCfgMemAlloc (t_pvoid *ppMem, t_uint Size, t_uint Options, t_int MemId) { APIRET rc; #ifdef TOCFG_COMPILE_FOR_USE_WITHOUT_TOOLBOX rc = Options; // To prevent from compiler warning "unused..." rc = MemId; // To prevent from compiler warning "unused..." *ppMem = malloc (Size); if (*ppMem == NULL) rc = TOOLCFG_ERROR_MALLOC_FAILED; else rc = NO_ERROR; #else rc = ToolMemAlloc (ppMem, Size, Options, MemId); #endif return rc; } static APIRET ToolCfgMemFree (t_pvoid pMem, t_int MemId) { APIRET rc; #ifdef TOCFG_COMPILE_FOR_USE_WITHOUT_TOOLBOX rc = MemId; // To prevent from compiler warning "unused..." free (pMem); rc = NO_ERROR; #else rc = ToolMemFree (pMem, MemId); #endif return rc; } /* -------------------- */ /* Error management */ /* -------------------- */ /* Error return values in this module are simply raised to the calling function. */ /* This way, the module CFG does not depend on any log management. */ #define CFG_CHK_APP(Fn) \ { \ APIRET ec; \ \ if ((ec=Fn) != NO_ERROR) \ { \ if (ec != TOOLCFG_ERROR_CONFIG_ERROR) \ (void) ToolCfgLogEntry(__FFL__, "Error %d.", ec); \ return ec; \ } \ } #define CFG_CHK_FPRINTF(Fn) \ { \ if ((Fn) < 1) \ return TOOLCFG_ERROR_FPRINTF_FAILED; \ } static APIRET ToolCfgLogEntry (t_pcchar pFileName, t_pcchar pFunctionName, t_int LineNr, t_pcchar pFormat, ...) { // APIRET rc=1; va_list VaList; va_start(VaList, pFormat); /* VaList points to the argument following pFormat */ if (ToolCfgLocal.pUserLogFn) (*ToolCfgLocal.pUserLogFn)(pFileName, pFunctionName, LineNr, pFormat, VaList); // if (rc) // (void) vfprintf (stderr, pFormat, VaList); va_end(VaList); return NO_ERROR; } static APIRET ToolCfgStdErrorHeader (t_pcchar pActCursor) { t_pToolCfgContext pCfgContext; t_pchar pEndOfLine; t_pchar pBuff; t_int Cursor; t_int LineLen; pCfgContext = ToolCfgLocal.pActCfgContext; if (pCfgContext->FileName[0] == '\0') CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Configuration error in command line. Parameter %d", pCfgContext->ActLineNr)) else CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Configuration error in file %s line %d" , &pCfgContext->FileName[0], pCfgContext->ActLineNr)) if (pCfgContext->pActLine) { pEndOfLine = pCfgContext->pActLine + pCfgContext->ActLineLen; *pEndOfLine = '\0'; CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "[%s]", pCfgContext->pActLine)) } if (pActCursor && pCfgContext->pActLine) { LineLen = (t_int) strlen (pCfgContext->pActLine); Cursor = pActCursor - pCfgContext->pActLine; Cursor = max (Cursor, 0 ); Cursor = min (Cursor, LineLen-1); CFG_CHK_APP (ToolCfgMemAlloc ((void **)&pBuff, (t_uint)(LineLen+3), MEM_OPT_NONE, MemIdCfgErrorHeader)) /* +3 for [ ] and '\0' */ (void) sprintf (pBuff, "[%*s^%*s]", Cursor, "", LineLen-Cursor-1, ""); CFG_CHK_APP (ToolCfgLogEntry(__FFL__, pBuff)) CFG_CHK_APP (ToolCfgMemFree (pBuff, MemIdCfgErrorHeader)) } return NO_ERROR; } /* ------------------------------------- */ /* Utility functions */ /* ------------------------------------- */ static t_int ToolCfgStrCmpNoCase (const char *pStr1, const char *pStr2) { #ifdef _WIN32 return strcmpi (pStr1, pStr2); #else return strcasecmp (pStr1, pStr2); #endif } static t_int ToolCfgStrNCmpNoCase (const char *pStr1, const char *pStr2, t_int Len) { #ifdef _WIN32 return strnicmp (pStr1, pStr2, Len); #else return strncasecmp (pStr1, pStr2, (size_t)Len); #endif } static t_pchar ToolCfgStrMaxCpy (t_pchar pDest, t_pcchar pSrc, t_int DestLen) { if (DestLen == 0) return pDest; pDest[DestLen-1] = '\0'; return strncpy (pDest, pSrc, DestLen-1); } static APIRET ToolCfgCopyName (t_pcchar pSrc, t_pchar pDst, t_int DstLen) { t_int SrcLen; if (pSrc == NULL) pDst[0] = '\0'; else { SrcLen = (t_int)strlen(pSrc); if (SrcLen > DstLen) { CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "SrcLen: %d DstLen: %d", SrcLen, DstLen)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "SrcString: %50.50s", pSrc)) return TOOLCFG_ERROR_NAME_TOO_LONG; } else (void) strcpy (pDst, pSrc); } return NO_ERROR; } static APIRET ToolCfgFindFirstWord (t_pcchar pActLine, const char **ppFirstWord, t_int LineLen, t_pint pRemLineLen) { for ( *ppFirstWord = pActLine; ((**ppFirstWord == ' ') || (**ppFirstWord == '\t')) && (LineLen > 0); ( *ppFirstWord)++, LineLen--) { } if ((LineLen <= 0) || (**ppFirstWord == CHAR_LF) || (**ppFirstWord == CHAR_CR)) *ppFirstWord = NULL; *pRemLineLen = LineLen; return NO_ERROR; } static APIRET ToolCfgCompareKeyWord (t_pcchar pTableKeyWord, t_pchar pCheckKeyWord, t_int LineLen, t_pint pEq, t_pchar *ppNextChar) { t_pchar pNextChar; t_int TableKeyLen; t_int CheckKeyLen; t_pchar pCh; pNextChar = NULL; *pEq = FALSE; TableKeyLen = (t_int) strlen (pTableKeyWord); if (pCheckKeyWord && (LineLen >= TableKeyLen)) { CheckKeyLen = 0; for (pCh = pCheckKeyWord; (*pCh != ' ') && (*pCh != CHAR_CR) && (*pCh != '=') && (*pCh != CHAR_LF) && (*pCh != '\t') && (*pCh != '\0'); pCh++) CheckKeyLen++; if (CheckKeyLen == TableKeyLen) { if (ToolCfgStrNCmpNoCase (pTableKeyWord, pCheckKeyWord, CheckKeyLen) == 0) { pNextChar = &pCheckKeyWord[CheckKeyLen]; *pEq = TRUE; } } } if (ppNextChar) *ppNextChar = pNextChar; return NO_ERROR; } static APIRET ToolCfgGetParamLen (t_pcchar pParam, t_pint pParamLen) { t_int LoopEnd; /* count param len */ *pParamLen = 0; LoopEnd = FALSE; if (*pParam == STRING_DELIMITER) { pParam++; (*pParamLen)++; while (!LoopEnd) { if (*pParam == '\0') LoopEnd = TRUE; else if (*pParam == STRING_DELIMITER) { if (*(pParam+1) == STRING_DELIMITER) { pParam++; (*pParamLen)++; } else { LoopEnd = TRUE; } } if (!LoopEnd) { pParam++; (*pParamLen)++; } } } else { while ((*pParam != ' ') && (*pParam != '\t') && (*pParam != '\0') && (*pParam != CHAR_CR) && (*pParam != CHAR_LF)) { pParam++; (*pParamLen)++; } } if (*pParam == STRING_DELIMITER) /* is there a string end delimiter? */ { pParam++; (*pParamLen)++; } /* was there a param? */ // if ((*pParam == '\0') && (*pParamLen == 0)) if (*pParamLen == 0) { CFG_CHK_APP (ToolCfgStdErrorHeader (pParam-1)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Parameter expected.")) return TOOLCFG_ERROR_CONFIG_ERROR; } return NO_ERROR; } static APIRET ToolCfgCheckIfOnlyOneParam (t_pchar pParam, t_pint pParamLen) { CFG_CHK_APP (ToolCfgGetParamLen (pParam, pParamLen)) pParam += *pParamLen; /* skip trailing spaces */ while (((*pParam == ' ') || (*pParam == '\t')) && (*pParam != '\0')) pParam++; /* is there a second param? */ if (*pParam != '\0') { CFG_CHK_APP (ToolCfgStdErrorHeader (pParam)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "No further parameter expected.")) return TOOLCFG_ERROR_CONFIG_ERROR; } return NO_ERROR; } static APIRET ToolCfgCheckIfNoParam (t_pchar pCh) { while (((*pCh == ' ') || (*pCh == '\t')) && (*pCh != '\0')) pCh++; if (*pCh != '\0') { CFG_CHK_APP (ToolCfgStdErrorHeader (pCh)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "No further parameter expected.")) return TOOLCFG_ERROR_CONFIG_ERROR; } return NO_ERROR; } /* ----------------------------------------------------------------------------------- */ /* Help text builder. It is used to help the user enter the correct parameter values */ /* ----------------------------------------------------------------------------------- */ static APIRET ToolCfgChkStrCpy (t_pchar pDstStr, t_pcchar pSrcStr, t_pint pCumulLen) { if (pDstStr) (void) strcpy (pDstStr + *pCumulLen, pSrcStr); (*pCumulLen) += (t_int)strlen (pSrcStr); return NO_ERROR; } static APIRET ToolCfgBuildHelpHMS(t_pToolCfgDataDesc pCfgDataDesc, t_pchar pHelpBuff, t_pint pHelpBuffLen) { t_pchar pTmp; t_int MinVal; t_int MaxVal; MinVal = (t_int)pCfgDataDesc->MinValue; MaxVal = (t_int)pCfgDataDesc->MaxValue; CFG_CHK_APP (ToolCfgMemAlloc ((void **)&pTmp, 256, MEM_OPT_NONE, MemIdCfgHelpInt)) (void) sprintf (pTmp, "[%02d:%02d:%02d..%02d:%02d:%02d]", MinVal/3600, (MinVal/60)%60, MinVal%60, MaxVal/3600, (MaxVal/60)%60, MaxVal%60); CFG_CHK_APP (ToolCfgChkStrCpy (pHelpBuff, pTmp, pHelpBuffLen)) CFG_CHK_APP (ToolCfgMemFree (pTmp, MemIdCfgHelpInt)) return NO_ERROR; } static APIRET ToolCfgBuildHelpPresence (t_pToolCfgDataDesc /*pCfgDataDesc*/, t_pchar pHelpBuff, t_pint pHelpBuffLen) { t_pcchar pTmp; pTmp = "Optional"; CFG_CHK_APP (ToolCfgChkStrCpy (pHelpBuff, pTmp, pHelpBuffLen)) return NO_ERROR; } static APIRET ToolCfgBuildHelpInteger (t_pToolCfgDataDesc pCfgDataDesc, t_pchar pHelpBuff, t_pint pHelpBuffLen) { t_pchar pTmp; CFG_CHK_APP (ToolCfgMemAlloc ((void **)&pTmp, 256, MEM_OPT_NONE, MemIdCfgHelpInt)) (void) sprintf (pTmp, "[%d..%d] | [0x%X..0x%X]", (t_int)pCfgDataDesc->MinValue, (t_int)pCfgDataDesc->MaxValue, (t_int)pCfgDataDesc->MinValue, (t_int)pCfgDataDesc->MaxValue); CFG_CHK_APP (ToolCfgChkStrCpy (pHelpBuff, pTmp, pHelpBuffLen)) CFG_CHK_APP (ToolCfgMemFree (pTmp, MemIdCfgHelpInt)) return NO_ERROR; } static APIRET ToolCfgBuildHelpDouble (t_pToolCfgDataDesc pCfgDataDesc, t_pchar pHelpBuff, t_pint pHelpBuffLen) { t_pchar pTmp; CFG_CHK_APP (ToolCfgMemAlloc ((void **)&pTmp, 256, MEM_OPT_NONE, MemIdCfgHelpInt)) (void) sprintf (pTmp, "[%G..%G]", pCfgDataDesc->MinValue, pCfgDataDesc->MaxValue); CFG_CHK_APP (ToolCfgChkStrCpy (pHelpBuff, pTmp, pHelpBuffLen)) CFG_CHK_APP (ToolCfgMemFree (pTmp, MemIdCfgHelpInt)) return NO_ERROR; } static APIRET ToolCfgBuildHelpString (t_pToolCfgDataDesc pCfgDataDesc, t_pchar pHelpBuff, t_pint pHelpBuffLen) { t_pchar pTmp; CFG_CHK_APP (ToolCfgMemAlloc ((void **)&pTmp, 256, MEM_OPT_NONE, MemIdCfgHelpString)) (void) sprintf (pTmp, "''", (t_int)pCfgDataDesc->DestLen); CFG_CHK_APP (ToolCfgChkStrCpy (pHelpBuff, pTmp, pHelpBuffLen)) CFG_CHK_APP (ToolCfgMemFree (pTmp, MemIdCfgHelpString)) return NO_ERROR; } static APIRET ToolCfgBuildHelpSet (t_pToolCfgDataDesc pCfgDataDesc, t_pchar pHelpBuff, t_pint pHelpBuffLen) { t_pToolCfgSet pSetArray; t_int i; pSetArray = pCfgDataDesc->pSetArray; CFG_CHK_APP (ToolCfgChkStrCpy (pHelpBuff, "[", pHelpBuffLen)) for (i=0; ; i++) { if (pSetArray[i].pSetString == NULL) /* end of array? */ break; CFG_CHK_APP (ToolCfgChkStrCpy (pHelpBuff, pSetArray[i].pSetString, pHelpBuffLen)) if (pSetArray[i+1].pSetString) CFG_CHK_APP (ToolCfgChkStrCpy (pHelpBuff, ", ", pHelpBuffLen)) } CFG_CHK_APP (ToolCfgChkStrCpy (pHelpBuff, "]", pHelpBuffLen)) return NO_ERROR; } static APIRET ToolCfgBuildHelpRange (t_pToolCfgDataDesc pCfgDataDesc, t_pchar pHelpBuff, t_pint pHelpBuffLen) { switch (pCfgDataDesc->CfgType) { case CFGTYPE_PRESENCE: CFG_CHK_APP (ToolCfgBuildHelpPresence (pCfgDataDesc, pHelpBuff, pHelpBuffLen)) break; case CFGTYPE_INTEGER: CFG_CHK_APP (ToolCfgBuildHelpInteger (pCfgDataDesc, pHelpBuff, pHelpBuffLen)) break; case CFGTYPE_DOUBLE: CFG_CHK_APP (ToolCfgBuildHelpDouble (pCfgDataDesc, pHelpBuff, pHelpBuffLen)) break; case CFGTYPE_STRING: CFG_CHK_APP (ToolCfgBuildHelpString (pCfgDataDesc, pHelpBuff, pHelpBuffLen)) break; case CFGTYPE_SET: CFG_CHK_APP (ToolCfgBuildHelpSet (pCfgDataDesc, pHelpBuff, pHelpBuffLen)) break; case CFGTYPE_HMS: CFG_CHK_APP (ToolCfgBuildHelpHMS (pCfgDataDesc, pHelpBuff, pHelpBuffLen)) break; case CFGTYPE_NULL: break; default: return TOOLCFG_ERROR_INVALID_CFGTYPE; } return NO_ERROR; } static APIRET ToolCfgBuildHelp (t_pToolCfgDataDesc pCfgDataDesc, t_pchar pHelpBuff, t_pint pHelpBuffLen) { *pHelpBuffLen = 0; CFG_CHK_APP (ToolCfgChkStrCpy (pHelpBuff, pCfgDataDesc->pName, pHelpBuffLen)) CFG_CHK_APP (ToolCfgChkStrCpy (pHelpBuff, " = " , pHelpBuffLen)) CFG_CHK_APP (ToolCfgBuildHelpRange (pCfgDataDesc, pHelpBuff, pHelpBuffLen)) (*pHelpBuffLen)++; return NO_ERROR; } static APIRET ToolCfgBuildTableHelp (t_pToolCfgTableDesc pCfgTableDesc, t_pchar pHelpBuff1, t_pchar pHelpBuff2, t_pint pHelpBuffLen) { t_pToolCfgDataDesc pCfgDataDesc; t_pchar pTmp; t_int i; t_int NameLen; t_int RangeLen; t_int Spaces; t_int HelpBuffLenDummy; t_int PrevLen; *pHelpBuffLen = 0; HelpBuffLenDummy = 0; CFG_CHK_APP (ToolCfgMemAlloc ((void **)&pTmp, 4096, MEM_OPT_NONE, MemIdCfgHelpTable)) for (i=0;;i++) { pCfgDataDesc = &pCfgTableDesc->pDataDescArray[i]; if (pCfgDataDesc->pName == NULL) break; NameLen = (t_int)strlen (pCfgDataDesc->pName); CFG_CHK_APP (ToolCfgChkStrCpy (pHelpBuff1, pCfgDataDesc->pName, pHelpBuffLen)) PrevLen = HelpBuffLenDummy; CFG_CHK_APP (ToolCfgBuildHelpRange (pCfgDataDesc, pHelpBuff2, &HelpBuffLenDummy)) RangeLen = HelpBuffLenDummy - PrevLen; if (RangeLen != NameLen) { Spaces = abs (RangeLen - NameLen); memset (pTmp, ' ', Spaces); pTmp[Spaces] = '\0'; if (RangeLen > NameLen) CFG_CHK_APP (ToolCfgChkStrCpy (pHelpBuff1, pTmp, pHelpBuffLen )) else CFG_CHK_APP (ToolCfgChkStrCpy (pHelpBuff2, pTmp, &HelpBuffLenDummy)) } CFG_CHK_APP (ToolCfgChkStrCpy (pHelpBuff1, " ", pHelpBuffLen )) CFG_CHK_APP (ToolCfgChkStrCpy (pHelpBuff2, " ", &HelpBuffLenDummy)) } CFG_CHK_APP (ToolCfgMemFree (pTmp, MemIdCfgHelpTable)) (*pHelpBuffLen)++; return NO_ERROR; } static APIRET ToolCfgQueryFileInfo (t_pchar pFileName, t_pint pYear, t_pint pMonth , t_pint pDay, t_pint pHour, t_pint pMinute, t_pint pSize) { // OS/2 code // --------- // FILEFINDBUF3 FindBuff; // HDIR hDir; // ULONG Count; // // hDir = HDIR_SYSTEM; // Count = 1; // Search for only 1 entry // CFG_CHK_APP(DosFindFirst(pFileName, &hDir, FILE_NORMAL, &FindBuff, sizeof(FILEFINDBUF3), &Count, FIL_STANDARD)) // CFG_CHK_APP(DosFindClose(hDir)) // // if (pYear ) *pYear = FindBuff.fdateLastWrite.year + OS2DOS_YEAROFFSET; // if (pMonth ) *pMonth = FindBuff.fdateLastWrite.month; // if (pDay ) *pDay = FindBuff.fdateLastWrite.day; // if (pHour ) *pHour = FindBuff.ftimeLastWrite.hours; // if (pMinute) *pMinute = FindBuff.ftimeLastWrite.minutes; // if (pSize ) *pSize = (t_int)FindBuff.cbFile; // Linux code // ---------- struct stat FileInfo; struct tm* LastModified = NULL; memset (&FileInfo, 0, sizeof(FileInfo)); // Get file statistics if (((stat (pFileName, &FileInfo)) == -1) || (!(FileInfo.st_mode & S_IFREG))) { CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Could not stat configuration file %s: file not found", pFileName)) return TOOLCFG_ERROR_FILE_NOT_FOUND; } LastModified = localtime (&(FileInfo.st_mtime)); if (pYear ) *pYear = LastModified->tm_year; if (pMonth ) *pMonth = LastModified->tm_mon; if (pDay ) *pDay = LastModified->tm_mday; if (pHour ) *pHour = LastModified->tm_hour; if (pMinute) *pMinute = LastModified->tm_min; if (pSize ) *pSize = FileInfo.st_size; return NO_ERROR; } static APIRET ToolCfgReadCmdLine (t_pToolCfgContext pCfgContext) { t_pchar pTmp; t_int i; t_uint Alloc; t_int SpaceSplit; /* Find size */ pCfgContext->BufferLen = 0; for (i=1; iBufferLen += (t_int) strlen (ToolCfgLocal.argv[i]) + 1; /* +1 for CR */ } pCfgContext->BufferLen++; /* ++ for ending '\0' */ /* Alloc memory */ Alloc = pCfgContext->BufferLen; if (Alloc == sizeof(t_pvoid)) Alloc++; CFG_CHK_APP (ToolCfgMemAlloc((void **)&pCfgContext->pBuffer, Alloc, MEM_OPT_NONE, MemIdCfgBuffer)) // Read command line into buffer, seperate arguments by a spaces pTmp = pCfgContext->pBuffer; for (i=1; ipBuffer; *pTmp != '\0'; pTmp++) { if (*pTmp == STRING_DELIMITER) SpaceSplit = !SpaceSplit; if (SpaceSplit && (*pTmp == ' ')) *pTmp = CHAR_CR; } // pTmp = pCfgContext->pBuffer; // for (i=1; iActLineLen = 0; pCfgContext->ActLineNr = 1; pCfgContext->pActLine = pCfgContext->pBuffer; return NO_ERROR; } static APIRET ToolCfgReadCfgFile (t_pToolCfgContext pCfgContext) { FILE *pCfgFile; t_int SizeRead; t_int rc; t_int Year, Month , Day; t_int Hour, Minute; t_int Size; /* Expand filename (only possible when using the toolbox) */ #ifndef TOCFG_COMPILE_FOR_USE_WITHOUT_TOOLBOX (void) strcpy (&ToolCfgLocal.TempFileName[0], &pCfgContext->FileName[0]); CFG_CHK_APP (ToolEnvExpand (&ToolCfgLocal.TempFileName[0], &pCfgContext->FileName[0], MAX_FILENAME_LEN)) #endif /* Find size */ pCfgFile = fopen (&pCfgContext->FileName[0], "rb"); if (pCfgFile == NULL) { CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Could not open configuration file %s", &pCfgContext->FileName[0])) return TOOLCFG_ERROR_OPEN_FAILED; } rc = setvbuf (pCfgFile, NULL, _IOFBF, 32768); if (rc) return TOOLCFG_ERROR_SETBUF_FAILED; rc = fseek (pCfgFile, 0, SEEK_END); if (rc) return TOOLCFG_ERROR_SEEKEND_FAILED; pCfgContext->BufferLen = (t_int) ftell (pCfgFile) + 1; /* +1 for ending '\0' */ /* Alloc memory */ CFG_CHK_APP (ToolCfgMemAlloc((void **)&pCfgContext->pBuffer, (t_uint)pCfgContext->BufferLen, MEM_OPT_NONE, MemIdCfgBuffer)) /* Read command line into buffer */ rc = fseek (pCfgFile, 0, SEEK_SET); if (rc) return TOOLCFG_ERROR_SEEKSET_FAILED; SizeRead = (t_int) fread (pCfgContext->pBuffer, 1, (size_t)pCfgContext->BufferLen, pCfgFile); if (SizeRead > pCfgContext->BufferLen) return TOOLCFG_ERROR_READ_FAILED; rc = fclose (pCfgFile); if (rc) return TOOLCFG_ERROR_CLOSE_FAILED; pCfgContext->pBuffer[SizeRead] = '\0'; CFG_CHK_APP (ToolCfgQueryFileInfo (&pCfgContext->FileName[0], &Year, &Month, &Day, &Hour, &Minute, &Size)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Scanning configuration file %s (%d bytes %02d.%02d.%d %02d:%02d)", &pCfgContext->FileName[0], Size, Day, Month, Year, Hour, Minute)) /* Set initial context */ pCfgContext->ActLineLen = 0; pCfgContext->ActLineNr = 1; pCfgContext->pActLine = pCfgContext->pBuffer; return NO_ERROR; } static APIRET ToolCfgGetLineLen (t_pToolCfgContext pCfgContext) { t_pchar pEol; t_pchar pLastBackslash; t_int CopyLen; t_int KeepRunning; pLastBackslash = NULL; KeepRunning = TRUE; pEol = pCfgContext->pActLine; while (KeepRunning) { switch (*pEol) { case CHAR_APPEND_LINE: pLastBackslash = pEol++; break; case ' ' : case '\t' : pEol++; break; case CHAR_CR: case CHAR_LF: if (pLastBackslash) { if (((*pEol == CHAR_CR) && (pEol[1] == CHAR_LF)) || ((*pEol == CHAR_LF) && (pEol[1] == CHAR_CR))) pEol++; pEol++; CopyLen = pCfgContext->pBuffer + pCfgContext->BufferLen - pEol; memcpy (pLastBackslash, pEol, CopyLen); pEol = pLastBackslash; pLastBackslash = NULL; pCfgContext->ActLineNr++; } else KeepRunning = FALSE; break; case '\0' : KeepRunning = FALSE; break; default : pLastBackslash = NULL; pEol++; } } pCfgContext->ActLineLen = pEol - pCfgContext->pActLine; return NO_ERROR; } static APIRET ToolCfgSearchLine (t_pToolCfgContext pCfgContext) { t_pchar pTmp; pTmp = pCfgContext->pActLine + pCfgContext->ActLineLen; if (*pTmp != '\0') { if (((pTmp[0] == CHAR_LF) && (pTmp[1] == CHAR_CR)) || ((pTmp[1] == CHAR_LF) && (pTmp[0] == CHAR_CR))) pTmp += 2; else pTmp += 1; } pCfgContext->ActLineNr++; pCfgContext->pActLine = pTmp; CFG_CHK_APP (ToolCfgGetLineLen (pCfgContext)) return NO_ERROR; } /* CfgNoFurtherParamsExpected reports an error if further */ /* parameters are found between pStart and the end of line. */ static APIRET ToolCfgNoFurtherParamsExpected (t_pcchar pStart, t_pcchar pCorrectSyntaxText) { while ((*pStart == ' ') || (*pStart == '\t')) pStart++; if ((*pStart != CHAR_CR) && (*pStart != CHAR_LF) && (*pStart != '\0')) { CFG_CHK_APP (ToolCfgStdErrorHeader (pStart)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "No further parameter expected.")) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, pCorrectSyntaxText)) return TOOLCFG_ERROR_CONFIG_ERROR; } return NO_ERROR; } //static t_pchar ToolCfgFindEndOfString (t_pchar pString) //{ // t_pchar pTmp; // // for ( pTmp = pString; // (*pTmp != CHAR_CR) && (*pTmp != ' ') && // (*pTmp != CHAR_LF) && (*pTmp != '\t') && (*pTmp != '\0'); // pTmp++) // { // } // return pTmp-1; //} static t_int ToolCfgScanningCmdLine (void) { if (ToolCfgLocal.pActCfgContext->FileName[0] == '\0') return TRUE; else return FALSE; } static APIRET ToolCfgDropContext (t_pToolCfgContext pCfgContext) { CFG_CHK_APP (ToolCfgMemFree (pCfgContext->pBuffer, MemIdCfgBuffer)) return NO_ERROR; } /* CfgGetNextLine is the core function of the configuration scanner. From the calling */ /* function's point of view, it simply reads the next line (or returns ppLine = NULL if */ /* no more data can be found). Internally it manages the INCLUDE and SECTION statements. */ static APIRET ToolCfgGetNextLine (t_pchar *ppLine, t_pint pLineLen) { t_pToolCfgContext pContext; t_pchar pEol, pTmp, pKeyWord, pFirstWord; t_int ParamLen; t_int RemLineLen; char TmpChar; t_int KeyLen; t_int KeyLenSectionStart; t_int KeyLenSectionEnd; t_int SectionNameFound; t_int i; t_int SectionSubNesting; bool ChkInclude; bool ChkIncludeOpt; APIRET rc; char Space[] = " "; pTmp = Space; pContext = ToolCfgLocal.pActCfgContext; while ((pContext->State != CFGSTATE_LINEREAD) && (pContext->State != CFGSTATE_COMPLETED)) { switch (pContext->State) { case CFGSTATE_INCLUDENEWFILE: case CFGSTATE_INCLUDENEWFILE_OPT: if (strlen (pContext->FileName) == 0) rc = ToolCfgReadCmdLine (pContext); /* The cmd line has to be read into pBuffer */ else rc = ToolCfgReadCfgFile (pContext); /* The cfg file has to be read into pBuffer */ if ((rc == TOOLCFG_ERROR_OPEN_FAILED) && (pContext->State == CFGSTATE_INCLUDENEWFILE_OPT)) { ToolCfgLocal.IncludeNestingLevel--; ToolCfgLocal.pActCfgContext = &ToolCfgLocal.pCfgContextStack[ToolCfgLocal.IncludeNestingLevel]; pContext = ToolCfgLocal.pActCfgContext; pContext->State = CFGSTATE_GETNEWLINE; } else { CFG_CHK_APP (rc) pTmp = pContext->pActLine; CFG_CHK_APP (ToolCfgGetLineLen (pContext)) pContext->State = CFGSTATE_CHECKEOF; } break; case CFGSTATE_GETNEWLINE: CFG_CHK_APP (ToolCfgSearchLine (pContext)) pContext->State = CFGSTATE_CHECKEOF; break; case CFGSTATE_CHECKEOF: pTmp = pContext->pActLine; if ((*pTmp == '\0') || (*pTmp == CHAR_EOF)) { if (pContext->SectionNesting != 0) { pContext->pActLine = NULL; CFG_CHK_APP (ToolCfgStdErrorHeader (NULL)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Missing statement %s before end of file.", KEYWORD_SECTIONEND)) return TOOLCFG_ERROR_CONFIG_ERROR; } CFG_CHK_APP (ToolCfgDropContext (pContext)) ToolCfgLocal.IncludeNestingLevel--; if (ToolCfgLocal.IncludeNestingLevel == -1) /* did we leave the last nesting level */ { pTmp = NULL; pContext->pActLine = NULL; pContext->ActLineLen = 0; pContext->State = CFGSTATE_COMPLETED; } else { ToolCfgLocal.pActCfgContext = &ToolCfgLocal.pCfgContextStack[ToolCfgLocal.IncludeNestingLevel]; pContext = ToolCfgLocal.pActCfgContext; pContext->State = CFGSTATE_GETNEWLINE; } } else pContext->State = CFGSTATE_CHECKINCLUDE; break; case CFGSTATE_CHECKINCLUDE: for ( pKeyWord = pTmp; (*pKeyWord == ' ') || (*pKeyWord == '\t'); pKeyWord++) { } ChkInclude = ToolCfgStrNCmpNoCase (pKeyWord, KEYWORD_INCLUDE , (t_int) strlen (KEYWORD_INCLUDE )) == 0; ChkIncludeOpt = ToolCfgStrNCmpNoCase (pKeyWord, KEYWORD_INCLUDE_OPT, (t_int) strlen (KEYWORD_INCLUDE_OPT)) == 0; if (ChkInclude || ChkIncludeOpt) { if (++ToolCfgLocal.IncludeNestingLevel >= ToolCfgLocal.MaxIncludeNestingLevel) return TOOLCFG_ERROR_INCLUDE_NESTING_OVERFLOW; pEol = pContext->pActLine + pContext->ActLineLen; TmpChar = *pEol; *pEol = '\0'; /* set to 0 to have sscanf stop at the end of line */ ToolCfgLocal.pActCfgContext = &ToolCfgLocal.pCfgContextStack[ToolCfgLocal.IncludeNestingLevel]; pContext = ToolCfgLocal.pActCfgContext; if (ChkIncludeOpt) { pContext->State = CFGSTATE_INCLUDENEWFILE_OPT; pFirstWord = pKeyWord + strlen (KEYWORD_INCLUDE_OPT); } else { pContext->State = CFGSTATE_INCLUDENEWFILE; pFirstWord = pKeyWord + strlen (KEYWORD_INCLUDE); } // Initialize for parameter scanning ParamLen = 0; RemLineLen = strlen (pFirstWord); // Get the filename CFG_CHK_APP (ToolCfgFindFirstWord (pFirstWord + ParamLen, (const char **) &pFirstWord, RemLineLen, &RemLineLen)) CFG_CHK_APP (ToolCfgGetParamLen (pFirstWord, &ParamLen)) ToolCfgStrMaxCpy (&pContext->FileName[0], pFirstWord, min(MAX_FILENAME_LEN, ParamLen+1)); RemLineLen -= ParamLen; // Get the section names for (i=0; ;i++) { CFG_CHK_APP (ToolCfgFindFirstWord (pFirstWord + ParamLen, (const char **) &pFirstWord, RemLineLen, &RemLineLen)) if (pFirstWord == NULL) break; if (i >= MAX_SECTIONNAMES) { CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Too many parameters for keyword %s or %s", KEYWORD_INCLUDE, KEYWORD_INCLUDE_OPT)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "The correct syntax is: %s [SectionName1] [SectionName2] ... [SectionName16]", KEYWORD_INCLUDE)) return TOOLCFG_ERROR_CONFIG_ERROR; } CFG_CHK_APP (ToolCfgGetParamLen (pFirstWord, &ParamLen)) ToolCfgStrMaxCpy (&(pContext->SectionNameArr[i][0]), pFirstWord, min(MAX_SECTIONNAME_LEN, ParamLen)+1); RemLineLen -= ParamLen; } *pEol = TmpChar; while (iSectionNameArr[i++])[0] = '\0'; pContext->SectionNesting = 0; } else pContext->State = CFGSTATE_CHECKSECTION; break; case CFGSTATE_CHECKSECTION: for ( pKeyWord = pTmp; /* lint ?????????? */ (*pKeyWord == ' ') || (*pKeyWord == '\t'); pKeyWord++) { } if (ToolCfgStrNCmpNoCase (pKeyWord, KEYWORD_SECTIONSTART, (t_int) strlen (KEYWORD_SECTIONSTART)) == 0) { // if (pContext->SectionNesting >0) // { // CFG_CHK_APP (ToolCfgStdErrorHeader (pKeyWord)) // CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "SECTION statements are not allowed to be nested within one file.")) // return TOOLCFG_ERROR_CONFIG_ERROR; // } pFirstWord = pKeyWord + strlen (KEYWORD_SECTIONSTART); RemLineLen = strlen (pFirstWord); CFG_CHK_APP (ToolCfgFindFirstWord (pFirstWord, (const char **) &pFirstWord, RemLineLen, &RemLineLen)) if (pFirstWord == NULL) { CFG_CHK_APP (ToolCfgStdErrorHeader (pFirstWord)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Section name expected.")) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "The correct syntax is: SECTION [SectionName1] [SectionName2] ...")) return TOOLCFG_ERROR_CONFIG_ERROR; } SectionNameFound = FALSE; while (pFirstWord != NULL) { CFG_CHK_APP (ToolCfgGetParamLen (pFirstWord, &ParamLen)) TmpChar = pFirstWord[ParamLen]; pFirstWord[ParamLen] = '\0'; for (i=0; (iSectionNameArr[i][0]), pFirstWord) == 0); // pFirstWord may have less chars than SectionNameArr[i], } // but in that case, ToolCfgStrCmpNoCase will no return 0 (eq) if (!SectionNameFound) { for (i=0; (iSectionNesting++; pContext->State = CFGSTATE_GETNEWLINE; } else { pContext->State = CFGSTATE_SEARCHSECTIONEND; } } else { pContext->State = CFGSTATE_CHECKSECTIONEND; } break; case CFGSTATE_CHECKSECTIONEND: KeyLen = (t_int) strlen (KEYWORD_SECTIONEND); for ( pKeyWord = pTmp; /* lint: ???? */ (*pKeyWord == ' ') || (*pKeyWord == '\t'); pKeyWord++) { } if (ToolCfgStrNCmpNoCase (pKeyWord, KEYWORD_SECTIONEND, KeyLen) == 0) { CFG_CHK_APP (ToolCfgNoFurtherParamsExpected (pKeyWord + KeyLen, "ENDSECTION requires no parameters.")) if (pContext->SectionNesting <= 0) { CFG_CHK_APP (ToolCfgStdErrorHeader (pKeyWord)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "No corresponding SECTION statement encountered.")) return TOOLCFG_ERROR_CONFIG_ERROR; } else { pContext->SectionNesting--; pContext->State = CFGSTATE_GETNEWLINE; } } else pContext->State = CFGSTATE_LINEREAD; break; case CFGSTATE_SEARCHSECTIONEND: KeyLenSectionStart = (t_int) strlen (KEYWORD_SECTIONSTART); KeyLenSectionEnd = (t_int) strlen (KEYWORD_SECTIONEND ); for (SectionSubNesting = 0;;) { CFG_CHK_APP (ToolCfgSearchLine (pContext)) if (*pContext->pActLine == '\0') { pContext->pActLine = NULL; CFG_CHK_APP (ToolCfgStdErrorHeader (NULL)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Missing statement ENDSECTION before end of file.")) return TOOLCFG_ERROR_CONFIG_ERROR; } pTmp = pContext->pActLine; while ((*pTmp != '\0') && ((*pTmp == ' ') || (*pTmp == '\t'))) pTmp++; if (ToolCfgStrNCmpNoCase (pTmp, KEYWORD_SECTIONEND, KeyLenSectionEnd) == 0) { CFG_CHK_APP (ToolCfgNoFurtherParamsExpected (pTmp + KeyLenSectionEnd, "ENDSECTION requires no parameters.")) if (SectionSubNesting == 0) { pContext->State = CFGSTATE_GETNEWLINE; break; } SectionSubNesting--; } else if (ToolCfgStrNCmpNoCase (pTmp, KEYWORD_SECTIONSTART, KeyLenSectionStart) == 0) { SectionSubNesting++; } } break; default: return TOOLCFG_ERROR_INVALID_STATE; } } pContext->State = CFGSTATE_GETNEWLINE; /* This will be our task on the next call of this function */ *ppLine = pContext->pActLine; *pLineLen = pContext->ActLineLen; return NO_ERROR; } /* ----------------------------------- */ /* Conversion functions */ /* ----------------------------------- */ static APIRET ToolCfgConvertpParamToHMS (t_pchar pParam, t_int /*ParamLen*/, t_pint pValue) { t_int rc; t_int Hour, Min, Sec; if (((pParam[0] >= '0') && (pParam[0] <= '9'))) { rc = sscanf (pParam, "%d:%d:%d", &Hour, &Min, &Sec); if (rc!=3) { Sec = 0; rc = sscanf (pParam, "%d:%d", &Hour, &Min); // Check reduced HH:MM format if (rc!=2) { CFG_CHK_APP (ToolCfgStdErrorHeader (pParam)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Invalid hh:mm:ss value.")) return TOOLCFG_ERROR_CONFIG_ERROR; } } *pValue = Hour*3600 + Min*60 + Sec; // convert to seconds } else { CFG_CHK_APP (ToolCfgStdErrorHeader (pParam)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Invalid entry, hh:mm:ss expected.")) return TOOLCFG_ERROR_CONFIG_ERROR; } return NO_ERROR; } static APIRET ToolCfgConvertpParamToInteger (t_pchar pParam, t_int ParamLen, t_pint pValue, t_pint pDecConv) { t_int rc; t_int i; t_int MinLen; if ( ((pParam[0] == '0') && ((pParam[1] == 'x') || (pParam[1] == 'X'))) || (pParam[0] == '$')) { if (pParam[0] == '$') MinLen = 1; else MinLen = 2; for (i=MinLen; i= '0') && (pParam[i] <= '9')) && !((pParam[i] >= 'a') && (pParam[i] <= 'f')) && !((pParam[i] >= 'A') && (pParam[i] <= 'F'))) { CFG_CHK_APP (ToolCfgStdErrorHeader (pParam+i)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Invalid hexadecimal value.")) return TOOLCFG_ERROR_CONFIG_ERROR; } } if (ParamLen > MinLen) rc = sscanf (&pParam[MinLen], "%x", pValue); else rc = 0; if (rc!=1) { CFG_CHK_APP (ToolCfgStdErrorHeader (pParam)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Invalid hexadecimal value.")) return TOOLCFG_ERROR_CONFIG_ERROR; } *pDecConv=FALSE; } else if (((pParam[0] >= '0') && (pParam[0] <= '9')) || (pParam[0] == '-')) { for (i=1; i '9')) { CFG_CHK_APP (ToolCfgStdErrorHeader (pParam+i)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Invalid decimal value.")) return TOOLCFG_ERROR_CONFIG_ERROR; } } rc = sscanf (pParam, "%d", pValue); if (rc!=1) { CFG_CHK_APP (ToolCfgStdErrorHeader (pParam)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Invalid decimal value.")) return TOOLCFG_ERROR_CONFIG_ERROR; } *pDecConv=TRUE; } else { CFG_CHK_APP (ToolCfgStdErrorHeader (pParam)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Invalid entry, decimal or hexadecimal number expected.")) return TOOLCFG_ERROR_CONFIG_ERROR; } return NO_ERROR; } static APIRET ToolCfgConvertpParamToDouble (t_pchar pParam, t_int ParamLen, t_pdouble pValue) { t_int rc; long double LongDoubleVal; // t_pchar pOldLocale; t_int i; t_int DecimalPoint; t_int Exponent; // Check all the chars in the param to detect entry errors // Convert ',' to '.' DecimalPoint = FALSE; Exponent = FALSE; for (i=0; i '9')) { CFG_CHK_APP (ToolCfgStdErrorHeader (pParam+i)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Invalid character encountered")) return TOOLCFG_ERROR_CONFIG_ERROR; } } // switch the 'locale' to accept '.' as decimal point, // So far, so good, but: the locale functions unser OS/2 are // scan the double value and switch back. // extremely slow! they require several seconds while scanning // pOldLocale = setlocale (LC_NUMERIC, NULL); // the configuration file (measured by IXTRA)! That's the reason // (void) setlocale (LC_NUMERIC, LC_C_USA); // why we trust in the US default. rc = sscanf (pParam, "%LG", &LongDoubleVal); // (void) setlocale (LC_NUMERIC, pOldLocale); if (rc!=1) { CFG_CHK_APP (ToolCfgStdErrorHeader (pParam)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Invalid double value.")) return TOOLCFG_ERROR_CONFIG_ERROR; } *pValue = (t_double) LongDoubleVal; return NO_ERROR; } static APIRET ToolCfgReadParameterHMS (t_pchar pParam, t_int ParamLen, t_pToolCfgDataDesc pCfgDataDesc, long BaseAddr, t_int Assign) { t_pcchar pFormatStr; t_int Value; t_int MinVal, MaxVal; CFG_CHK_APP (ToolCfgConvertpParamToHMS (pParam, ParamLen, &Value)) if ((Value < (t_int)pCfgDataDesc->MinValue) || (Value > (t_int)pCfgDataDesc->MaxValue)) { CFG_CHK_APP (ToolCfgStdErrorHeader (pParam)) MinVal = (t_int)pCfgDataDesc->MinValue; MaxVal = (t_int)pCfgDataDesc->MaxValue; pFormatStr = "Value out of range: %02d:%02d:%02d <= %s <= %02d:%02d:%02d"; CFG_CHK_APP (ToolCfgLogEntry(__FFL__, pFormatStr, MinVal/3600, (MinVal/60)%60, MinVal%60, pCfgDataDesc->pName, MaxVal/3600, (MaxVal/60)%60, MaxVal%60)) return TOOLCFG_ERROR_CONFIG_ERROR; } if (Assign) *((t_pint)((t_pchar)pCfgDataDesc->DestAddr + BaseAddr)) = Value; return NO_ERROR; } static APIRET ToolCfgReadParameterInteger (t_pchar pParam, t_int ParamLen, t_pToolCfgDataDesc pCfgDataDesc, long BaseAddr, t_int Assign) { t_pcchar pFormatStr; t_int Value; t_int DecConv; /* To check whether a decimal or hexadecimal conversion had be performed */ CFG_CHK_APP (ToolCfgConvertpParamToInteger (pParam, ParamLen, &Value, &DecConv)) if ((Value < (t_int)pCfgDataDesc->MinValue) || (Value > (t_int)pCfgDataDesc->MaxValue)) { CFG_CHK_APP (ToolCfgStdErrorHeader (pParam)) if (DecConv) pFormatStr = "Value out of range: %d <= %s <= %d"; else pFormatStr = "Value out of range: 0x%X <= %s <= 0x%X"; CFG_CHK_APP (ToolCfgLogEntry(__FFL__, pFormatStr, (t_int)pCfgDataDesc->MinValue, pCfgDataDesc->pName, (t_int)pCfgDataDesc->MaxValue)) return TOOLCFG_ERROR_CONFIG_ERROR; } if (Assign) *((t_pint)((t_pchar)pCfgDataDesc->DestAddr + BaseAddr)) = Value; return NO_ERROR; } static APIRET ToolCfgReadParameterDouble (t_pchar pParam, t_int ParamLen, t_pToolCfgDataDesc pCfgDataDesc, long BaseAddr, t_int Assign) { t_pcchar pFormatStr; t_double Value; CFG_CHK_APP (ToolCfgConvertpParamToDouble (pParam, ParamLen, &Value)) if ((Value < pCfgDataDesc->MinValue) || (Value > pCfgDataDesc->MaxValue)) { CFG_CHK_APP (ToolCfgStdErrorHeader (pParam)) pFormatStr = "Value out of range: %G <= %s <= %G"; CFG_CHK_APP (ToolCfgLogEntry(__FFL__, pFormatStr, pCfgDataDesc->MinValue, pCfgDataDesc->pName, pCfgDataDesc->MaxValue)) return TOOLCFG_ERROR_CONFIG_ERROR; } if (Assign) *((t_pdouble)((t_pchar)pCfgDataDesc->DestAddr + BaseAddr)) = Value; return NO_ERROR; } static APIRET ToolCfgConvertpParamToString (t_pchar pParam, t_int ParamLen, t_pchar *ppString, t_pint pStringLen) { if (pParam[0] != STRING_DELIMITER) { CFG_CHK_APP (ToolCfgStdErrorHeader (pParam)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "String expected. Use %c %c as string delimiters.", STRING_DELIMITER, STRING_DELIMITER)) return TOOLCFG_ERROR_CONFIG_ERROR; } if (pParam[ParamLen-1] != STRING_DELIMITER) { CFG_CHK_APP (ToolCfgStdErrorHeader (pParam+ParamLen-1)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "String exceeds end of line, use %c %c as string delimiters, or %c to append next line.", STRING_DELIMITER, STRING_DELIMITER, CHAR_APPEND_LINE)) return TOOLCFG_ERROR_CONFIG_ERROR; } *ppString = pParam+1; *pStringLen = ParamLen-2; return NO_ERROR; } static APIRET ToolCfgReadParameterString (t_pchar pParam, t_int ParamLen, t_pToolCfgDataDesc pCfgDataDesc, long BaseAddr, t_int Assign) { t_pchar pString; t_int StringLen; t_pchar pDest; t_int Src, Dst; CFG_CHK_APP (ToolCfgConvertpParamToString (pParam, ParamLen, &pString, &StringLen)) if (StringLen > pCfgDataDesc->DestLen) { CFG_CHK_APP (ToolCfgStdErrorHeader (pParam)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "String too long. The maximum length of the string is %d", pCfgDataDesc->DestLen)) return TOOLCFG_ERROR_CONFIG_ERROR; } if (Assign) { /* Copy the string, replace duplicate '' by single' */ pDest = (t_pchar)pCfgDataDesc->DestAddr + BaseAddr; for (Src=0, Dst=0; SrcDestAddr + BaseAddr, pString, (size_t) StringLen); // ((t_pchar)pCfgDataDesc->DestAddr + BaseAddr)[StringLen] = '\0'; } return NO_ERROR; } static APIRET ToolCfgConvertpParamToSet (t_pchar pParam, t_int ParamLen, t_pToolCfgDataDesc pCfgDataDesc, t_pint pSetValue) { t_pchar pTmp; t_int i; t_int Len; t_pToolCfgSet pSetArray; pSetArray = pCfgDataDesc->pSetArray; for (i=0; ; i++) { if (pSetArray[i].pSetString == NULL) break; /* end of array */ if (ParamLen == (t_int)strlen (pSetArray[i].pSetString)) if (ToolCfgStrNCmpNoCase (pSetArray[i].pSetString, pParam, ParamLen) == 0) break; /* set entry found */ } if (pSetArray[i].pSetString == NULL) { CFG_CHK_APP (ToolCfgStdErrorHeader (pParam)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Invalid set value.")) CFG_CHK_APP (ToolCfgBuildHelp (pCfgDataDesc, NULL, &Len)) CFG_CHK_APP (ToolCfgMemAlloc ((void **)&pTmp, (t_uint)Len, MEM_OPT_NONE, MemIdCfgHelpBuff)) CFG_CHK_APP (ToolCfgBuildHelp (pCfgDataDesc, pTmp, &Len)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, pTmp)) CFG_CHK_APP (ToolCfgMemFree (pTmp, MemIdCfgHelpBuff)) return TOOLCFG_ERROR_CONFIG_ERROR; } *pSetValue = pSetArray[i].SetValue; return NO_ERROR; } static APIRET ToolCfgReadParameterSet (t_pchar pParam, t_int ParamLen, t_pToolCfgDataDesc pCfgDataDesc, long BaseAddr, t_int Assign) { t_int SetValue; CFG_CHK_APP (ToolCfgConvertpParamToSet (pParam, ParamLen, pCfgDataDesc, &SetValue)) if (Assign) *((t_pint)((t_pchar)pCfgDataDesc->DestAddr + BaseAddr)) = SetValue; return NO_ERROR; } static APIRET ToolCfgReadParameter0 (t_pchar pFirstParamChar, t_int ParamLen, t_pToolCfgDataDesc pCfgDataDesc, long BaseAddr, t_int Assign) { if (BaseAddr == (long)INT_MIN) Assign = FALSE; switch (pCfgDataDesc->CfgType) { case CFGTYPE_INTEGER: CFG_CHK_APP (ToolCfgReadParameterInteger (pFirstParamChar, ParamLen, pCfgDataDesc, BaseAddr, Assign)) break; case CFGTYPE_DOUBLE : CFG_CHK_APP (ToolCfgReadParameterDouble (pFirstParamChar, ParamLen, pCfgDataDesc, BaseAddr, Assign)) break; case CFGTYPE_STRING : CFG_CHK_APP (ToolCfgReadParameterString (pFirstParamChar, ParamLen, pCfgDataDesc, BaseAddr, Assign)) break; case CFGTYPE_SET : CFG_CHK_APP (ToolCfgReadParameterSet (pFirstParamChar, ParamLen, pCfgDataDesc, BaseAddr, Assign)) break; case CFGTYPE_HMS : CFG_CHK_APP (ToolCfgReadParameterHMS (pFirstParamChar, ParamLen, pCfgDataDesc, BaseAddr, Assign)) break; case CFGTYPE_NULL : break; default: return TOOLCFG_ERROR_INVALID_CFGTYPE; } return NO_ERROR; } /* ---------------------------------------------- */ /* Table scanning functions */ /* ---------------------------------------------- */ APIRET ToolCfgAddGlobalSectionName (t_pcchar pSectionName) { t_int i; if (strlen (pSectionName) > MAX_SECTIONNAME_LEN) return TOOLCFG_ERROR_SECTIONNAME_TOO_LONG; for (i=0; i=MAX_GLOBALSECTIONNAMES) return TOOLCFG_ERROR_TOO_MANY_SECTIONNAMES; return NO_ERROR; } APIRET ToolCfgDelGlobalSectionName (t_pcchar pSectionName) { t_int i; if (strlen (pSectionName) > MAX_SECTIONNAME_LEN) return TOOLCFG_ERROR_SECTIONNAME_TOO_LONG; for (i=0; i=MAX_GLOBALSECTIONNAMES) return TOOLCFG_ERROR_SECTIONNAME_NOTFOUND; return NO_ERROR; } static APIRET ToolCfgScanTableAnalyseLine (t_pToolCfgTableDesc pCfgTableDesc, t_pchar pFirstWord, t_int RemLineLen, long BaseAddr, t_pint pLineOk) { t_int i; t_int ParamLen; t_pToolCfgDataDesc pCfgDataDesc; *pLineOk = FALSE; /* printf ("\r\nTable entry: %*.*s", RemLineLen, RemLineLen, pFirstWord); */ if (RemLineLen == 0) return NO_ERROR; ParamLen = 0; for (i=0; ;i++) { pCfgDataDesc = &pCfgTableDesc->pDataDescArray[i]; if (pCfgDataDesc->pName == NULL) break; /* Array ends here */ CFG_CHK_APP (ToolCfgFindFirstWord (pFirstWord + ParamLen, (const char **) &pFirstWord, RemLineLen, &RemLineLen)) CFG_CHK_APP (ToolCfgGetParamLen (pFirstWord, &ParamLen)) CFG_CHK_APP (ToolCfgReadParameter0 (pFirstWord, ParamLen, pCfgDataDesc, BaseAddr, TRUE)) } *pLineOk = TRUE; return NO_ERROR; } static APIRET ToolCfgScanTable (t_pchar pActLine, t_int LineLen, t_pToolCfgTableDesc pCfgTableDescArray) { t_pchar pFirstWord; t_int RemLineLen; t_int i, rcs, Eq; t_int LineOk; t_int Found; t_pchar pTableType; t_pchar pTableName; long BaseAddr; t_pcchar pErrorText; t_char TmpChar; t_pToolCfgTableDesc pCfgTableDesc = NULL; TmpChar = pActLine[LineLen]; /* set end of line to '\0' to ease processing */ pActLine[LineLen] = '\0'; CFG_CHK_APP (ToolCfgMemAlloc ((void **)&pTableType, 64, MEM_OPT_NONE, MemIdCfgTableType)) CFG_CHK_APP (ToolCfgMemAlloc ((void **)&pTableName, 64, MEM_OPT_NONE, MemIdCfgTableName)) CFG_CHK_APP (ToolCfgFindFirstWord (pActLine, (const char **) &pFirstWord, LineLen, &RemLineLen)) rcs = sscanf (pActLine, "%*s %s %s", pTableType, pTableName); if (rcs != 2) { CFG_CHK_APP (ToolCfgStdErrorHeader (pFirstWord)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Invalid parameters for keyword %s", KEYWORD_TABLESTART)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "The correct syntax is: %s ", KEYWORD_TABLESTART)) return TOOLCFG_ERROR_CONFIG_ERROR; } Found = FALSE; if (pCfgTableDescArray != NULL) { for (i=0; ;i++) { pCfgTableDesc = &pCfgTableDescArray[i]; if (pCfgTableDesc->pTableType == NULL) /* End of array reached? */ break; if (ToolCfgStrCmpNoCase(pCfgTableDesc->pTableType, pTableType) == 0) /* Table type found? */ { Found = TRUE; break; } } } if (!Found) { CFG_CHK_APP (ToolCfgStdErrorHeader (pFirstWord)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Invalid table type: %s", pTableType)) return TOOLCFG_ERROR_CONFIG_ERROR; } CFG_CHK_APP ((*pCfgTableDesc->pStartFn) (pTableName, &BaseAddr, &pErrorText)) if (pErrorText) { CFG_CHK_APP (ToolCfgStdErrorHeader (pActLine)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, pErrorText)) return TOOLCFG_ERROR_CONFIG_ERROR; } pActLine[LineLen] = TmpChar; for (LineLen=0;;) { CFG_CHK_APP (ToolCfgGetNextLine (&pActLine, &LineLen)) TmpChar = pActLine[LineLen]; /* set end of line to '\0' to ease processing */ pActLine[LineLen] = '\0'; if (pActLine == NULL) { CFG_CHK_APP (ToolCfgStdErrorHeader (NULL)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Missing statement %s before end of file.", KEYWORD_TABLEEND)) return TOOLCFG_ERROR_CONFIG_ERROR; } CFG_CHK_APP (ToolCfgFindFirstWord (pActLine, (const char **) &pFirstWord, LineLen, &RemLineLen)) CFG_CHK_APP (ToolCfgCompareKeyWord (KEYWORD_TABLEEND, pFirstWord, RemLineLen, &Eq, NULL)) if (Eq) { if (pCfgTableDesc->pEndFn) { CFG_CHK_APP ((*pCfgTableDesc->pEndFn) (&pErrorText)) if (pErrorText) { CFG_CHK_APP (ToolCfgStdErrorHeader (pActLine)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, pErrorText)) return TOOLCFG_ERROR_CONFIG_ERROR; } } pActLine[LineLen] = TmpChar; break; } CFG_CHK_APP (ToolCfgCompareKeyWord (KEYWORD_REMARK, pFirstWord, RemLineLen, &Eq, NULL)) if (!Eq) { CFG_CHK_APP (ToolCfgScanTableAnalyseLine (pCfgTableDesc, pFirstWord, RemLineLen, BaseAddr, &LineOk)) if (LineOk) { CFG_CHK_APP ((*pCfgTableDesc->pSaveAndNextFn) (&BaseAddr, &pErrorText)) if (pErrorText) { CFG_CHK_APP (ToolCfgStdErrorHeader (pActLine)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, pErrorText)) return TOOLCFG_ERROR_CONFIG_ERROR; } } } pActLine[LineLen] = TmpChar; } CFG_CHK_APP (ToolCfgMemFree (pTableType, MemIdCfgTableType)) CFG_CHK_APP (ToolCfgMemFree (pTableName, MemIdCfgTableName)) return NO_ERROR; } /* ---------------------------------------------- */ /* Parameter scanning functions */ /* ---------------------------------------------- */ static APIRET ToolCfgCheckAssignment (t_pchar pKeyWord, t_pToolCfgParamDesc pCfgParamDesc, t_pint pAssign) { t_ToolCfgAssignment AssignSource; t_ToolCfgAssignment AssignCount; AssignSource = (t_ToolCfgAssignment)(pCfgParamDesc->Assign & CFGASN_SOURCE); AssignCount = (t_ToolCfgAssignment)(pCfgParamDesc->Assign & CFGASN_COUNT ); if ((AssignSource == CFGASN_CMD) && !ToolCfgScanningCmdLine()) { CFG_CHK_APP (ToolCfgStdErrorHeader (pKeyWord)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Assignment for this parameter is not allowed in configuration file (only on command line).")) return TOOLCFG_ERROR_CONFIG_ERROR; } if ((AssignSource == CFGASN_CFG) && ToolCfgScanningCmdLine()) { CFG_CHK_APP (ToolCfgStdErrorHeader (pKeyWord)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Assignment for this parameter is not allowed on command line (only in configuration file).")) return TOOLCFG_ERROR_CONFIG_ERROR; } if ((AssignCount == CFGASN_ONCE) && ((pCfgParamDesc->CfgAssignments + pCfgParamDesc->CmdAssignments) >= 1)) { CFG_CHK_APP (ToolCfgStdErrorHeader (pKeyWord)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Assignment for this parameter is only allowed once")) return TOOLCFG_ERROR_CONFIG_ERROR; } if (AssignCount == CFGASN_TWICE) { if (((pCfgParamDesc->CfgAssignments>0) && !ToolCfgScanningCmdLine()) || ((pCfgParamDesc->CmdAssignments>0) && ToolCfgScanningCmdLine())) { CFG_CHK_APP (ToolCfgStdErrorHeader (pKeyWord)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Assignment for this parameter is only allowed once in configuration file.")) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "The assignment in configuration file may be replaced by a command line")) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "assignment")) return TOOLCFG_ERROR_CONFIG_ERROR; } } if (ToolCfgScanningCmdLine()) *pAssign = TRUE; else *pAssign = pCfgParamDesc->CmdAssignments ? FALSE : TRUE; return NO_ERROR; } static APIRET ToolCfgCheckEqualSign (t_pcchar pNextChar, t_pcchar *ppFirstParamChar) { while (((*pNextChar == ' ') || (*pNextChar == '\t')) && (*pNextChar != '\0')) pNextChar++; if ((*pNextChar == '\0') || (*pNextChar != '=')) { CFG_CHK_APP (ToolCfgStdErrorHeader (pNextChar-1)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Equal sign '=' expected.")) return TOOLCFG_ERROR_CONFIG_ERROR; } for ( *ppFirstParamChar = pNextChar+1; ((**ppFirstParamChar == ' ') || (**ppFirstParamChar == '\t')) && (**ppFirstParamChar != '\0'); ( *ppFirstParamChar)++) { } if (**ppFirstParamChar == '\0') { CFG_CHK_APP (ToolCfgStdErrorHeader ((*ppFirstParamChar)-1)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Parameter expected.")) return TOOLCFG_ERROR_CONFIG_ERROR; } return NO_ERROR; } static APIRET ToolCfgReadParameter (t_pchar pKeyWord, t_pchar pNextChar, t_pToolCfgParamDesc pCfgParamDesc) { t_pToolCfgDataDesc pCfgDataDesc; t_pchar pFirstParamChar; t_pchar pErrorText; t_int Assign; t_int ParamLen; if (pCfgParamDesc) CFG_CHK_APP (ToolCfgCheckAssignment (pKeyWord, pCfgParamDesc, &Assign)) pCfgDataDesc = &pCfgParamDesc->DataDesc; if (pCfgDataDesc->CfgType == CFGTYPE_PRESENCE) { CFG_CHK_APP (ToolCfgCheckIfNoParam (pNextChar)) *((t_pint)(pCfgParamDesc->DataDesc.DestAddr)) = TRUE; } else { CFG_CHK_APP (ToolCfgCheckEqualSign (pNextChar, (const char **) &pFirstParamChar)) CFG_CHK_APP (ToolCfgCheckIfOnlyOneParam (pFirstParamChar, &ParamLen)) CFG_CHK_APP (ToolCfgReadParameter0 (pFirstParamChar, ParamLen, pCfgDataDesc, 0, Assign)) } if (Assign) { if (ToolCfgScanningCmdLine()) pCfgParamDesc->CmdAssignments++; else pCfgParamDesc->CfgAssignments++; } if (pCfgParamDesc->pCallOnInitFn) { CFG_CHK_APP ((*pCfgParamDesc->pCallOnInitFn)(pCfgParamDesc, &pErrorText)) if (pErrorText) { CFG_CHK_APP (ToolCfgStdErrorHeader (pKeyWord)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, pErrorText)) return TOOLCFG_ERROR_CONFIG_ERROR; } } return NO_ERROR; } static APIRET ToolCfgAnalyseEntry (t_pchar pActLine, t_int LineLen, t_pToolCfgParamDesc pParamDescArray, t_pToolCfgTableDesc pTableDescArray) { t_pchar pKeyWord; t_pchar pNextChar; t_pToolCfgDataDesc pCfgDataDesc; t_int i; t_int RemLineLen; t_int Eq, EqDef, EqUnDef; t_char TmpChar; t_pchar pSectionName; t_int SectionNameLen; APIRET rc; if (LineLen <=0) /* it's an empty line, unnecessary to continue */ return NO_ERROR; TmpChar = pActLine[LineLen]; /* set end of line to '\0' to ease processing */ pActLine[LineLen] = '\0'; CFG_CHK_APP (ToolCfgFindFirstWord (pActLine, (const char **) &pKeyWord, LineLen, &RemLineLen)) if (pKeyWord == NULL) // Were there just spaces or tabs in this line ? { pActLine[LineLen] = TmpChar; return NO_ERROR; } CFG_CHK_APP (ToolCfgCompareKeyWord (KEYWORD_TABLESTART, pKeyWord, RemLineLen, &Eq, NULL)) if (Eq) { pActLine[LineLen] = TmpChar; CFG_CHK_APP (ToolCfgScanTable(pActLine, LineLen, pTableDescArray)) return NO_ERROR; } CFG_CHK_APP (ToolCfgCompareKeyWord (KEYWORD_REMARK, pKeyWord, RemLineLen, &Eq, NULL)) if (Eq) { pActLine[LineLen] = TmpChar; return NO_ERROR; } CFG_CHK_APP (ToolCfgCompareKeyWord (KEYWORD_DEFINE , pKeyWord, RemLineLen, &EqDef , &pSectionName)) if (!EqDef) CFG_CHK_APP (ToolCfgCompareKeyWord (KEYWORD_UNDEFINE, pKeyWord, RemLineLen, &EqUnDef, &pSectionName)) if (EqDef || EqUnDef) { while (((*pSectionName == ' ') || (*pSectionName == '\t')) && (*pSectionName != '\0')) pSectionName++; CFG_CHK_APP (ToolCfgCheckIfOnlyOneParam (pSectionName, &SectionNameLen)) pActLine[LineLen] = TmpChar; TmpChar = pSectionName[SectionNameLen]; pSectionName[SectionNameLen] = '\0'; if (EqDef) rc = ToolCfgAddGlobalSectionName (pSectionName); else rc = ToolCfgDelGlobalSectionName (pSectionName); switch (rc) { case TOOLCFG_ERROR_SECTIONNAME_TOO_LONG : CFG_CHK_APP (ToolCfgStdErrorHeader (pSectionName)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Section name too long (Max. %d characters).", MAX_SECTIONNAME_LEN)) return TOOLCFG_ERROR_CONFIG_ERROR; case TOOLCFG_ERROR_TOO_MANY_SECTIONNAMES: CFG_CHK_APP (ToolCfgStdErrorHeader (pSectionName)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Too many global section names defined (Max. is %d).", MAX_GLOBALSECTIONNAMES)) return TOOLCFG_ERROR_CONFIG_ERROR; case TOOLCFG_ERROR_SECTIONNAME_NOTFOUND: CFG_CHK_APP (ToolCfgStdErrorHeader (pSectionName)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "The section name %s is not defined.", pSectionName)) return TOOLCFG_ERROR_CONFIG_ERROR; default: CFG_CHK_APP (rc) } pSectionName[SectionNameLen] = TmpChar; return NO_ERROR; } Eq = FALSE; if (pParamDescArray != NULL) { for (i=0; ; i++) { pCfgDataDesc = &pParamDescArray[i].DataDesc; if (pCfgDataDesc->pName == NULL) break;/* end of array */ CFG_CHK_APP (ToolCfgCompareKeyWord (pCfgDataDesc->pName, pKeyWord, RemLineLen, &Eq, &pNextChar)) if (Eq) { CFG_CHK_APP (ToolCfgReadParameter (pKeyWord, pNextChar, &pParamDescArray[i])) break; } } } if (!Eq) /* keyword not found in table */ { CFG_CHK_APP (ToolCfgStdErrorHeader (pKeyWord)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Invalid keyword.")) return TOOLCFG_ERROR_CONFIG_ERROR; } pActLine[LineLen] = TmpChar; return NO_ERROR; } /* CfgFreeContextBuffers: Free all context buffers that are still in use */ static APIRET ToolCfgFreeContextBuffers (void) { t_pToolCfgContext pCfgContext; t_int i; for (i=ToolCfgLocal.IncludeNestingLevel; i>0; i--) { pCfgContext = &ToolCfgLocal.pCfgContextStack[i]; if (pCfgContext->pBuffer) CFG_CHK_APP (ToolCfgMemFree (pCfgContext->pBuffer, MemIdCfgBuffer)) } return NO_ERROR; } static APIRET ToolCfgScanParams (t_pToolCfgParamDesc pParamDescArray, t_pToolCfgTableDesc pTableDescArray) { t_pchar pActLine; t_int LineLen; APIRET rc; CFG_CHK_APP (ToolCfgGetNextLine (&pActLine, &LineLen)) rc = NO_ERROR; while (pActLine && !rc) { rc = ToolCfgAnalyseEntry(pActLine, LineLen, pParamDescArray, pTableDescArray); if (!rc) CFG_CHK_APP (ToolCfgGetNextLine (&pActLine, &LineLen)) } CFG_CHK_APP (ToolCfgFreeContextBuffers()) CFG_CHK_APP (rc) return NO_ERROR; } static APIRET ToolCfgScanSource (t_pcchar pFileName, t_pcchar pSectionName, t_pToolCfgParamDesc pParamDescArray, t_pToolCfgTableDesc pTableDescArray) { APIRET rc; t_int ContextStackSize; t_int i; ContextStackSize = ToolCfgLocal.MaxIncludeNestingLevel * (t_int) sizeof (t_ToolCfgContext); CFG_CHK_APP (ToolCfgMemAlloc ((void **)&ToolCfgLocal.pCfgContextStack, (t_uint)ContextStackSize, MEM_OPT_NONE, MemIdCfgContextStack)) ToolCfgLocal.pActCfgContext = &ToolCfgLocal.pCfgContextStack[0]; ToolCfgLocal.IncludeNestingLevel = 0; /* initialise first context stack entry */ ToolCfgLocal.pActCfgContext->BufferLen = 0; ToolCfgLocal.pActCfgContext->ActLineNr = 0; ToolCfgLocal.pActCfgContext->pActLine = NULL; ToolCfgLocal.pActCfgContext->pBuffer = NULL; ToolCfgLocal.pActCfgContext->SectionNesting = 0; ToolCfgLocal.pActCfgContext->State = CFGSTATE_INCLUDENEWFILE; CFG_CHK_APP (ToolCfgCopyName (pFileName , & ToolCfgLocal.pActCfgContext->FileName [0] , MAX_FILENAME_LEN )) CFG_CHK_APP (ToolCfgCopyName (pSectionName, &(ToolCfgLocal.pActCfgContext->SectionNameArr[0][0]), MAX_SECTIONNAME_LEN)) for (i=1; iSectionNameArr[i][0] = '\0'; rc = ToolCfgScanParams (pParamDescArray, pTableDescArray); CFG_CHK_APP (ToolCfgMemFree (ToolCfgLocal.pCfgContextStack, MemIdCfgContextStack)) CFG_CHK_APP (rc) return NO_ERROR; } /* CfgCheckInitialisation: Check whether all parameters have been initialized. */ static APIRET ToolCfgCheckInitialisation(t_pToolCfgParamDesc pParamDescArray) { t_int i, Err; t_pToolCfgParamDesc pCfgParamDesc; t_pToolCfgDataDesc pCfgDataDesc; Err = FALSE; for (i=0; ;i++) { pCfgParamDesc = &pParamDescArray[i]; pCfgDataDesc = &pCfgParamDesc->DataDesc; if (pCfgDataDesc->pName == NULL) break; /* end of array reached */ if (( pCfgParamDesc->CfgAssignments == 0 ) && ( pCfgParamDesc->CmdAssignments == 0 ) && ( pCfgParamDesc->DataDesc.CfgType != CFGTYPE_NULL ) && ( pCfgParamDesc->DataDesc.CfgType != CFGTYPE_PRESENCE) && // Parameters of type 'presence' are always optional ((pCfgParamDesc->Assign & CFGASN_OPTIONAL) == 0 )) { CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Configuration error: Parameter %s has not been initialized.", pCfgDataDesc->pName)) Err = TRUE; } } if (Err) return TOOLCFG_ERROR_CONFIG_ERROR; return NO_ERROR; } static APIRET ToolCfgLogGetSetName (t_pToolCfgSet pSetArray, t_int SetValue, t_pcchar *ppSetString) { t_int i; *ppSetString = NULL; for (i=0; ; i++) { if (pSetArray[i].pSetString == NULL) break; /* end of array */ if (pSetArray[i].SetValue == SetValue) { *ppSetString = pSetArray[i].pSetString; break; } } return NO_ERROR; } static APIRET ToolCfgPrintContents (t_pchar pBuff, t_pToolCfgParamDesc pCfgParamDesc) { t_pToolCfgDataDesc pCfgDataDesc; t_pchar pSetString; t_int Hms; t_int SetValue; if ((pCfgParamDesc->CfgAssignments == 0) && (pCfgParamDesc->CmdAssignments == 0)) { sprintf (pBuff, "not initialized"); } else { pCfgDataDesc = &pCfgParamDesc->DataDesc; switch (pCfgDataDesc->CfgType) { case CFGTYPE_PRESENCE:sprintf (pBuff, "%s" , *(int *)pCfgDataDesc->DestAddr ? "present" : "not present"); break; case CFGTYPE_INTEGER: sprintf (pBuff, "%d (0x%X)", *(int *)pCfgDataDesc->DestAddr, *(int *)pCfgDataDesc->DestAddr); break; case CFGTYPE_DOUBLE: sprintf (pBuff, "%G" , *(double*)pCfgDataDesc->DestAddr); break; case CFGTYPE_STRING: sprintf (pBuff, "%s" , (char *)pCfgDataDesc->DestAddr); break; case CFGTYPE_SET: SetValue = *(int *)pCfgDataDesc->DestAddr; CFG_CHK_APP (ToolCfgLogGetSetName (pCfgDataDesc->pSetArray, SetValue, (const char **) &pSetString)) if (pSetString == NULL) sprintf (pBuff, "Set str unknown for value %d", SetValue); else sprintf (pBuff, "%s", pSetString); break; case CFGTYPE_HMS: Hms = (*(int *)pCfgDataDesc->DestAddr); sprintf (pBuff, "%02d:%02d:%02d", Hms/3600, (Hms/60)%60, Hms%60); break; case CFGTYPE_NULL: break; default: return TOOLCFG_ERROR_INVALID_CFGTYPE; } } return NO_ERROR; } APIRET ToolCfgPrintParamContents (t_pToolCfgParamDesc pParamDescArray, t_pchar pName, t_pchar pBuff) { t_pToolCfgParamDesc pCfgParamDesc; t_pToolCfgDataDesc pCfgDataDesc; t_int i; if (pBuff) pBuff[0] = '\0'; for (i=0; ;i++) { pCfgParamDesc = &pParamDescArray[i]; pCfgDataDesc = &pCfgParamDesc->DataDesc; if (pCfgDataDesc->pName == NULL) return TOOLCFG_ERROR_UNKNOWN_PARAMETER; if (ToolCfgStrCmpNoCase (pCfgDataDesc->pName, pName) == 0) { if (pBuff) CFG_CHK_APP (ToolCfgPrintContents (pBuff, pCfgParamDesc)) break; } } return NO_ERROR; } /* ToolCfgLogConfiguration: Write all the configuration parameters with their values to the log file */ APIRET ToolCfgLogConfiguration (t_pToolCfgParamDesc pParamDescArray) { t_pToolCfgParamDesc pCfgParamDesc; t_pToolCfgDataDesc pCfgDataDesc; t_pchar pBuff; t_int i, Err; t_int wr; CFG_CHK_APP (ToolCfgMemAlloc ((void **)&pBuff, 4096, MEM_OPT_NONE, MemIdCfgLogConfiguration)) Err = FALSE; for (i=0; ;i++) { pCfgParamDesc = &pParamDescArray[i]; pCfgDataDesc = &pCfgParamDesc->DataDesc; if (pCfgDataDesc->pName == NULL) break; /* end of array reached */ if (( pCfgParamDesc->CfgAssignments == 0 ) && ( pCfgParamDesc->CmdAssignments == 0 ) && ( pCfgParamDesc->DataDesc.CfgType != CFGTYPE_NULL ) && ( pCfgParamDesc->DataDesc.CfgType != CFGTYPE_PRESENCE) && // Parameters of type 'presence' are always optional ((pCfgParamDesc->Assign & CFGASN_OPTIONAL) == 0 )) { CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Parameter %s has not been initialized.", pCfgDataDesc->pName)) Err = TRUE; } else { wr = sprintf (pBuff, "%s = ", pCfgDataDesc->pName); CFG_CHK_APP (ToolCfgPrintContents (&pBuff[wr], pCfgParamDesc)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "%s", pBuff)) } } CFG_CHK_APP (ToolCfgMemFree (pBuff, MemIdCfgLogConfiguration)) if (Err) return TOOLCFG_ERROR_CONFIG_ERROR; return NO_ERROR; } /* ToolCfgResetAssignCounters: Reset all assignment counters for all keywords */ static APIRET ToolCfgResetAssignCounters (t_pToolCfgParamDesc pParamDescArray) { t_int i; for (i=0; ; i++) { if (pParamDescArray[i].DataDesc.pName == NULL) break; /* end of array reached */ pParamDescArray[i].CmdAssignments = 0; pParamDescArray[i].CfgAssignments = 0; } return NO_ERROR; } /* CfgGetCmdLineOption: Read an option from the command line. This function is */ /* usually called to get the configuration or log file name. */ APIRET ToolCfgGetCmdLineOption (t_pcchar pParamName, t_pcchar *ppValue) { t_int i, Eq; t_int LineLen = 0; t_pchar pNextChar = NULL; t_ToolCfgContext CfgContext; *ppValue = NULL; Eq = 0; for (i=1; i 0) && (LineFlag)) { LineLen = (t_int) strlen (pRemark); rcp = fprintf (pFile, "\r\n%*s%s ", Indent, "", KEYWORD_REMARK); CFG_CHK_FPRINTF(rcp) for (i=0; ipName == NULL) break; /* end of array reached */ Source = (t_ToolCfgAssignment) (pParamDescArray[i].Assign & CFGASN_SOURCE); if (((Source & CFGASN_CMD) && !(Source & CFGASN_CFG) && (CfgParams == FALSE)) || ((Source & CFGASN_CFG) && (CfgParams == TRUE ))) { CFG_CHK_APP (ToolCfgBuildHelp (pCfgDataDesc, NULL, &Len)) CFG_CHK_APP (ToolCfgMemAlloc ((void **)&pTmp1, (t_uint)Len, MEM_OPT_NONE, MemIdCfgHelpBuff)) CFG_CHK_APP (ToolCfgBuildHelp (pCfgDataDesc, pTmp1, &Len)) CFG_CHK_FPRINTF (fprintf (pFile, "\r\n %s", pTmp1)) CFG_CHK_APP (ToolCfgMemFree (pTmp1, MemIdCfgHelpBuff)) (*pEntries)++; } } } if (CfgParams && pTableDescArray) { for (i=0; ; i++) { pCfgTableDesc = &pTableDescArray[i]; if (pCfgTableDesc->pTableType == NULL) break; /* end of array reached */ CFG_CHK_APP (ToolCfgBuildTableHelp (pCfgTableDesc, NULL, NULL, &Len)) CFG_CHK_APP (ToolCfgMemAlloc ((void **)&pTmp1, (t_uint)Len, MEM_OPT_NONE, MemIdCfgHelpBuff)) CFG_CHK_APP (ToolCfgMemAlloc ((void **)&pTmp2, (t_uint)Len, MEM_OPT_NONE, MemIdCfgHelpBuff)) CFG_CHK_APP (ToolCfgBuildTableHelp (pCfgTableDesc, pTmp1, pTmp2, &Len)) CFG_CHK_FPRINTF (fprintf (pFile, "\r\n\r\n %s %s ", KEYWORD_TABLESTART, pCfgTableDesc->pTableType)) CFG_CHK_APP (ToolCfgEnterRemark (pFile, pTmp1, 6, TRUE )) CFG_CHK_APP (ToolCfgEnterRemark (pFile, pTmp2, 6, FALSE)) CFG_CHK_FPRINTF (fprintf (pFile, "\r\n %s", KEYWORD_TABLEEND)) CFG_CHK_APP (ToolCfgMemFree (pTmp1, MemIdCfgHelpBuff)) CFG_CHK_APP (ToolCfgMemFree (pTmp2, MemIdCfgHelpBuff)) (*pEntries)++; } } return NO_ERROR; } APIRET ToolCfgBuildTemplate (t_pcchar pFileName, t_pcchar pComment, t_pcchar pSectionName, t_ToolCfgParamDesc *pParamDescArray, t_ToolCfgTableDesc *pTableDescArray) { FILE *pFile; t_int Entries, rc; t_pchar pTmp; const t_int TmpLen = 256; struct tm *NowTM; time_t NowT; pFile = fopen(pFileName, "wb"); if (pFile == NULL) return TOOLCFG_ERROR_TEMPLATE_OPEN_FAILED; setbuf (pFile, NULL); CFG_CHK_APP (ToolCfgMemAlloc ((void **)&pTmp, TmpLen, MEM_OPT_NONE, MemIdCfgTemplateHeader)) (void) time (&NowT); NowTM = localtime (&NowT); rc = sprintf (pTmp, "Configuration file template, created on "); (void) strftime (pTmp+rc, (size_t)(TmpLen-rc), "%d/%m/%Y %H:%M:%S", NowTM); CFG_CHK_APP (ToolCfgEnterRemark (pFile, pTmp, 0, TRUE)) CFG_CHK_APP (ToolCfgMemFree (pTmp, MemIdCfgTemplateHeader)) if(pComment) CFG_CHK_APP (ToolCfgEnterRemark (pFile, pComment, 0, TRUE)) if (pSectionName) CFG_CHK_FPRINTF (fprintf (pFile, "\r\n\r\n%s %s\r\n", KEYWORD_SECTIONSTART, pSectionName)) CFG_CHK_APP (ToolCfgBuildTemplate0 (pFile, TRUE, &Entries, pParamDescArray, pTableDescArray)) if (pSectionName) CFG_CHK_FPRINTF (fprintf (pFile, "\r\n\r\n%s", KEYWORD_SECTIONEND)) CFG_CHK_APP (ToolCfgEnterEmptyLine (pFile)) CFG_CHK_APP (ToolCfgEnterRemark (pFile, "Options, that can only be entered on command line", 0, TRUE)) CFG_CHK_APP (ToolCfgBuildTemplate0 (pFile, FALSE, &Entries, pParamDescArray, pTableDescArray)) if (Entries == 0) CFG_CHK_APP (ToolCfgEnterRemark (pFile, "There are no such options", 0, FALSE)) CFG_CHK_APP (ToolCfgEnterEmptyLine (pFile)) CFG_CHK_APP (ToolCfgEnterEmptyLine (pFile)) rc = fclose(pFile); if (rc) return TOOLCFG_ERROR_CLOSE_FAILED; return NO_ERROR; } /* ToolCfgSetErrLogFn: The application can specify the desired logging */ /* function here (for example vprintf, or an own function). */ APIRET ToolCfgSetLogFn (t_pToolCfgUserLogFn pUserLogFn) { ToolCfgLocal.pUserLogFn = pUserLogFn; return NO_ERROR; } APIRET ToolCfgGetSetString (t_pToolCfgSet pSetArray, int SetValue, const char **ppSetString) { t_pToolCfgSet pSet; *ppSetString = NULL; for (pSet = &pSetArray[0]; pSet->pSetString != NULL; pSet++) { if (pSet->SetValue == SetValue) { *ppSetString = pSet->pSetString; break; } } return NO_ERROR; } /* ------------------------------ */ /* Module initialisation */ /* ------------------------------ */ static int IsInit = 0; APIRET ToolCfgInit (int argc, char *argv[]) { if(IsInit == 1) return NO_ERROR; IsInit = 1; CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (ERROR_BASE_TOOL_CFG )) CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (TOOLCFG_ERROR_OPEN_FAILED )) CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (TOOLCFG_ERROR_READ_FAILED )) CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (TOOLCFG_ERROR_CLOSE_FAILED )) CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (TOOLCFG_ERROR_SEEKEND_FAILED )) CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (TOOLCFG_ERROR_SEEKSET_FAILED )) CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (TOOLCFG_ERROR_INVALID_STATE )) CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (TOOLCFG_ERROR_NAME_TOO_LONG )) CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (TOOLCFG_ERROR_INCLUDE_NESTING_OVERFLOW )) CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (TOOLCFG_ERROR_CONFIG_ERROR )) CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (TOOLCFG_ERROR_INVALID_ASSIGNMENT_OPTION)) CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (TOOLCFG_ERROR_INVALID_CFGTYPE )) CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (TOOLCFG_ERROR_TEMPLATE_OPEN_FAILED )) CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (TOOLCFG_ERROR_FPRINTF_FAILED )) CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (TOOLCFG_ERROR_CMDLINE_OPTION_NOT_FOUND )) CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (TOOLCFG_ERROR_MALLOC_FAILED )) CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (TOOLCFG_ERROR_SECTIONNAME_TOO_LONG )) CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (TOOLCFG_ERROR_TOO_MANY_SECTIONNAMES )) CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (TOOLCFG_ERROR_SECTIONNAME_NOTFOUND )) CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (TOOLCFG_ERROR_UNKNOWN_PARAMETER )) CFG_CHK_APP (MEM_REGISTER_MEMID (MemIdCfgBuffer )) CFG_CHK_APP (MEM_REGISTER_MEMID (MemIdCfgErrorHeader )) CFG_CHK_APP (MEM_REGISTER_MEMID (MemIdCfgContextStack )) CFG_CHK_APP (MEM_REGISTER_MEMID (MemIdCfgTemplateHeader )) CFG_CHK_APP (MEM_REGISTER_MEMID (MemIdCfgHelpBuff )) CFG_CHK_APP (MEM_REGISTER_MEMID (MemIdCfgHelpString )) CFG_CHK_APP (MEM_REGISTER_MEMID (MemIdCfgHelpInt )) CFG_CHK_APP (MEM_REGISTER_MEMID (MemIdCfgHelpTable )) CFG_CHK_APP (MEM_REGISTER_MEMID (MemIdCfgTableType )) CFG_CHK_APP (MEM_REGISTER_MEMID (MemIdCfgTableName )) CFG_CHK_APP (MEM_REGISTER_MEMID (MemIdCfgLogConfiguration)) ToolCfgLocal.argc = argc; ToolCfgLocal.argv = argv; ToolCfgLocal.pUserLogFn = NULL; ToolCfgLocal.MaxIncludeNestingLevel = MAX_CFG_NESTING_LEVEL; memset (&ToolCfgLocal.GlobalSectionNameArr[0], 0, sizeof (ToolCfgLocal.GlobalSectionNameArr)); return NO_ERROR; } APIRET ToolCfgUseAdjustedCommandLine (int argc, char *argv[]) { ToolCfgLocal.argc = argc; ToolCfgLocal.argv = argv; return NO_ERROR; } APIRET ToolCfgDeInit (void) { if(IsInit == 0) return NO_ERROR; CFG_CHK_APP (ToolCfgFreeContextBuffers ()) IsInit = 0; return NO_ERROR; } libguytools2-2.0.1/toolerror.cpp000066400000000000000000000210261140544147500167110ustar00rootroot00000000000000// **************************************************************************** // Project: libguytools // **************************************************************************** // Programmer: Guy Voncken // Police Grand-Ducale // Service de Police Judiciaire // Section Nouvelles Technologies // **************************************************************************** // Module: Error handling // **************************************************************************** #include #include #include #include #include "toolconstants.h" #include "toolglobalid.h" #include "toolerror.h" /* ------------------------------ */ /* Type & structure definitions */ /* ------------------------------ */ typedef struct { int ErrorCode; const char *pMsg; } t_ToolErrorEntry, *t_pToolErrorEntry; typedef struct { t_pToolErrorLogFn pLogFn; t_pToolErrorEntry pErrorCodeArr; int ErrorCodeArrEntries; int ErrorCodeArrLen; } t_ToolErrorLocal; /* ------------------------------ */ /* Variables */ /* ------------------------------ */ static t_ToolErrorLocal ToolErrorLocal; static int Initialised = FALSE; APIRET ToolErrorLog (const char *pFileName, const char *pFunctionName, int LineNr, const char * pFormat, ...) { va_list VaList; va_start(VaList, pFormat); if (ToolErrorLocal.pLogFn != NULL) { ToolErrorLocal.pLogFn (pFileName, pFunctionName, LineNr, pFormat, VaList); } else { printf ("\nError in %s, %s, %d:", pFileName, pFunctionName, LineNr); vprintf (pFormat, VaList); } va_end(VaList); return NO_ERROR; } /* ------------------------------ */ /* Functions */ /* ------------------------------ */ static APIRET ToolErrorFindEntry (int ErrorCode, t_pToolErrorEntry *ppEntry) { t_pToolErrorEntry pEntry = NULL; int i; for (i=0; iErrorCode == ErrorCode) break; } if (i >= ToolErrorLocal.ErrorCodeArrEntries) return TOOL_ERROR_ENTRY_NOT_FOUND; if (ppEntry) *ppEntry = pEntry; return NO_ERROR; } APIRET ToolErrorRegisterError (int ErrorCode, const char *pMsg) { t_pToolErrorEntry pEntry; if (Initialised == FALSE) return TOOL_ERROR_NOT_INITIALISED; APIRET rc = ToolErrorFindEntry (ErrorCode, NULL); if (rc == TOOL_ERROR_ENTRY_NOT_FOUND) { pEntry = &(ToolErrorLocal.pErrorCodeArr[ToolErrorLocal.ErrorCodeArrEntries++]); pEntry->ErrorCode = ErrorCode; pEntry->pMsg = pMsg; } else { ToolErrorLog (__FFL__, "Duplicate ErrorCode %d", ErrorCode); return TOOL_ERROR_DUPLICATE_ENTRY; } return NO_ERROR; } APIRET ToolErrorGetMessage (int ErrorCode, const char **ppMsg) { if (ErrorCode == NO_ERROR) { *ppMsg = "NO_ERROR"; } else { t_pToolErrorEntry pEntry; APIRET rc = ToolErrorFindEntry (ErrorCode, &pEntry); if (rc == TOOL_ERROR_ENTRY_NOT_FOUND) *ppMsg = NULL; else *ppMsg = pEntry->pMsg; } return NO_ERROR; } const char *ToolErrorMessage (int ErrorCode) { static char TmpStr [20]; // Attention: This is not multi-threading compatible!! const char *pMsg; APIRET rc = ToolErrorGetMessage (ErrorCode, &pMsg); if (rc != NO_ERROR) { snprintf(TmpStr, sizeof(TmpStr), "[%d]", ErrorCode); pMsg = TmpStr; } return pMsg; } APIRET ToolErrorCheck (char const *pFileName, char const *pFunctionName, int LineNr, int ErrorCode) { const char *pMsg; if (ErrorCode == NO_ERROR) { ToolErrorLog (pFileName, pFunctionName, LineNr, "%s called with Rc=0", __FUNCTION__); } else { APIRET rc = ToolErrorGetMessage (ErrorCode, &pMsg); switch (rc) { case NO_ERROR: ToolErrorLog(pFileName, pFunctionName, LineNr, "Error %d: %s", ErrorCode, pMsg); break; case TOOL_ERROR_ENTRY_NOT_FOUND: ToolErrorLog(pFileName, pFunctionName, LineNr, "Error %d: -- unregistered error code --", ErrorCode); break; default: ToolErrorLog(__FFL__, "Unexpected internal error %ld...", rc); ToolErrorLog(__FFL__, "...while trying to log problem %d coming from %s/%s/%d", ErrorCode, pFileName, pFunctionName, LineNr); break; } } return NO_ERROR; } APIRET ToolErrorSetLogFn (t_pToolErrorLogFn pLogFn) { ToolErrorLocal.pLogFn = pLogFn; return NO_ERROR; } const char *ToolErrorTranslateErrno (int Errno) { const char *pTxt; switch (Errno) { case EPERM : pTxt = "Operation not permitted"; break; case ENOENT : pTxt = "No such file or directory"; break; case ESRCH : pTxt = "No such process"; break; case EINTR : pTxt = "Interrupted system call"; break; case EIO : pTxt = "I/O error"; break; case ENXIO : pTxt = "No such device or address"; break; case E2BIG : pTxt = "Argument list too long"; break; case ENOEXEC: pTxt = "Exec format error"; break; case EBADF : pTxt = "Bad file number"; break; case ECHILD : pTxt = "No child processes"; break; case EAGAIN : pTxt = "Try again"; break; case ENOMEM : pTxt = "Out of memory"; break; case EACCES : pTxt = "Permission denied"; break; case EFAULT : pTxt = "Bad address"; break; case ENOTBLK: pTxt = "Block device required"; break; case EBUSY : pTxt = "Device or resource busy"; break; case EEXIST : pTxt = "File exists"; break; case EXDEV : pTxt = "Cross-device link"; break; case ENODEV : pTxt = "No such device"; break; case ENOTDIR: pTxt = "Not a directory"; break; case EISDIR : pTxt = "Is a directory"; break; case EINVAL : pTxt = "Invalid argument"; break; case ENFILE : pTxt = "File table overflow"; break; case EMFILE : pTxt = "Too many open files"; break; case ENOTTY : pTxt = "Not a typewriter"; break; case ETXTBSY: pTxt = "Text file busy"; break; case EFBIG : pTxt = "File too large"; break; case ENOSPC : pTxt = "No space left on device"; break; case ESPIPE : pTxt = "Illegal seek"; break; case EROFS : pTxt = "Read-only file system"; break; case EMLINK : pTxt = "Too many links"; break; case EPIPE : pTxt = "Broken pipe"; break; case EDOM : pTxt = "Math argument out of domain of func"; break; case ERANGE : pTxt = "Math result not representable"; break; default : pTxt = "toolerror.coo: None of the standard error codes"; break; } return pTxt; } /* --------------------------------------------------------------------------------- */ /* Module initialisation */ /* --------------------------------------------------------------------------------- */ APIRET ToolErrorInit (int MaxErrors) { if (Initialised == TRUE) return TOOL_ERROR_ALREADY_INITIALISED; ToolErrorLocal.pErrorCodeArr = (t_pToolErrorEntry) malloc (MaxErrors * sizeof(t_ToolErrorEntry)); ToolErrorLocal.ErrorCodeArrLen = MaxErrors; ToolErrorLocal.ErrorCodeArrEntries = 0; Initialised = TRUE; return NO_ERROR; } APIRET ToolErrorDeInit () { if (Initialised == FALSE) return TOOL_ERROR_NOT_INITIALISED; free (ToolErrorLocal.pErrorCodeArr); ToolErrorLocal.pLogFn = NULL; Initialised = FALSE; return NO_ERROR; } libguytools2-2.0.1/toollog.cpp000077500000000000000000000106751140544147500163540ustar00rootroot00000000000000// **************************************************************************** // Project: libguytools // **************************************************************************** // Programmer: Guy Voncken // Police Grand-Ducale // Service de Police Judiciaire // Section Nouvelles Technologies // **************************************************************************** // Module: Log utility // **************************************************************************** #ifndef _FILE_OFFSET_BITS #define _FILE_OFFSET_BITS 64 #endif #include #include #include #include #include #include #include #include #include "toolglobalid.h" #include "toolerror.h" #include "toollog.h" // ----------- // Constants // ----------- const char * LogLevelLookup [t_Log::Entries] = {"Debug", "Info", "Error"}; const int LOG_HEADER_LEN = 75; const char LibGuyToolsVersion[] = LIBGUYTOOLS_VERSION; // ----------------- // Local variables // ----------------- static bool LogInitialised = false; static QMutex LogMutex; static char *pLogFilename; static char LogLineHeader[512]; t_Log::t_Log (const char* pFileName, APIRET &rc) { if (!LogInitialised) { LogInitialised = true; pLogFilename = (char *) malloc (strlen (pFileName)+1); strcpy (pLogFilename, pFileName); Entry (Info, __FFL__, "Log file opened"); rc = NO_ERROR; } else { rc = TOOLLOG_ERROR_INITIALISED_TWICE; } } t_Log::~t_Log(void) { Entry (Info, __FFL__, "Log file closed"); free (pLogFilename); LogInitialised = false; } bool t_Log::IsInitialised (void) { return LogInitialised; } void t_Log::GetLibGuyToolsVersion (const char **pVersion) { *pVersion = LibGuyToolsVersion; } void t_Log::vEntry (t_Level Level, const char *pFileName, const char *pFunctionName, int LineNr, const char *pFormat, va_list pArguments) { time_t NowT; struct tm *pNowTM; FILE *pFile; int wr; static bool LogFileError = false; // Variable prevents us from repetitive log error messages time (&NowT); pNowTM = localtime (&NowT); LogMutex.lock(); wr = strftime (&LogLineHeader[0] , sizeof(LogLineHeader) , "%a %d.%b.%Y %H:%M:%S ", pNowTM); wr += snprintf (&LogLineHeader[wr], sizeof(LogLineHeader)-wr, "%08X ", (unsigned int)pthread_self()); // wr += snprintf (&LogLineHeader[wr], sizeof(LogLineHeader)-wr, "%4d ", getpid()); // getpid returns alyways the same number if (pFileName && pFunctionName) wr += snprintf (&LogLineHeader[wr], sizeof(LogLineHeader)-wr, "%s %s %d", pFileName, pFunctionName, LineNr); while (wr < LOG_HEADER_LEN) LogLineHeader[wr++] = ' '; snprintf (&LogLineHeader[wr], sizeof(LogLineHeader)-wr, "%-5s - ", LogLevelLookup[Level]); if (LogInitialised) { pFile = fopen64 (pLogFilename, "a"); if (pFile == NULL) { if (!LogFileError) printf ("\nLog file error: Can't be opened"); LogFileError = true; } else { LogFileError = false; fprintf (pFile, "%s", &LogLineHeader[0]); vfprintf (pFile, pFormat, pArguments); fprintf (pFile, "\n"); fclose (pFile); } } if (!LogInitialised || (pFile == NULL)) { printf ("\n"); printf ("%s", &LogLineHeader[0]); vprintf (pFormat, pArguments); } LogMutex.unlock(); } void t_Log::Entry (t_Level Level, const char *pFileName, const char *pFunctionName, int LineNr, const char *pFormat, ...) { va_list VaList; va_start(VaList, pFormat); vEntry (Level, pFileName, pFunctionName, LineNr, pFormat, VaList); va_end(VaList); } void t_Log::vEntryInfo (const char *pFileName, const char *pFunctionName, int LineNr, const char *pFormat, va_list pArguments) { vEntry (Info, pFileName, pFunctionName, LineNr, pFormat, pArguments); } void t_Log::vEntryDebug (const char *pFileName, const char *pFunctionName, int LineNr, const char *pFormat, va_list pArguments) { vEntry (Debug, pFileName, pFunctionName, LineNr, pFormat, pArguments); } void t_Log::vEntryError (const char *pFileName, const char *pFunctionName, int LineNr, const char *pFormat, va_list pArguments) { vEntry (Error, pFileName, pFunctionName, LineNr, pFormat, pArguments); } libguytools2-2.0.1/tools.pro000066400000000000000000000016761140544147500160510ustar00rootroot00000000000000TEMPLATE = lib DESTDIR = ./lib TARGET = guytools include( ./libguytools_version.pro.inc ) # The following line allows the software to see its own version # (just for logging purpose). Many slashes and quotes... look at # result of it during compilation DEFINES += "LIBGUYTOOLS_VERSION=\\\""$$VERSION"\\\"" # Use the standard Qt configuration but remove the GUI part, as we do not need it. CONFIG += qt QT -= gui CONFIG += warn_on thread release DEFINES += TOCFG_COMPILE_FOR_USE_WITHOUT_TOOLBOX DEPENDPATH += ./include INCLUDEPATH += ./include QMAKE_CXXFLAGS_WARN_ON += -Wno-strict-aliasing # Switch off warning "dereferencing type-punned pointer will break strict-aliasing rules" QMAKE_CXXFLAGS_WARN_ON += -fmessage-length=0 # Tell g++ not to split messages into different lines QMAKE_CXXFLAGS_RELEASE += -O3 SOURCES += toollog.cpp SOURCES += toolerror.cpp SOURCES += toolsysinfo.cpp SOURCES += toolsignal.cpp SOURCES += toolcfg.cpp libguytools2-2.0.1/toolsignal.cpp000066400000000000000000000234741140544147500170460ustar00rootroot00000000000000// **************************************************************************** // Project: libguytools // **************************************************************************** // Programmer: Guy Voncken // Police Grand-Ducale // Service de Police Judiciaire // Section Nouvelles Technologies // **************************************************************************** // Module: Signal handler with backtrace // **************************************************************************** #include #include #include //#define __USE_GNU #include #include //#define __USE_XOPEN #include #include #include #include "tooltypes.h" #include "toolglobalid.h" #include "toolsignal.h" #include "toolerror.h" // ------------------------------------ // Constants // ------------------------------------ #define __FFL__ (char *) __FILE__, (char *)__FUNCTION__, __LINE__ // ------------------------------------ // Type definitions // ------------------------------------ typedef struct { t_pToolSignalLogFn pLogFn; t_pToolSignalHandler pSignalHandlerFn; struct sigaction SignalActionDefault; } t_ToolSignalLocal; // ------------------------------------ // Module variables // ------------------------------------ bool ToolSignalInitialised = false; t_ToolSignalLocal ToolSignalLocal; // ------------------------------------ // Log functions // ------------------------------------ static int ToolSignalLogEntry (bool Error, const char *pFileName, const char *pFunctionName, int LineNr, const char *pFormat, ...) { va_list VaList; va_start(VaList, pFormat); if (ToolSignalLocal.pLogFn) { (*ToolSignalLocal.pLogFn)(Error, pthread_self(), pFileName, pFunctionName, LineNr, pFormat, VaList); } else { printf ("\n"); vprintf (pFormat, VaList); } va_end(VaList); return NO_ERROR; } // ------------------------------------ // Main functions // ------------------------------------ static void ToolSignalStandardSet (sigset_t *pSignalSet) { sigfillset (pSignalSet); // Add all known signals to set, except the ones listed below: sigdelset (pSignalSet, SIGSEGV); // - handled by our backtrace function, see below sigdelset (pSignalSet, SIGPIPE); // - which would cause problems in ceratin situations when our program deals with pipes sigdelset (pSignalSet, SIGWINCH); // - emitted on window resize sigdelset (pSignalSet, SIGCHLD); // - QProcess relies on receiving this one in order to know when a child process finishes } // These settings will be valid for the current thread and all its children threads. That's the reason, why // ToolSignalInit should be called in the application main thread before starting any other thread. static void *ToolSignalThread (void *p) { sigset_t SignalSet; int Signal; bool Exit; char *pSignalName; p=p; // Dummy statement to avoid compiler warning about unused p ToolSignalLogEntry (false, __FFL__, "Signal guard thread started with id %d", getpid()); Exit = false; while (!Exit) { ToolSignalStandardSet (&SignalSet); sigwait (&SignalSet, &Signal); // wait for any signal in given set // when we get here, we've caught a signal // --------------------------------------- pSignalName = strsignal(Signal); ToolSignalLogEntry (true, __FFL__, "Thread (%d-%d): Caught signal: %s", getpid(), pthread_self(), pSignalName); if (ToolSignalLocal.pSignalHandlerFn) (*ToolSignalLocal.pSignalHandlerFn) (Signal); switch (Signal) { case SIGTERM: case SIGINT : Exit = true; break; default: break; } } ToolSignalLogEntry (true, __FFL__, "Stopping signal guard thread."); return NULL; } // ToolSignalBacktraceHandler is called by any // thread in the program causing a segment violation. static void ToolSignalBacktraceHandler (int Signal, siginfo_t *pSignalInfo, void *pSecret) { const int TraceArrLen = 50; char **ppMessages; void *TraceArr[TraceArrLen]; int TraceSize; int i; static int RecursiveCallDetection = 0; void *pIP = NULL; #if defined(__sparc__) struct sigcontext* pSigContext = (struct sigcontext*) pSecret; #if __WORDSIZE == 64 pIP = (void*) pSigContext->sigc_regs.tpc ; #else pIP = (void*) pSigContext->si_regs.pc ; #endif #else ucontext_t* pUContext = (ucontext_t*) pSecret; #if defined(__i386__) pIP = (void*) pUContext->uc_mcontext.gregs[REG_EIP]; #elif defined(__x86_64__) pIP = (void*) pUContext->uc_mcontext.gregs[REG_RIP]; #elif defined(__hppa__) pIP = (void*) pUContext->uc_mcontext.sc_iaoq[0] & ~0x3UL; #elif (defined (__ppc__)) || (defined (__powerpc__)) pIP = (void*) pUContext->uc_mcontext.regs->nip; #endif #endif RecursiveCallDetection++; switch (RecursiveCallDetection) { case 1: ppMessages = NULL; ToolSignalLogEntry (true, __FFL__, "----------------------------------------------------------------------"); if (Signal == SIGSEGV) { ToolSignalLogEntry (true, __FFL__, "Thread (%d-%d): Got signal '%s' (%d), faulty address is %p, from %p", getpid(), pthread_self(), strsignal(Signal), Signal, pSignalInfo->si_addr, pIP); } else { ToolSignalLogEntry (true, __FFL__, "Thread (%d-%d): Got signal '%s' (%d) -- strange, function should only be called on SIGSEGV.", getpid(), pthread_self(), strsignal(Signal), Signal); } TraceSize = backtrace (TraceArr, TraceArrLen); TraceArr[1] = pIP; ppMessages = backtrace_symbols (TraceArr, TraceSize); ToolSignalLogEntry (true, __FFL__, "Backtrace execution path:"); for (i=1; i #include #include #include #include #include #include #include #include //#include #include #include "toolconstants.h" #include "toolglobalid.h" #include "toolerror.h" #include "toolsysinfo.h" // ------------------------------------ // Constants // ------------------------------------ // ------------------------------------ // Type definitions // ------------------------------------ // ------------------------------------ // Local variables // ------------------------------------ static bool ToolSysInfoInitialized = false; // ------------------------------------ // Functions // ------------------------------------ APIRET ToolSysInfoGetMacAddr (t_pToolSysInfoMacAddr pMacAddr) { struct ifreq Ifr; struct ifreq *pIfr; struct ifconf Ifc; char buf[1024]; int s, i, wr; bool ok = false; s = socket(AF_INET, SOCK_DGRAM, 0); if (s==-1) return TOOLSYSINFO_ERROR_SOCKET; Ifc.ifc_len = sizeof(buf); Ifc.ifc_buf = buf; ioctl(s, SIOCGIFCONF, &Ifc); pIfr = Ifc.ifc_req; for (i = Ifc.ifc_len / sizeof(struct ifreq); --i >= 0; pIfr++) { strcpy (Ifr.ifr_name, pIfr->ifr_name); if (ioctl (s, SIOCGIFFLAGS, &Ifr) == 0) { if (! (Ifr.ifr_flags & IFF_LOOPBACK)) { if (ioctl(s, SIOCGIFHWADDR, &Ifr) == 0) { ok = true; break; } } } } close(s); if (!ok) return TOOLSYSINFO_ERROR_NO_ADDR; bcopy (Ifr.ifr_hwaddr.sa_data, &pMacAddr->AddrVal[0], TOOLSYSINFO_MACADDRLEN_VAL); wr = 0; for (int i=0; iAddrStr[wr], "%02X", pMacAddr->AddrVal[i]); return NO_ERROR; } APIRET ToolSysInfoUname (QString &Uname) { struct utsname name; if (uname (&name) == -1) return TOOLSYSINFO_ERROR_UNAME; Uname = QString(name.sysname) + " " + name.nodename + " " + name.release + " " + name.version + " " + name.machine; return NO_ERROR; } // ------------------------------ // Module initialisation // ------------------------------ APIRET ToolSysInfoInit (void) { if (ToolSysInfoInitialized) return TOOLSYSINFO_ALREADY_INITIALISED; TOOL_CHK (TOOL_ERROR_REGISTER_CODE (ERROR_BASE_TOOL_SYSINFO)) TOOL_CHK (TOOL_ERROR_REGISTER_CODE (TOOLSYSINFO_ALREADY_INITIALISED)) TOOL_CHK (TOOL_ERROR_REGISTER_CODE (TOOLSYSINFO_ERROR_SOCKET)) TOOL_CHK (TOOL_ERROR_REGISTER_CODE (TOOLSYSINFO_ERROR_NO_ADDR)) TOOL_CHK (TOOL_ERROR_REGISTER_CODE (TOOLSYSINFO_ERROR_UNAME)) ToolSysInfoInitialized = true; return NO_ERROR; } APIRET ToolSysInfoDeInit (void) { return NO_ERROR; } libguytools2-2.0.1/trunk.pro000066400000000000000000000000301140544147500160330ustar00rootroot00000000000000include( ./tools.pro )