Commit bec71ca2 authored by 杨军's avatar 杨军
Browse files

增加初始文件,建立项目骨架

parents
Tony <Tony@eztor.com>
2014-03-10 23:32 Tony
1.Add automake autoconf project files;
2.Add ParkServer project tree.
\ No newline at end of file
AUTOMAKE_OPTIONS=
SUBDIRS=src
default: all
all:
aclocal
autoheader
automake --add-missing
autoconf
ParkServer项目简介:
ParkServer是为了停车管理系统的设备管理而设计的,它包括:
1、停车管理服务器:负责连接无线中继、管理终端、巡检平板等设备。提供管理云服务;
2、停车管理客户端:用于无线中继、管理终端和巡检平板,与停车管理服务端进行通讯的模块。
停车管理服务端:
启动方式:
ParkService --config:/etc/psr/psrservice.conf -d
ParkService --config:/etc/psr/psrservice.conf --cmd:reload 通知重新应用配置
ParkService --config:/etc/psr/psrservice.conf --cmd:quit 通知退出服务
ParkService --config:/etc/psr/psrservice.conf --cmd:xxxx 通知服务程序解析命令xxxx
其他程序可以通过127.0.0.1:5000或者/tmp/psrfifo发送cmd,端口和FIFO地址可以在配置文件中配置
停车管理客户端:
启动方式:
#define PSR_POS_FLAG 0
#define PSR_POS_IDENT 1
#define PSR_POS_CMDTYPE 2
#define PSR_POS_TYPE 3
#define PSR_POS_DATALEN 4
#define PSR_POS_DATA 6
通讯数据格式:
flag : 偏移地址0长度1字节,数据包引导符0xFB
ident : 偏移地址1长度1字节,数据包的标识,方便处理重复数据包
cmd : 偏移地址2长度1字节,命令类型,系统将根据命令的类型做相应的预处理,0x10以下的命令保留,具体业务命令须大于0x10
fmt : 偏移地址3长度1字节,数据包的处理方式,0x10=http,0x11=xml,0x12=json,0x13=radius
len : 偏移地址4长度2字节,数据包长度,网络字节序整数
data : 偏移地址6长度len字节
CRC : 1字节(可选),data校验和
eflag : 1字节(可选),0xFE
\ No newline at end of file
AC_PREREQ(2.59)
AC_INIT([PSUart],[0.5],[Objective Systems <tony@eztor.com>],[PSUart])
PACKAGE=psuart
VERSION=0.1
AC_CONFIG_AUX_DIR(config)
AM_INIT_AUTOMAKE([1.9 tar-pax])
AM_INIT_AUTOMAKE($PACKAGE, $VERSION)
AC_CONFIG_SRCDIR([src])
AC_CONFIG_HEADERS([config.h])
dnl should include it in src files before using here
PROJECTDIR=`pwd`
AC_SUBST(PROJECTDIR)
if test "x$prefix" = "xNONE"; then
INSTALLPREFIX=.
else
INSTALLPREFIX="${prefix}"
fi
AC_SUBST(INSTALLPREFIX)
#Find psrlib path and read version
PSRLIB_INC="$PROJECTDIR/inc"
psr_location="/usr/include /usr/local/include $PROJECTRDIR/inc $PROJECTRDIR/src/include"
for al in $psr_location
do
AC_CHECK_FILE($al/psuservice.h)
if [[ -f "$al/psuservice.h" ]]
then
PSR_INC=$al
fi
AC_CHECK_FILE($al/psu_ver.h)
if [[ -f "$al/psu_ver.h" ]]
then
PSRLIB_VERSION=`grep "PSRLIB_VERSION \"" $al/psu_ver.h | cut -f3 -d ' ' | sed -e 's/"//g'`
PSRLIB_MAJOR_VERSION=`echo ${PSRLIB_VERSION} | cut -f1 -d.`
PSRLIB_MINOR_VERSION=`echo ${PSRLIB_VERSION} | cut -f2 -d.`
PSRLIB_BUILD_VERSION=`echo ${PSRLIB_VERSION} | cut -f3 -d.`
let PSRLIB_VER=${PSRLIB_MAJOR_VERSION}*10000+${PSRLIB_MINOR_VERSION}*100+${PSRLIB_BUILD_VERSION}
echo "PSRLIB_VER is ${PSRLIB_VER}"
fi
done
AC_SUBST(PSRLIB_INC)
AC_CHECK_FILE($PSRLIB_INC,, AC_MSG_ERROR([No psuservice.h found]))
DEBUG_THREADS="-DDUMP_SCHEDULER -DDEBUG_SCHEDULER -DDEBUG_THREADS -DDETECT_DEADLOCKS #-DDO_CRASH"
AC_SUBST(DEBUG_THREADS)
AC_PROG_CC
#AC_PROG_RANLIB # 这里的意义是:当你使用了静态库的时候,需要这一句
#AC_PROG_LIBTOOL # 如果你使用了共享库,那么使用AC_PROG_LIBTOOL
AC_LANG([C])
dnl not required as using libtool AC_PROG_RANLIB
AC_HEADER_STDC
AC_CHECK_HEADERS([netdb.h netinet/in.h stdlib.h string.h sys/socket.h sys/time.h unistd.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_TYPE_SIZE_T
AC_HEADER_TIME
AC_HEADER_DIRENT
AC_STRUCT_TM
dnl Checks for library functions.
#AC_FUNC_MALLOC
AC_FUNC_SELECT_ARGTYPES
AC_FUNC_STRFTIME
AC_FUNC_VPRINTF
AC_CHECK_FUNCS([localtime_r memmove memset select socket strcasecmp strchr strerror])
CFLAGS="$CFLAGS -I$PSRLIB_INC -I$PROJECTDIR/src/include"
AC_CONFIG_FILES([Makefile
src/Makefile
])
AC_OUTPUT
/* inih -- simple .INI file parser
inih is released under the New BSD license (see LICENSE.txt). Go to the project
home page for more info:
http://code.google.com/p/inih/
*/
#ifndef __INI_H__
#define __INI_H__
/* Make this header file easier to include in C++ code */
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
/* Parse given INI-style file. May have [section]s, name=value pairs
(whitespace stripped), and comments starting with ';' (semicolon). Section
is "" if name=value pair parsed before any section heading. name:value
pairs are also supported as a concession to Python's ConfigParser.
For each name=value pair parsed, call handler function with given user
pointer as well as section, name, and value (data only valid for duration
of handler call). Handler should return nonzero on success, zero on error.
Returns 0 on success, line number of first error on parse error (doesn't
stop on first error), -1 on file open error, or -2 on memory allocation
error (only when INI_USE_STACK is zero).
*/
int ini_parse(const char* filename,
int (*handler)(void* user, const char* section,
const char* name, const char* value),
void* user);
/* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't
close the file when it's finished -- the caller must do that. */
int ini_parse_file(FILE* file,
int (*handler)(void* user, const char* section,
const char* name, const char* value),
void* user);
/* Nonzero to allow multi-line value parsing, in the style of Python's
ConfigParser. If allowed, ini_parse() will call the handler with the same
name for each subsequent line parsed. */
#ifndef INI_ALLOW_MULTILINE
#define INI_ALLOW_MULTILINE 1
#endif
/* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of
the file. See http://code.google.com/p/inih/issues/detail?id=21 */
#ifndef INI_ALLOW_BOM
#define INI_ALLOW_BOM 1
#endif
/* Nonzero to use stack, zero to use heap (malloc/free). */
#ifndef INI_USE_STACK
#define INI_USE_STACK 1
#endif
/* Stop parsing on first error (default is to keep parsing). */
#ifndef INI_STOP_ON_FIRST_ERROR
#define INI_STOP_ON_FIRST_ERROR 0
#endif
/* Maximum line length for any line in INI file. */
#ifndef INI_MAX_LINE
#define INI_MAX_LINE 200
#endif
int read_profile_string( const char *section, const char *key,char *value, int size,const char *default_value, const char *file);
int read_profile_int( const char *section, const char *key,int default_value, const char *file);
int write_profile_string( const char *section, const char *key,const char *value, const char *file);
#ifdef __cplusplus
}
#endif
#endif /* __INI_H__ */
#ifndef __H_PSRS_H__
#define __H_PSRS_H__
#include "ini.h"
#include "utils.h"
#include "xLogMessage.h"
#define PSUSERVICE_TAG "PSUSERVICE"
/*定义本文件中使用的打印日志、告警和错误的宏
*/
#define psus_log(level,fmt, args...) LogMessage(level,__FILE__,__LINE__,PSUSERVICE_TAG,fmt,## args)
#define psus_error(fmt, args...) LogErrorMessage(__FILE__,__LINE__,PSUSERVICE_TAG,fmt,## args)
#define psus_warning(fmt, args...) LogWarningMessage(__FILE__,__LINE__,PSUSERVICE_TAG,fmt,## args)
#define IP2STR(ip) (ip>>24)&0xFF,(ip>>16)&0xFF,(ip>>8)&0xFF,ip&0xFF
/* define the config struct type */
typedef struct {
int flag; //日志输出类别
unsigned short minLevel; //日志级别的最小值
unsigned short maxLevel; //日志级别的最大值
int selectTimeout; //Select等待的超时时间
struct sockaddr_in net_addr; //提供服务的监听地址和端口
int uart_fd; //存储本地管理和接口命令的FIFO文件描述符
int net_fd; //存储服务监听的Socket文件描述符
#define CFG(s, n, default) char *s##_##n;
#include "psuservice.def"
} psus_config;
/* create one and fill in its default values */
psus_config Psus_Config_Default = {
#define CFG(s, n, default) default,
#include "psuservice.def"
};
typedef struct net_handle PSUSHANDLE;
psus_config *get_psus_data(void);
#endif //__H_PSRS_H__
#ifndef __APP_UTILS__
#define __APP_UTILS__
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <netinet/in.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifndef EZUTILS_API
#define EZUTILS_API
#endif
#define PATHSPLIT '/'
#define PATHSPLITS "/"
#define TRUE 1
#define FALSE 0
#define MAX_ARG_LEN 512 /*this define max argument length*/
int HexEncodeGetRequiredLength(int nSrcLen);
int HexDecodeGetRequiredLength(int nSrcLen);
int HexEncode(const unsigned char *pbSrcData, int nSrcLen, char *szDest, int *pnDestLen);
char GetHexValue(char ch);
int HexDecode(const char *pSrcData, int nSrcLen, unsigned char *pbDest, int* pnDestLen);
int utils_strincmp(const char *s1,const char *s2,int n);
unsigned char utils_crc(const unsigned char *buf,int size);
/**
* 将参数字符串分割为数组
*/
int split_arguments(const char *arginfo,char argArray[][MAX_ARG_LEN],int maxsize,char spliter);
unsigned int get_ip_addr(char *ipaddr);
unsigned int ParseIPAddr(char *cAddr,unsigned short *port);
EZUTILS_API char * LeftString(char *Dest,char *aSource,char BreakChar);
EZUTILS_API int RemovePrefix(char *Result,char *Source,char *DecPrefix);
EZUTILS_API char * Addprefix(char *Result,char *Source,char *AddPrefix);
EZUTILS_API char *Copy(char *dstr,const char *sstr,int from,int count);
EZUTILS_API char *Trim(char *dstr,const char *str);
EZUTILS_API void SplitStringValue(char *str,char *buf);
EZUTILS_API void SplitStringKeyValue(char *str,char *key,char * value);
EZUTILS_API long GetIPAddressByName(char *aDomain);
EZUTILS_API char *IP2Str(unsigned long aIP);
EZUTILS_API unsigned long Str2IP(char *aIP);
EZUTILS_API int IsPublicIP(unsigned long ip);
EZUTILS_API int IsPrivateIP(unsigned long ip);
EZUTILS_API int IsValidIP(unsigned long ip);
EZUTILS_API int IsMulticastIP(unsigned long ip);
EZUTILS_API char * ExtractFilePath(const char *FileName,char *path);
EZUTILS_API char * ExtractFileName(const char *FileName,char *fn);
EZUTILS_API char * ChangeFileExt(char *src,char *ext);
EZUTILS_API char * ChangeFilePath(char * src,char *path);
int GetTickCount(void);
int StrToInt(char * str);
int GetCmdParamValue(int argc, char* argv[],char *param,char* paramValue);
int CheckCmdLine(int argc, char* argv[],char *sw);
int ParseCmdParamValue(const char *cmd,const char *param,char *value);
int SetNonblocking(int fd);
int get_ip(char *localip);
void DisplaySocketInfo(int sockfd);
/*
* 当发现一个可用串口时的回调函数,这个回调函数讲用于each_comm函数
* @param param 上下文相关参数
* @param com 发现的串口设备字符串
* */
typedef void (*ON_FIND_COMM)(void *param,char *com);
/**
* 打开串口的函数
* @param Dev 串口字符串,字符串格式为: com=/dev/ttyUSB0(串口设备字符串),s=9600(波特率),p=N(奇偶校验),b=1(停止位),d=8(数据位数)
* @return
* 返回串口句柄,如果失败则返回值<=0
*/
int com_open(char *dev,int flag);
void com_close(int fd);
/**
* 从串口接收信息的函数
* @param fd 串口句柄
* @param buf 存放接收内容的缓冲区
* @param maxLen 存放接收内容缓冲区的大小
*/
int com_recive(int fd,char *buf,int maxLen,int timeout);
int com_write(int fd,char *buf,int len);
/**
* 枚举所有可用串口的函数,标准C中的文件结构中文件名是13个字符。
* @param filter 查找串口的过滤字符串,如"/dev/ttyUSB*"表示查找所有以ttyUSB开头的设备
* @param ofc 回调函数
* @param param 调用回调函数时提供的上下文相关的参数
*/
void each_comm(char *filter,ON_FIND_COMM ofc,void *param);
#ifdef __cplusplus
}
#endif
#endif
#ifndef _H_LOGMESSAGE_H_
#define _H_LOGMESSAGE_H_
#include <stdio.h>
#include <stdlib.h>
#ifndef EZUTILS_API
#define EZUTILS_API
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef void (*LogMessageT)(int Level,char *msgstr); //日志回调函数
typedef void (*ReportErrorMessageT)(char *msgstr); //错误报告回调函数
typedef void (*ReportWarningMessageT)(char *msgstr); //告警回调函数
#define MAX_MODULE_NUM 32
#define MakeMsgHeader(d,s) (((d) << 24) | ((s) << 16)) //合成消息的来源和目标信息
#define M_LogLevel(x,m) (x |(m<<16))
#define LM_FLAG(x) (1 << x) //模块的Log标志,x为模块的宏定义
#define LM_SYSTEM 0 //系统消息
#define LM_ERROR 0xFFFF //错误消息
#define LM_WARNING 0xFFFE //敬告消息
EZUTILS_API void InitLogMessage(void);
EZUTILS_API void DeleteLogMessage(void);
EZUTILS_API void SetLogCallback(LogMessageT lmt,ReportWarningMessageT rwmt,ReportErrorMessageT remt);
EZUTILS_API unsigned short GetMaxLogLevel(void);
EZUTILS_API unsigned short GetMinLogLevel(void);
EZUTILS_API void SetLogLevel(unsigned short aMinLevel,unsigned short aMaxLevel);
EZUTILS_API void RemoveLogModule(unsigned short aModule);
EZUTILS_API void AddLogModule(unsigned short aModule);
EZUTILS_API unsigned int GetLogModule(void);
EZUTILS_API void SetLogModule(unsigned int aLogModule);
/*
****************************************************************************************************
概述
显示日志信息的函数
修改历史
2003-11-20 杨军 增加了向网络发送日志的功能
****************************************************************************************************
*/
EZUTILS_API void LogMessage(int Level,char *file,int line,const char *tag,char *fmt,...);
EZUTILS_API void LogErrorMessage(char *file,int line,const char *tag,char *fmt,...);
EZUTILS_API void LogWarningMessage(char *file,int line,const char *tag,char *fmt,...);
/*向指定文件添加日志记录的函数
fn : 日志文件名
flag : 打印位置标识,DEBUG_CONSOLE表示输出到控制台,DEBUG_FILE表示输出到文件
pszDest : 日志信息
*/
#define DEBUG_CONSOLE 0x10
#define DEBUG_FILE 0x01
EZUTILS_API void _log(char *fn,int flag,char *pszDest);
#ifdef __cplusplus
}
#endif
#endif
## Process this file with automake to produce Makefile.in
##AM_CFLAGS=-g -Wall
bin_PROGRAMS = psuart
ParkService_INCLUDES = $(PSRLIB_INC)
ParkService_SOURCES = psuservice.c ini.c utils.c xLogMessage.c
ParkService_LDADD = @LIBOBJS@
/* inih -- simple .INI file parser
inih is released under the New BSD license (see LICENSE.txt). Go to the project
home page for more info:
http://code.google.com/p/inih/
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <assert.h>
#include "ini.h"
#if !INI_USE_STACK
#include <stdlib.h>
#endif
#define MAX_SECTION 50
#define MAX_NAME 50
/* Strip whitespace chars off end of given string, in place. Return s. */
static char* rstrip(char* s)
{
char* p = s + strlen(s);
while (p > s && isspace((unsigned char)(*--p)))
*p = '\0';
return s;
}
/* Return pointer to first non-whitespace char in given string. */
static char* lskip(const char* s)
{
while (*s && isspace((unsigned char)(*s)))
s++;
return (char*)s;
}
/* Return pointer to first char c or ';' comment in given string, or pointer to
null at end of string if neither found. ';' must be prefixed by a whitespace
character to register as a comment. */
static char* find_char_or_comment(const char* s, char c)
{
int was_whitespace = 0;
while (*s && *s != c && !(was_whitespace && *s == ';')) {
was_whitespace = isspace((unsigned char)(*s));
s++;
}
return (char*)s;
}
/* Version of strncpy that ensures dest (size bytes) is null-terminated. */
static char* strncpy0(char* dest, const char* src, size_t size)
{
strncpy(dest, src, size);
dest[size - 1] = '\0';
return dest;
}
/* See documentation in header file. */
int ini_parse_file(FILE* file,
int (*handler)(void*, const char*, const char*,
const char*),
void* user)
{
/* Uses a fair bit of stack (use heap instead if you need to) */
#if INI_USE_STACK
char line[INI_MAX_LINE];
#else
char* line;
#endif
char section[MAX_SECTION] = "";
char prev_name[MAX_NAME] = "";
char* start;
char* end;
char* name;
char* value;
int lineno = 0;
int error = 0;
#if !INI_USE_STACK
line = (char*)malloc(INI_MAX_LINE);
if (!line) {
return -2;
}
#endif
/* Scan through file line by line */
while (fgets(line, INI_MAX_LINE, file) != NULL) {
lineno++;
start = line;
#if INI_ALLOW_BOM
if (lineno == 1 && (unsigned char)start[0] == 0xEF &&
(unsigned char)start[1] == 0xBB &&
(unsigned char)start[2] == 0xBF) {
start += 3;
}
#endif
start = lskip(rstrip(start));
if (*start == ';' || *start == '#') {
/* Per Python ConfigParser, allow '#' comments at start of line */
}
#if INI_ALLOW_MULTILINE
else if (*prev_name && *start && start > line) {
/* Non-black line with leading whitespace, treat as continuation
of previous name's value (as per Python ConfigParser). */
if (!handler(user, section, prev_name, start) && !error)
error = lineno;
}
#endif
else if (*start == '[') {
/* A "[section]" line */
end = find_char_or_comment(start + 1, ']');
if (*end == ']') {
*end = '\0';
strncpy0(section, start + 1, sizeof(section));
*prev_name = '\0';
}
else if (!error) {
/* No ']' found on section line */
error = lineno;
}
}
else if (*start && *start != ';') {
/* Not a comment, must be a name[=:]value pair */
end = find_char_or_comment(start, '=');
if (*end != '=') {
end = find_char_or_comment(start, ':');
}
if (*end == '=' || *end == ':') {
*end = '\0';
name = rstrip(start);
value = lskip(end + 1);
end = find_char_or_comment(value, '\0');
if (*end == ';')
*end = '\0';
rstrip(value);
/* Valid name[=:]value pair found, call handler */
strncpy0(prev_name, name, sizeof(prev_name));
if (!handler(user, section, name, value) && !error)
error = lineno;
}
else if (!error) {
/* No '=' or ':' found on name[=:]value line */
error = lineno;
}
}
#if INI_STOP_ON_FIRST_ERROR
if (error)
break;
#endif
}
#if !INI_USE_STACK
free(line);
#endif
return error;
}
/* See documentation in header file. */
int ini_parse(const char* filename,
int (*handler)(void*, const char*, const char*, const char*),
void* user)
{
FILE* file;
int error;
file = fopen(filename, "r");
if (!file)
return -1;
error = ini_parse_file(file, handler, user);
fclose(file);
return error;
}
#define MAX_FILE_SIZE 1024*16
#define LEFT_BRACE '['
#define RIGHT_BRACE ']'
static int load_ini_file(const char *file, char *buf,int *file_size)
{
FILE *in = NULL;
int i=0;
*file_size =0;
assert(file !=NULL);
assert(buf !=NULL);
in = fopen(file,"r");
if( NULL == in) {
return 0;
}
buf[i]=fgetc(in);
//load initialization file
while( buf[i]!= (char)EOF) {
i++;
assert( i < MAX_FILE_SIZE ); //file too big, you can redefine MAX_FILE_SIZE to fit the big file
buf[i]=fgetc(in);
}
buf[i]='\0';
*file_size = i;
fclose(in);
return 1;
}
static int newline(char c)
{
return ('\n' == c || '\r' == c )? 1 : 0;
}
static int end_of_string(char c)
{
return '\0'==c? 1 : 0;
}
static int left_barce(char c)
{
return LEFT_BRACE == c? 1 : 0;
}
static int isright_brace(char c )
{
return RIGHT_BRACE == c? 1 : 0;
}
static int parse_file(const char *section, const char *key, const char *buf,int *sec_s,int *sec_e,
int *key_s,int *key_e, int *value_s, int *value_e)
{
const char *p = buf;
int i=0;
assert(buf!=NULL);
assert(section != NULL && strlen(section));
assert(key != NULL && strlen(key));
*sec_e = *sec_s = *key_e = *key_s = *value_s = *value_e = -1;
while( !end_of_string(p[i]) ) {
//find the section
if( ( 0==i || newline(p[i-1]) ) && left_barce(p[i]) )
{
int section_start=i+1;
//find the ']'
do {
i++;
} while( !isright_brace(p[i]) && !end_of_string(p[i]));
if( 0 == strncmp(p+section_start,section, i-section_start)) {
int newline_start=0;
i++;
//Skip over space char after ']'
while(isspace(p[i])) {
i++;
}
//find the section
*sec_s = section_start;
*sec_e = i;
while( ! (newline(p[i-1]) && left_barce(p[i]))
&& !end_of_string(p[i]) ) {
int j=0;
//get a new line
newline_start = i;
while( !newline(p[i]) && !end_of_string(p[i]) ) {
i++;
}
//now i is equal to end of the line
j = newline_start;
if(';' != p[j]) //skip over comment
{
while(j < i && p[j]!='=') {
j++;
if('=' == p[j]) {
if(strncmp(key,p+newline_start,j-newline_start)==0)
{
//find the key ok
*key_s = newline_start;
*key_e = j-1;
*value_s = j+1;
*value_e = i;
return 1;
}
}
}
}
i++;
}
}
}
else
{
i++;
}
}
return 0;
}
/**
*@brief read string in initialization file\n
* retrieves a string from the specified section in an initialization file
*@param section [in] name of the section containing the key name
*@param key [in] name of the key pairs to value
*@param value [in] pointer to the buffer that receives the retrieved string
*@param size [in] size of result's buffer
*@param default_value [in] default value of result
*@param file [in] path of the initialization file
*@return 1 : read success; \n 0 : read fail
*/
int read_profile_string( const char *section, const char *key,char *value,
int size, const char *default_value, const char *file)
{
char buf[MAX_FILE_SIZE]={0};
int file_size;
int sec_s,sec_e,key_s,key_e, value_s, value_e;
//check parameters
assert(section != NULL && strlen(section));
assert(key != NULL && strlen(key));
assert(value != NULL);
assert(size > 0);
assert(file !=NULL &&strlen(key));
if(!load_ini_file(file,buf,&file_size))
{
if(default_value!=NULL)
{
strncpy(value,default_value, size);
}
return 0;
}
if(!parse_file(section,key,buf,&sec_s,&sec_e,&key_s,&key_e,&value_s,&value_e))
{
if(default_value!=NULL)
{
strncpy(value,default_value, size);
}
return 0; //not find the key
}
else
{
int cpcount = value_e -value_s;
if( size-1 < cpcount)
{
cpcount = size-1;
}
memset(value, 0, size);
memcpy(value,buf+value_s, cpcount );
value[cpcount] = '\0';
return 1;
}
}
/**
*@brief read int value in initialization file\n
* retrieves int value from the specified section in an initialization file
*@param section [in] name of the section containing the key name
*@param key [in] name of the key pairs to value
*@param default_value [in] default value of result
*@param file [in] path of the initialization file
*@return profile int value,if read fail, return default value
*/
int read_profile_int( const char *section, const char *key,int default_value,
const char *file)
{
char value[32] = {0};
if(!read_profile_string(section,key,value, sizeof(value),NULL,file))
{
return default_value;
}
else
{
return atoi(value);
}
}
/**
* @brief write a profile string to a ini file
* @param section [in] name of the section,can't be NULL and empty string
* @param key [in] name of the key pairs to value, can't be NULL and empty string
* @param value [in] profile string value
* @param file [in] path of ini file
* @return 1 : success\n 0 : failure
*/
int write_profile_string(const char *section, const char *key,
const char *value, const char *file)
{
char buf[MAX_FILE_SIZE]={0};
char w_buf[MAX_FILE_SIZE]={0};
int sec_s,sec_e,key_s,key_e, value_s, value_e;
int value_len = 0;
int file_size;
FILE *out;
//check parameters
if(section == NULL || strlen(section) == 0)
return 0;
if(key == NULL || strlen(key) == 0)
return 0;
if(value == NULL)
return 0;
if(file ==NULL || strlen(file) == 0)
return 0;
value_len = (int)strlen(value);
if(!load_ini_file(file,buf,&file_size))
{
sec_s = -1;
}
else
{
parse_file(section,key,buf,&sec_s,&sec_e,&key_s,&key_e,&value_s,&value_e);
}
if( -1 == sec_s)
{
if(0==file_size)
{
sprintf(w_buf+file_size,"[%s]\n%s=%s\n",section,key,value);
}
else
{
//not find the section, then add the new section at end of the file
memcpy(w_buf,buf,file_size);
sprintf(w_buf+file_size,"\n[%s]\n%s=%s\n",section,key,value);
}
}
else if(-1 == key_s)
{
//not find the key, then add the new key=value at end of the section
memcpy(w_buf,buf,sec_e);
sprintf(w_buf+sec_e,"%s=%s\n",key,value);
sprintf(w_buf+sec_e+strlen(key)+strlen(value)+2,buf+sec_e, file_size - sec_e);
}
else
{
//update value with new value
memcpy(w_buf,buf,value_s);
memcpy(w_buf+value_s,value, value_len);
memcpy(w_buf+value_s+value_len, buf+value_e, file_size - value_e);
}
out = fopen(file,"w");
if(NULL == out)
{
return 0;
}
if(-1 == fputs(w_buf,out) )
{
fclose(out);
return 0;
}
fclose(out);
return 1;
}
/* Parse a configuration file into a struct using X-Macros */
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/utsname.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include "md5.h"
#include "psuservice.h"
static psus_config psus_data; //从配置文件中读取的服务端配置数据
/* create one and fill in its default values */
psus_config Psus_Config_Default = {
0x11,
0,
9,
10,
{},
-1,
-1,
#define CFG(s, n, default) default,
#include "psuservice.def"
};
/* process a line of the INI file, storing valid values into config struct */
static int handler(void *user, const char *section, const char *name,const char *value)
{
psus_config *cfg = (psus_config *)user;
if (0) ;
#define CFG(s, n, default) else if (strcmp(section, #s)==0 && \
strcmp(name, #n)==0) cfg->s##_##n = strdup(value);
#include "psuservice.def"
return 1;
}
/* print all the variables in the config, one per line */
static void dump_config(psus_config *cfg)
{
#define CFG(s, n, default) psus_log(10,"%s_%s = %s", #s, #n, cfg->s##_##n == NULL?"":cfg->s##_##n);
#include "psuservice.def"
}
/* clear all the variables in the config, one per line */
static void clear_config(psulib_config *cfg)
{
#define CFG(s, n, default) if(cfg->s##_##n != NULL){ \
free(cfg->s##_##n); \
cfg->s##_##n = NULL; \
}
#include "psulib.def"
}
/* clear all the variables in the config, one per line */
static void save_config(psulib_config *cfg,char *file)
{
//printf("%s = %d\n",__func__,__LINE__);
#define CFG(s, n, default) write_profile_string(#s,#n,cfg->s##_##n,file);
#include "psulib.def"
}
static void default_config(psulib_config *cfg,psulib_config *defcfg)
{
//printf("%s = %d\n",__func__,__LINE__);
#define CFG(s, n, default) if(cfg->s##_##n != NULL) \
free(cfg->s##_##n); \
if(defcfg->s##_##n != NULL) \
cfg->s##_##n = strdup(defcfg->s##_##n);
#include "psulib.def"
}
/**
从配置文件读取配置的函数,当管理命令需要执行载入配置命令时可以使用此函数
*/
static int LoadPsuConfig(char *fn)
{
int r = TRUE;
psus_config *psudata = &psus_data;
int ret = 1;
unsigned short port;
memcpy(&psus_data,0,sizeof(psus_config));
default_config(psusdata,&Psus_Config_Default);
if (ini_parse(fn, handler, &psus_data) < 0){
psus_error("Can't load '%s', using defaults",fn);
r = FALSE;
}
dump_config(&psus_data);
psudata->flag = StrToInt(psudata->log_flag);
psudata->minLevel = StrToInt(psudata->log_minLevel);
psudata->maxLevel = StrToInt(psudata->log_maxLevel);
SetLogLevel(psudata->minLevel,psudata->maxLevel);
SetLogCallback(_log_message,_log_warning,_log_error);
psudata->flag = StrToInt(psudata->log_flag);
psudata->minLevel = StrToInt(psudata->log_minLevel);
psudata->maxLevel = StrToInt(psudata->log_maxLevel);
SetLogLevel(psudata->minLevel,psudata->maxLevel);
psudata->selectTimeout = StrToInt(psudata->network_selectTimeout);
//初始化服务Socket地址信息
unsigned int addr;
memset(&(psudata->srv_addr),0,sizeof(struct sockaddr));
addr = ParseIPAddr(psudata->network_ipaddr,&port);
psudata->srv_addr.sin_family = AF_INET;
psudata->srv_addr.sin_addr.s_addr = addr;
psudata->srv_addr.sin_port = htons(port);
return r;
}
int normalReencode(void *user, const char*src, char*data)
{
strcpy(data,src);
return strlen(data);
}
/* process a line of the INI file, storing valid values into config struct */
static int normalParser(void *user, const char *name,const char *value)
{
psus_log(15,"\t%s=%s",name,value);
return 0;
}
int normalRequest(void *user,struct net_handle *h)
{
//服务端对接受到的请求的处理函数,处理完后要同步发出回应
psus_log(10,"\tResponse to %d.%d.%d.%d:%d(len=%d)...",IP2STR(ntohl(h->src_addr.sin_addr.s_addr)),
ntohs(h->src_addr.sin_port),h->req_len);
sendto(h->fd, h->request, h->req_len, 0,
(const struct sockaddr *)(void *)&h->src_addr,
(socklen_t)sizeof(struct sockaddr_in));
return 0;
}
int normalResponse(void *user,struct net_handle *h)
{
//服务器端不处理同步回应函数,服务端向客户端发送的请求都是通过异步回应来满足的
return 0;
}
/*
设置启动和关闭输出到文件的标识。
*/
void _set_debug_file(int v)
{
if(v == 0){
psus_data.flag &= ~DEBUG_FILE;
}else{
psus_data.flag |= DEBUG_FILE;
}
}
/*
最终输出日志的函数,输出位置使用psu_data的flag变量的设置。可以选择是输出到控制台还是文件。
*/
static void _log_message(int Level,char *msgstr)
{
_log(psus_data.log_file,psus_data.flag,msgstr);
}
/*
最终输出错误的函数,错误信息会同时输出到控制台和文件。
*/
static void _log_error(char *msgstr)
{
_log(psus_data.log_file,0x11,msgstr);
}
/*
最终输出告警的函数,告警信息会同时输出到控制台和文件。
*/
static void _log_warning(char *msgstr)
{
_log(psus_data.log_file,0x11,msgstr);
}
//外部获取平台库配置的数据结构的方法
psus_config *get_psus_data(void)
{
return &psus_data;
}
void dump_buffer(char *pstr,int size)
{
char buf[1024];
int hexlen = sizeof(buf);
if(pstr != NULL && size > 0){
memset(buf,0,sizeof(buf));
HexEncode(pstr,size,buf,&hexlen);
_log(psus_data.log_file,psus_data.flag,buf);
}else{
_log(psus_data.log_file,psus_data.flag,"(null) or empty.");
}
}
int OpenUart(psus_config *psudata)
{
if(psudata->uart_fd > 0)
return psudata->uart_fd;
psudata->uart_fd = com_open(psudata->uart_port);
if(psudata->uart_fd <= 0){
psus_error("open fifo error:%s",strerror(errno));
return -1;
}
return psudata->uart_fd;
}
void CloseUart(psus_config *psudata)
{
if(psudata->uart_fd > 0)
close(psudata->uart_fd);
psudata->uart_fd = 0;
}
int StartServiceSocket(psus_config *psudata)
{
unsigned short port;
if(psudata->net_fd > 0){
//如果已经创建了此socket,那么直接返回避免重复创建
return psudata->net_fd;
}
if ((psudata->net_fd = socket ( AF_INET , SOCK_STREAM , 0)) == -1) {
psus_error("Service socket error:%s",strerror(errno));
return -1;
}
if(!SetNonblocking(psudata->net_fd)){
psus_warning("set socket %d nonblocking fail.",psudata->net_fd);
}
if(bind(psudata->net_fd,(struct sockaddr *)&psudata->net_addr,sizeof(struct sockaddr))==-1)
{
psus_error("Service bind socket error:%d",ntohs(psudata->net_addr.sin_port));
close(psudata->net_fd);
psudata->net_fd = 0;
return -2;
}
psulib_log(10,"Service socket bind to %d...",ntohs(psudata->net_addr.sin_port));
return psudata->net_fd;
}
void CloseServiceSocket(psus_config *psudata)
{
if(psudata->net_fd > 0){
close(psudata->net_fd);
psudata->net_fd = 0;
}
}
int WaitMessageAndHandle(char *configfn,int timeout)
{
int iRet = 0,mfd,sfd,ffd;
fd_set rfds;
ffd = OpenUart(get_psu_data());
sfd = StartServiceSocket(get_psu_data());
if(ffd > 0)
FD_CLR(ffd,&rfds);
FD_CLR(sfd,&rfds);
FD_ZERO(&rfds);
if(ffd > 0)
FD_SET(ffd, &rfds);
FD_SET(sfd, &rfds);
struct timeval tv={5,0};
tv.tv_sec = timeout;
if(tv.tv_sec == -1)
iRet = select(MAX(sfd,ffd), &rfds, NULL, NULL, NULL);
else
iRet = select(MAX(sfd,ffd), &rfds, NULL, NULL, &tv);
if(0 >= iRet) return 0; //等待超时,进入下一次循环
if(FD_ISSET(ffd, &rfds))
{
//这里处理通过UART收到的命令
int len;
unsigned char buf[4096];
memset(buf,0,sizeof(buf));
len = read(ffd,buf,bufsize);
if(len > 0 && sfd > 0){
iRet = write(sfd,buf,bufsize);
}
}
else if(FD_ISSET(sfd, &rfds))
{
//这里处理的是服务器主动向客户端发送的消息,处理完以后客户端沿沿原途径做出回应
int len;
unsigned char buf[4096];
memset(buf,0,sizeof(buf));
len = read(sfd,buf,bufsize);
if(len > 0 && ffd > 0){
iRet = write(ffd,buf,bufsize);
}
}
return iRet;
}
int main(int argc, char* argv[])
{
char fn[MAX_PATH];
char cmd[128];
int i=0;
struct net_handle psushandle;
memset(&psushandle,0,sizeof(struct net_handle));
if(!GetCmdParamValue(argc,argv,"config",fn))
strcpy(fn,"/etc/psr/psuserver.conf");
//printf("%s\n",argv[0]);
printf("Use config file : %s\n",fn);
LoadPsrConfig(fn);
if(CheckCmdLine(argc,argv,"d")){
pid_t fpid; //fpid表示fork函数返回的值
psus_log(10,"Using deamon runing parameter.");
fpid = fork();
if (fpid < 0){
psus_error("error in fork!");
if(get_psr_data()->mrg_fd > 0){
close(get_psr_data()->mrg_fd);
}
return -1;
}else if (fpid == 0){
//子进程
psus_log(10,"Child process runing(%d)...",getpid());
}else{
//父进程,服务程序退出父进程
psus_log(10,"Child process %d runing,Parent process exit.",fpid);
return 0;
}
}
//启动服务处理循环
//处理命令接口
int iRet = 0;
do{
iRet = WaitMessageAndHandle(fn,get_psr_data()->selectTimeout);
}while(iRet >= 0);
psus_warning("Process %d end.",getpid());
CloseUart(get_psr_data());
CloseServiceSocket(get_psr_data());
return 0;
}
// CFG(section, name, default)
CFG(main, version, "0.1.0.1")
CFG(log, flag, "0x10")
CFG(log, file, DEFAULT_LOG_FILE)
CFG(log, minLevel,"0")
CFG(log, maxLevel,"10")
//字符串格式为:com=/dev/ttyUSB0(串口设备字符串),s=9600(波特率),p=N(奇偶校验),b=1(停止位),d=8(数据位数)
CFG(uart, port, "/dev/ttyACM0,115200,N,1,8")
CFG(network, ipaddr, "*:5001")
CFG(network, timeout, "3")
CFG(network, retries, "3")
CFG(network, secret, "androidex")
CFG(network, selectTimeout,"10")
CFG(network, type, "0x24")
CFG(db, ipaddr, "localhost:5432")
CFG(db, user, "psuadmin")
#undef CFG
#!/bin/bash
#
### BEGIN INIT INFO
# Provides: parkserver
# Required-Start: $local_fs $network $named $remote_fs $syslog
# Required-Stop: $local_fs $network $named $remote_fs $syslog
# Short-Description: Very Secure Ftp Daemon
# Description: parkserver is a Very Secure FTP daemon. It was written completely from
# scratch
### END INIT INFO
# parkserver This shell script takes care of starting and stopping
# standalone parkserver.
#
# chkconfig: - 60 50
# description: Vsftpd is a ftp daemon, which is the program \
# that answers incoming ftp service requests.
# processname: parkserver
# config: /eztor/parkserver/cfg/parkserver.conf
# Source function library.
. /etc/rc.d/init.d/functions
# Source networking configuration.
. /etc/sysconfig/network
BINPATH="/usr/bin/psusvr"
CONFIGFILE="/etc/psuconfig.conf"
LOGFILE="/var/log/psuconfig.log"
BINFILE="$BINPATH/psuserver"
RETVAL=0
prog="psuserver"
start() {
# Start daemons.
# Check that networking is up.
[ ${NETWORKING} = "no" ] && exit 1
[ -x $BINFILE ] || exit 1
[ -x $CONFIGFILE ] || exit 1
echo -n $"Starting $prog : "
daemon $BINFILE $CONFIGFILE
RETVAL=$?
echo
[ $RETVAL -eq 0 ]
return $RETVAL
}
stop() {
# Stop daemons.
echo -n $"Shutting down $prog: "
killproc $prog
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$prog
return $RETVAL
}
# See how we were called.
case "$1" in
start)
start
;;
stop)
stop
;;
restart|reload)
stop
start
RETVAL=$?
;;
condrestart|try-restart|force-reload)
if [ -f /var/lock/subsys/$prog ]; then
stop
start
RETVAL=$?
fi
;;
status)
status $prog
RETVAL=$?
;;
*)
echo $"Usage: $0 {start|stop|restart|try-restart|force-reload|status}"
exit 1
esac
exit $RETVAL
/**
* 公用函数库
*/
#include <stdio.h> /*标准输入输出定义*/
#include <stdlib.h> /*标准函数库定义*/
#include <unistd.h> /*Unix标准函数定义*/
#include <fcntl.h> /*文件控制定义*/
#include <termios.h> /*PPSIX终端控制定义*/
#include <errno.h> /*错误号定义*/
#include <time.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <sys/socket.h>
#include <dirent.h>
#include <unistd.h>
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <netdb.h>
#include "utils.h"
typedef unsigned char BYTE;
int HexEncodeGetRequiredLength(int nSrcLen)
{
return 2 * nSrcLen + 1;
}
int HexDecodeGetRequiredLength(int nSrcLen)
{
return nSrcLen/2;
}
int HexEncode(const unsigned char *pbSrcData, int nSrcLen, char *szDest, int *pnDestLen)
{
int nRead = 0;
int nWritten = 0;
BYTE ch;
static const char s_chHexChars[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F'};
if (!pbSrcData || !szDest || !pnDestLen)
{
return FALSE;
}
if(*pnDestLen < HexEncodeGetRequiredLength(nSrcLen))
{
return FALSE;
}
while (nRead < nSrcLen)
{
ch = *pbSrcData++;
nRead++;
*szDest++ = s_chHexChars[(ch >> 4) & 0x0F];
*szDest++ = s_chHexChars[ch & 0x0F];
nWritten += 2;
}
*pnDestLen = nWritten;
return TRUE;
}
#define HEX_INVALID ((char)-1)
//Get the decimal value of a hexadecimal character
char GetHexValue(char ch)
{
if (ch >= '0' && ch <= '9')
return (ch - '0');
if (ch >= 'A' && ch <= 'F')
return (ch - 'A' + 10);
if (ch >= 'a' && ch <= 'f')
return (ch - 'a' + 10);
return HEX_INVALID;
}
int HexDecode(const char *pSrcData, int nSrcLen, unsigned char *pbDest, int* pnDestLen)
{
int nRead = 0;
int nWritten = 0;
if (!pSrcData || !pbDest || !pnDestLen)
{
return 0;
}
if(*pnDestLen < HexDecodeGetRequiredLength(nSrcLen))
{
return 0;
}
while (nRead < nSrcLen)
{
char ch1,ch2;
if((char)*pSrcData == '\r' || (char)*pSrcData == '\n')break;
ch1 = GetHexValue((char)*pSrcData++);
ch2 = GetHexValue((char)*pSrcData++);
if ((ch1==HEX_INVALID) || (ch2==HEX_INVALID))
{
return 0;
}
*pbDest++ = (unsigned char)(16*ch1+ch2);
nWritten++;
nRead += 2;
}
*pnDestLen = nWritten;
return 1;
}
unsigned char utils_crc(const unsigned char *buf,int size)
{
unsigned char ret = 0;
int i;
for(i=0; i < size;i++)
ret += (unsigned char)(buf[i]);
return ret;
}
int utils_strincmp(const char *s1,const char *s2,int n)
{
/* case insensitive comparison */
int d;
if(n == 0){
n = strlen(s1);
if(n < strlen(s2))
n = strlen(s2);
}
while (--n >= 0) {
#ifdef ASCII_CTYPE
if (!isascii(*s1) || !isascii(*s2))
d = *s1 - *s2;
else
#endif
d = (tolower((unsigned char)*s1) - tolower((unsigned char)*s2));
if ( d != 0 || *s1 == '\0' || *s2 == '\0' )
return d;
++s1;
++s2;
}
return(0);
}
/*
function SplitArguments split string argument to a array.
parameters:
arginfo : Asterisk introduction arguments list.It is compart by char '|' .
argArray : a string array,it will store each argument.
maxsize : the max size of argArray.
spliter : it is a char witch arginfo used.default is '|'.
*/
int split_arguments(const char *arginfo,char argArray[][MAX_ARG_LEN],int maxsize,char spliter)
{
int index =0;
char *ps, *pe;
//printf("\nSplitArguments %s\n",arginfo);
ps = (char *)arginfo;//strchr(arginfo,spliter);
while(ps && index < maxsize)
{
if(*ps == spliter)ps++;
pe = strchr(ps,spliter);
if(pe){
int len = pe-ps;
strncpy(argArray[index++],ps,len < MAX_ARG_LEN? len : MAX_ARG_LEN-1);
ps = pe + 1;//strchr(pe,spliter);
}else{
if(strlen(ps) > 0)
strncpy(argArray[index++],ps,MAX_ARG_LEN-1);
break;
}
}
return index;
}
unsigned int get_ip_addr(char *ipaddr)
{
unsigned int iip = 0;
unsigned char *ip = (unsigned char *)&iip;
char arg[4][MAX_ARG_LEN];
memset(arg,0,4*MAX_ARG_LEN);
if(utils_strincmp(ipaddr,"*",strlen(ipaddr)) == 0){
iip = INADDR_ANY;
}else{
split_arguments(ipaddr,arg,4,'.');
ip[0] = atoi(arg[0]);
ip[1] = atoi(arg[1]);
ip[2] = atoi(arg[2]);
ip[3] = atoi(arg[3]);
}
return iip;
}
/*
**************************************************************************
概述
解析网络传输地址
**************************************************************************
*/
unsigned int ParseIPAddr(char *cAddr,unsigned short *port)
{
char Buf[50];
char *p=Buf,*ppos=NULL;
strcpy(Buf,cAddr);
ppos = strchr(p,':');
if(ppos == NULL)
*port = 0;
else{
*port = StrToInt(ppos+1);
*ppos = '\0';
}
return get_ip_addr(Buf);
}
//返回BreakChar后的字符串
EZUTILS_API char * LeftString(char *Dest,char *aSource,char BreakChar)
{
char *p = aSource;
while (*p && *p != ' ' && *p!=13 && *p!=BreakChar)p++;
strncpy(Dest,aSource,p-aSource);
if (*p) p++;
return p;
}
EZUTILS_API int RemovePrefix(char *Result,char *Source,char *DecPrefix)
{
int SourceLen,DecPrefixLen,sPos,bfound=FALSE;
SourceLen = (int)strlen(Source);
sPos = DecPrefixLen = strlen(DecPrefix);
if(utils_strincmp(DecPrefix,"*a",0)==0)
{
//不删除前缀
sPos = 0;
strcpy(Result,Source+sPos);
return TRUE;
}else{
int i;
for(i = 0; i<DecPrefixLen;i++ )
{
if (i >= SourceLen) break;//如果到源号码的尾部,跳出循环
if (DecPrefix[i] == '*'){
sPos = SourceLen;
break;
}
if ((Source[i] != DecPrefix[i]) && (DecPrefix[i] != '?'))
{
sPos = 0;
break;
}
}
}
strcpy(Result,Source+sPos);
return sPos>0;
}
EZUTILS_API char * Addprefix(char *Result,char *Source,char *AddPrefix)
{
strcpy(Result ,AddPrefix);
strcat(Result,Source);
return Result;
}
EZUTILS_API char * ExtractFilePath(const char *FileName,char *path)
{
char *p = (char *)strrchr(FileName,PATHSPLIT);
int len = p == NULL ? strlen(FileName) : (int)(p - FileName)+1;
strncpy(path,FileName,len);
path[len] = '\0';
return path;
}
EZUTILS_API char * ExtractFileName(const char *FileName,char *fn)
{
if(!FileName)
{
strcpy(fn,"");
}else{
char *p = (char *)strrchr(FileName,PATHSPLIT);
if(p)
strcpy(fn,p+1);
else
strcpy(fn,FileName);
}
return fn;
}
EZUTILS_API char * ChangeFileExt(char *src,char *ext)
{
char *p = strrchr(src,'.');
if(p)*p = '\0';
strcat(src,ext);
return src;
}
EZUTILS_API char * ChangeFilePath(char * src,char *path)
{
char fn[255];
ExtractFileName(src,fn);
strcpy(src,path);
if(path[strlen(path)-1] != '\\')
strcat(src,PATHSPLITS);
strcat(src,fn);
return src;
}
/*
说明:
比较版本号,版本号为x.x.x.x格式。这需要调用GetFileVersionS函数来获得。
参数:
char *newversion : 版本号1
char *oldversion : 版本号2
返回值:
1 : 版本号1大于版本号2
0 : 两个版本号相同
-1 : 版本号1小于版本号2
*/
int VersionCompare(char* newversion,char* oldversion)
{
return 0;
}
EZUTILS_API char *Copy(char *dstr,const char *sstr,int from,int count)
{
int i = 0;
if(from >= (int)strlen(sstr) || count <=0)strcpy(dstr,"");
else{
while(from+i<(int)strlen(sstr) && i<count){
dstr[i] = sstr[i + from];
i++;
}
dstr[i] = '\0';
}
return dstr;
}
/*
*********************************************************************
概述
去掉字符串前后的空格、制表符、换行符等
*********************************************************************
*/
EZUTILS_API char *Trim(char *dstr,const char *str)
{
int iStart=0,iEnd = (int)strlen(str)-1;
while(str[iStart] == ' '|| str[iStart]=='\t'||str[iStart]=='\n'||str[iStart]=='\r')iStart++;
while(str[iEnd] ==' '|| str[iEnd]=='\t'||str[iEnd]=='\n'||str[iEnd]=='\r')iEnd--;
return Copy(dstr,str,iStart,iEnd-iStart+1);
}
/*
********************************************************************
概数
获得Name=Value字符串的Value部分,如果不包含=号则去全部字符串
********************************************************************
*/
EZUTILS_API void SplitStringValue(char *str,char *buf)
{
char spliter[] = "=#|&@";
char *ps=str,*ppos=NULL,*p = spliter;
while(*p && (ppos == NULL)){
ppos = strchr(ps,*p);
p++;
}
if(ppos == NULL){
strcpy(buf,str);
}else{
strcpy(buf,ppos+1);
}
}
/*
********************************************************************
概数
获得Name=Value字符串的Key&Value部分,如果不包含=号则Key取全部字符串
********************************************************************
*/
EZUTILS_API void SplitStringKeyValue(char *str,char *key,char * value)
{
char spliter[] = "=#|&@";
char *ps=str,*ppos=NULL,*p = str;
while(*p && (ppos == NULL)){
ppos = strchr(spliter,*p);
p++;
}
if(*p == '\0'){
strcpy(value,"");
strcpy(key,str);
}else{
strncpy(key,str,p-str-1);
key[p-str-1] = 0;
strcpy(value,p);
}
}
/*
*****************************************************************
概述
判断ip地址是否为组播地址
参数
ip : 4字节的ip地址
*****************************************************************
*/
EZUTILS_API int IsMulticastIP(unsigned long ip)
{
unsigned char iFirst;
char *p = (char *)&ip;
iFirst = p[0];
return iFirst >=224 && iFirst <= 240;
}
/*
*****************************************************************
概述
判断是否为有效的ip
参数
ip : 4字节的ip地址
*****************************************************************
*/
EZUTILS_API int IsValidIP(unsigned long ip)
{
unsigned char iFirst, iSecond;
char *p = (char *)&ip;
iFirst = p[0];
iSecond = p[1];
if (iFirst == 127 || iFirst >= 224)
{
return FALSE;
}
else if (!iFirst)
{
if (!iSecond)
{
return FALSE;
}
}
return TRUE;
}
/*
*****************************************************************
概述
判断是否为私有的ip
参数
ip : 4字节的ip地址
*****************************************************************
*/
EZUTILS_API int IsPrivateIP(unsigned long ip)
{
unsigned char iFirst, iSecond;
char *p = (char *)&ip;
iFirst = p[0];
iSecond = p[1];
if (iFirst == 10) return TRUE;
if (iFirst == 172 && (iSecond >= 16 && iSecond <= 32))return TRUE;
if (iFirst == 192 && iSecond == 168)return TRUE;
return FALSE;
}
/*
*****************************************************************
概述
判断是否为公网的ip
参数
ip : 4字节的ip地址
*****************************************************************
*/
EZUTILS_API int IsPublicIP(unsigned long ip)
{
return IsValidIP(ip) && (!IsPrivateIP(ip));
}
int GetTickCount(void)
{
struct timeval tv;
gettimeofday( &tv, NULL );
// this will rollover ~ every 49.7 days
return (tv.tv_sec * 1000 + tv.tv_usec / 1000);
}
/**
考虑了8-10-16进制的字符串转整数的函数
*/
int StrToInt(char * str)
{
int value = 0;
int sign = 1;
int radix;
if(str == NULL)return 0;
if(*str == '-'){
sign = -1;
str++;
}
if(*str == '0' && (*(str+1) == 'x' || *(str+1) == 'X')){
radix = 16;
str += 2;
}else if(*str == '0'){
radix = 8;
str++;
}else{
radix = 10;
}
while(*str)
{
if(radix == 16)
{
if(*str >= '0' && *str <= '9')
value = value * radix + *str - '0';
else if(*str >= 'a' && *str <= 'f')
value = value * radix + (*str | 0x20) - 'a' + 10;
else if(*str >= 'A' && *str <= 'F')
value = value * radix + (*str | 0x20) - 'A' + 10;
}else{
if(*str >= '0' && *str <= '9')
value = value * radix + *str - '0';
}
str++;
}
return sign*value;
}
int ParseCmdParamValue(const char *cmd,const char *param,char *value)
{
char *str=(char *)cmd,*strp=(char *)cmd,sw[100]="";
memset(sw,0,sizeof(sw));
while(*str==' ' || *str=='/' || *str=='-' || *str == '\\')str++;
strp = str;
while((*strp!='\0')&&(*strp != ':'))strp++;
strncpy(sw,str,strp-str);
switch(*strp)
{
case '\0':
strcpy(value,""); //如果后面没有参数,则使用空值作为参数
break;
case ':':
strcpy(value,strp+1);
break;
default:
strcpy(value,"");
break;
}
if (utils_strincmp(sw,param,0)==0){
return TRUE;
}
return FALSE;
}
int CheckCmdLine(int argc, char* argv[],char *sw)
{
int i;
char *str;
for(i=1;i<argc;i++)
{
str = argv[i];
while(*str==' ' || *str=='/' || *str=='-' || *str == '\\')str++;
if (utils_strincmp(str,sw,0)==0)
return TRUE;
}
return FALSE;
}
int GetCmdParamValue(int argc, char* argv[],char *param,char* paramValue)
{
int i;
char *str,*strp,sw[100]="";
strcpy(paramValue,"");
for(i=1;i<argc;i++)
{
str = argv[i];
memset(sw,0,sizeof(sw));
//printf("argv[%d]=%s\r\n",i,argv[i]);
while(*str==' ' || *str=='/' || *str=='-' || *str == '\\')str++;
strp = str;
while((*strp!='\0')&&(*strp != ':'))strp++;
strncpy(sw,str,strp-str);
switch(*strp)// == _T('\0'))strcpy(paramValue,"");
{
case '\0':
if(i+1 < argc)
{
if((argv[i+1][0] != '/') && (argv[i+1][0] != '-'))
strcpy(paramValue,argv[i+1]); //如果后面还有参数,且参数不是以'/' '-'开头时,则使用下一个参数作为参数值
else
strcpy(paramValue,""); //如果后面没有参数,则使用空值作为参数
}else{
strcpy(paramValue,""); //如果后面没有参数,则使用空值作为参数
}
break;
case ':':
strcpy(paramValue,strp+1);
break;
default:
break;
}
//printf("\t%s=%s\r\n",sw,paramValue);
if (utils_strincmp(sw,param,0)==0){
return TRUE;
}
}
return FALSE;
}
int SetNonblocking(int fd)
{
int opts;
opts = fcntl(fd,F_GETFL);
if (opts >= 0 )
{
opts = opts | O_NONBLOCK;
if(fcntl(fd,F_SETFL,opts) >= 0 )
{
return TRUE;
}
}
return FALSE;
}
int get_ip(char *localip)
{
int i = 0;
struct hostent *hp;
struct utsname localname;
uname(&localname);
hp = gethostbyname(localname.nodename);
for (i = 0; hp->h_addr_list[i] != NULL ; ++i){
strcpy(localip, inet_ntoa(*(struct in_addr*) hp->h_addr_list[i]));
//psrlib_log(10,"IP:%s",localip);
}
return 0;
}
void DisplaySocketInfo(int sockfd)
{
struct sockaddr_in *addr;
struct ifreq ifr;
char address[100];
get_ip(address);
//printf("IP:%s",address);
bzero(&ifr, sizeof(ifr));
strcpy(ifr.ifr_name,"en0");
if(ioctl(sockfd,SIOCGIFADDR,&ifr) == -1){
perror("ioctl error");
return;
}
addr = (struct sockaddr_in *)&(ifr.ifr_addr);
if(addr){
//psrlib_log(10,"inet addr: %s:%d ",inet_ntoa(addr->sin_addr),ntohs(addr->sin_port));
}
if(ioctl(sockfd,SIOCGIFBRDADDR,&ifr) == -1){
//psrlib_error("ioctl error");
}
addr = (struct sockaddr_in *)&ifr.ifr_broadaddr;
//psrlib_log(10,"broad addr: %s ",(char*)inet_ntoa(addr->sin_addr));
if(ioctl(sockfd,SIOCGIFNETMASK,&ifr) == -1){
//psrlib_error("ioctl error");
}
addr = (struct sockaddr_in *)&ifr.ifr_addr;
//psrlib_log(10,"inet mask: %s ",(char*)inet_ntoa(addr->sin_addr));
}
/**
* 串口操作的函数库
*/
/*
* 设置串口的波特率参数
*/
static void com_set_speed(int fd, int speed) {
int i;
int status;
struct termios Opt;
int speed_arr[] = {B115200, B38400, B19200, B9600, B4800, B2400, B1200, B300, B38400,
B19200, B9600, B4800, B2400, B1200, B300, };
int name_arr[] = {115200, 38400, 19200, 9600, 4800, 2400, 1200, 300, 38400, 19200,
9600, 4800, 2400, 1200, 300, };
//检查串口是否打开如果没有打开则返回,什么也不做
if(fd<=0){
return;
}
tcgetattr(fd, &Opt); //用来得到机器原端口的默认设置
for (i = 0; i < sizeof(speed_arr) / sizeof(int); i++) {
if (speed == name_arr[i]) {
tcflush(fd, TCIOFLUSH); //刷新输入输出缓冲
cfsetispeed(&Opt, speed_arr[i]);
cfsetospeed(&Opt, speed_arr[i]);
status = tcsetattr(fd, TCSANOW, &Opt);
if (status != 0)
perror("set com speed error:tcsetattr.");
tcflush(fd, TCIOFLUSH);
return;
}
}
}
/**
* 设置串口优先级
*@param fd 类型 int 打开的串口文件句柄*
*@param databits 类型 int 数据位 取值 为 7 或者8*
*@param stopbits 类型 int 停止位 取值为 1 或者2*
*@param parity 类型 int 效验类型 取值为N,E,O,,S
*/
static int com_set_parity(int fd, int databits, int stopbits, char parity) {
struct termios options;
//检查串口是否打开如果没有打开则返回,什么也不做
//__android_log_print(ANDROID_LOG_INFO, "utils", "com_set_parity(%d,数据位%d,停止位%d,校验类型%c)",fd,databits,stopbits,parity);
if(fd<=0){
return FALSE;
}
if (tcgetattr(fd, &options) != 0) {
perror("SetupSerial 1");
return FALSE;
}
options.c_cflag &= ~CSIZE;
switch (databits) /*设置数据位数*/
{
case 7:
options.c_cflag |= CS7;
break;
case 8:
options.c_cflag |= CS8;
break;
default:
perror("Unsupported data size\n");
return FALSE;
}
switch (parity) {
case 'n':
case 'N':
options.c_cflag &= ~PARENB; //Clear parity enable
options.c_iflag &= ~INPCK; //Enable parity checking
break;
case 'E':
options.c_cflag |= PARENB; // Enable parity
options.c_cflag &= ~PARODD; // 转换为偶效验
options.c_iflag |= INPCK; // Disnable parity checking
break;
default:
perror("Unsupported parity\n");
return FALSE;
}
/* 设置停止位*/
switch (stopbits) {
case 1:
options.c_cflag &= ~CSTOPB;
break;
case 2:
options.c_cflag |= CSTOPB;
break;
default:
perror("Unsupported stop bits\n");
return FALSE;
}
options.c_cc[VTIME] = 0; //150; // 15 seconds
options.c_cc[VMIN] = 0;
//options.c_cc[VMIN] = 1; //read()到一个char时就返回
tcflush(fd, TCIFLUSH); //Update the options and do it NOW
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG | IEXTEN);
options.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
options.c_oflag &= ~(OPOST);
if (tcsetattr(fd, TCSANOW, &options) != 0) //使端口属性设置生效
{
perror("SetupSerial 3");
return FALSE;
}
tcflush(fd, TCIOFLUSH);
return TRUE;
}
/**
* 打开串口的函数
* @param Dev 串口字符串,字符串格式为:com=/dev/ttyUSB0(串口设备字符串),s=9600(波特率),p=N(奇偶校验),b=1(停止位),d=8(数据位数)
* @return
* 返回串口句柄,如果失败则返回值<=0
*/
int com_open(char *dev,int flag) {
int fd;
char arg[5][MAX_ARG_LEN];
char *com="/dev/ttyUSB0",*s="115200",*p="N",*b="1",*d="8";
memset(arg,0,5*MAX_ARG_LEN);
int argc = split_arguments(dev,arg,5,',');
switch(argc){
case 0:
break;
case 1:
com = arg[0];
break;
case 2:
com = arg[0];
s = arg[1];
break;
case 3:
com = arg[0];
s = arg[1];
p = arg[2];
break;
case 4:
com = arg[0];
s = arg[1];
p = arg[2];
b = arg[3];
break;
default:
com = arg[0];
s = arg[1];
p = arg[2];
b = arg[3];
d = arg[4];
break;
}
fd = open(com, flag | O_NOCTTY | O_NDELAY);
if (fd<=0) {
_log("utils","Can't Open Serial Port %s:%s\n",com,strerror(errno));
} else {
//int pn = (p[0] != 'N') || (p[0] != 'n');
char pn= p[0];
//__android_log_print(ANDROID_LOG_INFO, "utils", "波特率 %s",s);
com_set_speed(fd, atoi(s));
if (com_set_parity(fd, atoi(d), atoi(b), pn)==FALSE)
{
perror("设置串口参数出错");
com_close(fd);
return 0;
}
}
return fd;
}
/**
* 枚举所有可用串口的函数,标准C中的文件结构中文件名是13个字符。
* @param filter 查找串口的过滤字符串,如"/dev/ttyUSB*"表示查找所有以ttyUSB开头的设备
* @param ofc 回调函数
* @param param 调用回调函数时提供的上下文相关的参数
*/
void each_comm(char *filter,ON_FIND_COMM ofc,void *param)
{
/*struct ffblk ff;
int done;
if(ofc == NULL)return;
done = findfirst(filter,&ff,0);
while(!done)
{
if(ff.ff_attrib&FA_DIREC != FA_DIREC)
ofc(param,ff.ff_name);
done=findnext(&ff);
}*/
}
void com_close(int fd)
{
//检查串口是否打开如果没有打开则返回,什么也不做
if(fd>0){
if(close(fd)==-1)
_log( "utils","Close Serial Port:%s\n",strerror(errno));
}
}
/**
* 从串口接收信息的函数
* @param fd 串口句柄
* @param buf 存放接收内容的缓冲区
* @param maxLen 存放接收内容缓冲区的大小
*/
int com_recive(int fd,char *buf,int maxLen,int timeout)
{
fd_set rfds;
int len=0,r=0;
struct timeval tv;
//检查串口是否打开如果没有打开则返回,什么也不做
if(fd<=0){
return -1;
}
FD_ZERO(&rfds);
FD_SET(fd,&rfds);
//_log( "utils", "Select %d",fd);
if(timeout == -1){
r = select(fd+1,&rfds,NULL,NULL,NULL);
}else{
memset(&tv,0,sizeof(tv));
tv.tv_sec = 0;
tv.tv_usec = timeout*1000;//1000000us = 1s
r = select(fd+1,&rfds,NULL,NULL,&tv);
}
if(r==-1){
//发生错误
tcflush(fd, TCIOFLUSH);
//_log( "utils", "Select return %d(timeout=%d)",r,timeout);
return r;
}else if (r==0)
{
//等待超时
tcflush(fd, TCIOFLUSH);
//_log( "utils", "Select return %d(timeout=%d)",r,timeout);
return r;
}else{
if(FD_ISSET(fd,&rfds)){
len = read(fd,buf,maxLen);
if(len > 0){
#if 0
char hexbuf[512];
int dlen=sizeof(hexbuf);
memset(hexbuf,0,sizeof(hexbuf));
HexEncode(buf,len,hexbuf,&dlen);
_log( "utils", "Recive data(%d) from fd=%d,hexbuf=%s",len,fd,hexbuf);
#endif
}
return len;
}else{
return -1;
}
}
return r;
}
int com_write(int fd,char *buf,int len)
{
//检查串口是否打开如果没有打开则返回,什么也不做
if(fd<=0){
return -1;
}
#if 0
{
char hexbuf[512];
int dlen=sizeof(hexbuf);
memset(hexbuf,0,sizeof(hexbuf));
HexEncode(buf,len,hexbuf,&dlen);
//_log( "utils", "Send data(%d) from fd=%d,hexbuf=%s",len,fd,hexbuf);
}
#endif
return write(fd,buf,len);
}
/*
****************************************************************************************
概述
日志输出的相关函数。
说明
要使用LogMessage请先调用一次InitLogMessage,当应用程序不再使用此单元的内容时应调用
DeleteLogMessage以释放内存。
创建
2003-7-10 杨军
修改历史
+ 2003-11-26 杨军 增加了对网络日志对本子网采用广播的方式,默认为广播方式
+ 2003-11-20 杨军 增加了对网络日志的支持,可以向网络指定地址和端口发送日志,使
用此功能需要增加 LOGTONET 编译开开关。
****************************************************************************************
*/
#include <stdio.h>
#include <stdarg.h>
#include <time.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/select.h>
#include "utils.h"
#include "xLogMessage.h"
static volatile unsigned int log_signle = 0;
//显示Log的级别
static volatile unsigned short MinLogLevel=0,MaxLogLevel = 255; //当LogLevel=0表示系统消息,-1(0xFFFF)表示错误,-2(0xFFFE)是警告;一定会输出
static volatile unsigned int LogModule = 0xFFFFFFFF; //默认只打印系统消息
#define MAX_REV_BUFFER_SIZE 1024
/*
*************************************************************************
概述
初始化LogMessage的函数。
说明
+ LogMessage的显示级别适用了访问互斥,在此
函数中回初始化互斥变量。
+ 在使用LogMessage之前一定要调用此函数进行
初始化。强烈建议在系统初始化的开始调用此函
数。
*************************************************************************
*/
EZUTILS_API void InitLogMessage(void)
{
log_signle = 0;
MinLogLevel = 0;
MaxLogLevel = 255;
LogModule = 0xFFFFFFFF;
}
/*
******************************************************************
概述
释放内存
******************************************************************
*/
EZUTILS_API void DeleteLogMessage(void)
{
log_signle = 0;
MinLogLevel = 0;
MaxLogLevel = 255;
LogModule = 0xFFFFFFFF;
}
EZUTILS_API int LockLogLevel(int flag)
{
if(flag){
while(log_signle > 0){
//sleep(10);
fd_set fdR;
struct timeval timeout={0,0};
FD_ZERO(&fdR);
FD_SET(fileno(stdin), &fdR);
memset(&timeout,0,sizeof(struct timeval));
timeout.tv_usec = 1000;
select(fileno(stdin)+1, &fdR, NULL, NULL, &timeout);
}
log_signle++;
return TRUE;
}else{
if(log_signle == 0){
log_signle++;
return TRUE;
}else{
return FALSE;
}
}
}
EZUTILS_API int UnlockLogLevel(void)
{
if(log_signle > 0){
log_signle--;
return TRUE;
}else{
return FALSE;
}
}
/*
*************************************************************************
概述
取得日志显示级别的函数。
说明
此函数是为了封装LogLevel的访问读。
*************************************************************************
*/
EZUTILS_API unsigned short GetMaxLogLevel(void)
{
unsigned short Level;
LockLogLevel(TRUE);
Level = MaxLogLevel;
UnlockLogLevel();
return Level;
}
/*
*************************************************************************
概述
取得日志显示级别的函数。
说明
此函数是为了封装LogLevel的访问读。
*************************************************************************
*/
unsigned short GetMinLogLevel(void)
{
unsigned short Level;
LockLogLevel(TRUE);
Level = MinLogLevel;
UnlockLogLevel();
return Level;
}
/*
*************************************************************************
概述
设置日志显示级别的函数。
说明
此函数是为了封装LogLevel的访问写。
最大最小级别顺序可以互换,命令会根据实际数值调整。
*************************************************************************
*/
EZUTILS_API void SetLogLevel(unsigned short aMinLevel,unsigned short aMaxLevel)
{
LockLogLevel(TRUE);
MaxLogLevel = aMinLevel > aMaxLevel ? aMinLevel : aMaxLevel;
MinLogLevel = aMinLevel < aMaxLevel ? aMinLevel : aMaxLevel;
UnlockLogLevel();
}
/*
*************************************************************************
概述
设置日志显示模块的函数。
说明
此函数是为了封装LogModule的访问写。
*************************************************************************
*/
EZUTILS_API unsigned int GetLogModule(void)
{
unsigned int lModule;
LockLogLevel(TRUE);
lModule = LogModule;
UnlockLogLevel();
return lModule;
}
/*
*************************************************************************
概述
设置日志显示模块的函数。
说明
此函数是为了封装LogModule的访问写。
系统模块是否显示调试信息是通过aLogModule的相应位是否打开来确定的。当1
左移模块的代码位为1时表示显示信息,否则为不显示。最终调试信息是否会显示还
要配合最大最小级别来确定。
+ 0 : 关闭所有模块
+ -1 : 打开所有模块
*************************************************************************
*/
EZUTILS_API void SetLogModule(unsigned int aLogModule)
{
LockLogLevel(TRUE);
LogModule = aLogModule;
UnlockLogLevel();
}
/*
*************************************************************************
概述
增加日志显示模块的函数。
说明
此函数是为了简化LogModule的访问写。
*************************************************************************
*/
EZUTILS_API void AddLogModule(unsigned short aModule)
{
LockLogLevel(TRUE);
LogModule = LogModule |LM_FLAG(aModule);
UnlockLogLevel();
}
/*
***********************************
说明:
此函数是为了简化LogModule的访问写。
概述:
移除日志显示模块的函数。
参数:
aModule : 模块标识
***********************************
*/
EZUTILS_API void RemoveLogModule(unsigned short aModule)
{
LockLogLevel(TRUE);
LogModule = LogModule &(~ LM_FLAG(aModule));
UnlockLogLevel();
}
static LogMessageT OnLogMessage = NULL;
static ReportErrorMessageT OnReportError = NULL;
static ReportWarningMessageT OnReportWarning = NULL;
/*
*************************************************************************************************
概述
设置输出日志\错误\警告的回调函数的方法
*************************************************************************************************
*/
EZUTILS_API void SetLogCallback(LogMessageT lmt,ReportWarningMessageT rwmt,ReportErrorMessageT remt)
{
OnLogMessage = lmt;
OnReportWarning = rwmt;
OnReportError = remt;
}
/*向指定文件添加日志记录的函数
fn : 日志文件名
flag : 打印位置标识,DEBUG_CONSOLE表示输出到控制台,DEBUG_FILE表示输出到文件
pszDest : 日志信息
*/
EZUTILS_API void _log(char *fn,int flag,char *pszDest)
{
if((flag&DEBUG_CONSOLE) == DEBUG_CONSOLE){
//为了便于测试同时输出信息到控制台
printf("%s\r\n",pszDest);
}
if((flag&DEBUG_FILE) == DEBUG_FILE && fn != NULL)
{
FILE *log_fd = NULL;
time_t timer;
struct tm *tblock;
timer=time(NULL);
tblock = localtime(&timer);
log_fd = fopen(fn,"a+");
if(log_fd != NULL){
fprintf(log_fd,"%.4d-%.2d-%.2d %.2d:%.2d:%.2d\t%s\r\n",
tblock->tm_year+1900,
tblock->tm_mon+1,
tblock->tm_mday,
tblock->tm_hour,
tblock->tm_min,
tblock->tm_sec,
pszDest);
fclose(log_fd);
}else{
printf("Open %s error:%s.\r\n",fn,strerror(errno));
}
}
}
/*
****************************************************************************************************
概述
显示日志信息的函数
修改历史
2003-11-20 杨军 增加了向网络发送日志的功能
****************************************************************************************************
*/
EZUTILS_API void LogMessage(int Level,char *file,int line,const char *tag,char *fmt,...)
{
unsigned int lModule,lLevel;
int ltype;
if(!fmt)return;
lModule= (Level & 0xFFFF0000)>>16;
lLevel = (Level & 0x0000FFFF);
ltype = (lLevel == LM_SYSTEM ) || //检查是否为系统消息
(lLevel == LM_ERROR) || //检查是否为错误消息
(lLevel == LM_WARNING); //检查是否为警告消息
if ((!ltype) && (lLevel > GetMaxLogLevel() || lLevel < GetMinLogLevel())) return; //大于LogLevel的信息将放弃不显示
if ((1<<lModule) & GetLogModule()) //检查Log的模块是否需要LOG
{
char pszDest[2048],*p = pszDest;
int hlen=0;
va_list args;
memset(pszDest,0,sizeof(pszDest));
if(0){
sprintf(pszDest,"Line %d in %s\nHINT:[%s]",line,file,tag);
hlen = strlen(pszDest);
p = pszDest + hlen;
}
va_start(args, fmt);
vsnprintf(p, sizeof(pszDest)-hlen, fmt, args);
va_end(args);
if(OnLogMessage) OnLogMessage(Level,pszDest);
}
}
/*
****************************************************************************************************
概述
显示错误信息的函数
****************************************************************************************************
*/
EZUTILS_API void LogErrorMessage(char *file,int line,const char *tag,char *fmt,...)
{
char pszDest[2048],*p;
int hlen=0;
va_list args;
memset(pszDest,0,sizeof(pszDest));
sprintf(pszDest,"Line %d in %s\nERROR:[%s]",line,file,tag);
hlen = strlen(pszDest);
p = pszDest + hlen;
va_start(args, fmt);
vsnprintf(p, sizeof(pszDest)-hlen, fmt, args);
va_end(args);
if(OnReportError) OnReportError(pszDest);
}
/*
****************************************************************************************************
概述
显示警告信息的函数
****************************************************************************************************
*/
EZUTILS_API void LogWarningMessage(char *file,int line,const char *tag,char *fmt,...)
{
char pszDest[2048],*p;
int hlen=0;
va_list args;
memset(pszDest,0,sizeof(pszDest));
sprintf(pszDest,"Line %d in %s\nWARNING:[%s]",line,file,tag);
hlen = strlen(pszDest);
p = pszDest + hlen;
va_start(args, fmt);
vsnprintf(p, sizeof(pszDest)-hlen, fmt, args);
va_end(args);
if(OnReportWarning) OnReportWarning(pszDest);
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment