#include "mnic.h"
#include "dotconf.h"
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <pthread.h>
#include "proc_inv.h"
#include "version.h"

#define THRNR 	 10
#define DAYS	 25
#define LINE_SIZE	2048
#define HOST_NAME_SIZE  40
#define BOND_PATH "/proc/net/bonding/*"
#define LOG_PATH  "/var/log/netcard/"
#define SHM_PATH  "/share/sys_netcard_shm_path"
#define SEM_PATH  "/share/sys_netcard_sem_path"
#define MAX_GW	 32
#define	DEV_MAXLEN	32
#define IPLEN 16
#define CONF_FILE "/conf/nic/sys_netcard_conf.txt"

//#define MNIC_VERSION "1.9"

#define NIC_UNKNOWN 0
#define NIC_DOWN 1
#define NIC_UNRUNNING 2
#define NIC_UNLINKABLE 3
#define NIC_NORMAL 4

//网卡设备描述结构
typedef struct __nic_dev{
	char	dev_name[DEV_MAXLEN];		//网卡名称
	char	ping_ip[MAX_GW][IPLEN];		//ping地址列表，最多32个
	int	gw_num;				//地址列表的长度
}NIC_DEV;

typedef struct __config_file_st{
	unsigned char   domain;
	short           serv;
	short           event;
	int             udpport;
	int             monitor_interval;
	int             write_interval;
	int             flow_interval;
	int             flow_limit;
	int             flow_peak;
	char            udp[NIC_NAME_LEN];
	NIC_DEV		nic[MAXNICNUM];	//被监视网卡的列表
	char            ip[IPSIZE];
	int		pingnum;	//OPTIONAL!! How many times for once ping check? Default is 2.
	int		pinglap;	//OPTIONAL!! How many seconds does ping wait for reply package? Default is 1.
	int 		crazyping;
}CONFIG_FILE_ST;

typedef struct inc_name_node{
	char name[NIC_NAME_LEN];
	struct inc_name_node *next;
}NET_NAME_ST;

typedef struct inc_info_node{
	NETCARD_INFO info;
	int	status;
	struct inc_info_node *next;
}NETCARD_INFO_ST;

typedef struct net_info{
	NETCARD_INFO info[MAXNICNUM];
}SHM;

typedef struct __thread_env_st{
	D5000_NIC_ALARM Malarm;
	char bond_file_path[64];
	char host_name[HOST_NAME_SIZE];
	int  host_name_size;
	CONFIG_FILE_ST *conf;
}THENV;

typedef struct __thread_mem_st{
	int semid;
	SHM *shm_ptr;
	NETCARD_INFO_ST *listp;
	CONFIG_FILE_ST *conf;
}THMEM;

typedef struct __thread_flow_st{
	THENV env;
	THMEM mem;
}THFLOW;

int find_nic_config(char *);

static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
static short seqno = 1;
static char log_flag = 1;
static int sem_id = 0;
static char process_name[64];
char log_path[1024];
char shm_path[1024];
char sem_path[1024];
char conf_path[1024];

int host_name_size = 0;
char host_name[HOST_NAME_SIZE];
int semid = -1;
SHM *shm_ptr;

//20100510
int total_ping_time, elapsed_ping_time;
int get_netcard_status(NETCARD_INFO_ST *);

/****dotconf****/
static DOTCONF_CB(cb_str);
static DOTCONF_CB(cb_int);
int nicnum = 0;
CONFIG_FILE_ST conf;

char myconf[][64] = {
	"domain",			// 0
	"serv",				// 1 
	"event",			// 2
	"udpport",			// 3
	"sys_netcard_shm_path",		// 4 
	"sys_netcard_sem_path",		// 5
	"monitor_interval",		// 6
	"write_interval",		// 7
	"flow_interval",		// 8
	"flow_limit",			// 9
	"flow_peak",			// 10
	"udp",				// 11
	"nic",				// 12
	"ping",				// 13
	"pingnum",			// 14
	"pinglap",			// 15
	"crazyping",			// 16
	""
};

static const configoption_t options[] = {
	{myconf[0],  ARG_INT, cb_int, NULL, CTX_ALL},
	{myconf[1],  ARG_INT, cb_int, NULL, CTX_ALL},
	{myconf[2],  ARG_INT, cb_int, NULL, CTX_ALL},
	{myconf[3],  ARG_INT, cb_int, NULL, CTX_ALL},
	{myconf[4],  ARG_STR, cb_str, NULL, CTX_ALL},
	{myconf[5],  ARG_STR, cb_str, NULL, CTX_ALL},
	{myconf[6],  ARG_INT, cb_int, NULL, CTX_ALL},
	{myconf[7],  ARG_INT, cb_int, NULL, CTX_ALL},
	{myconf[8],  ARG_INT, cb_int, NULL, CTX_ALL},
	{myconf[9],  ARG_INT, cb_int, NULL, CTX_ALL},
	{myconf[10], ARG_INT, cb_int, NULL, CTX_ALL},
	{myconf[11], ARG_STR, cb_str, NULL, CTX_ALL},
	{myconf[12], ARG_STR, cb_str, NULL, CTX_ALL},       
	{myconf[13],  ARG_STR, cb_str, NULL, CTX_ALL},
	{myconf[14],  ARG_INT, cb_int, NULL, CTX_ALL},
	{myconf[15],  ARG_INT, cb_int, NULL, CTX_ALL},
	{myconf[16],  ARG_INT, cb_int, NULL, CTX_ALL},
	LAST_OPTION
};

/* 1 for output more debug information, from getenv(SYS_NIC_DEBUG) */
static int sys_nic_debug = 0;

/****dotconf****/

void create_dir(char *create_path);

#if 0
///////////////// no use

static pthread_mutex_t  lock_record_log = PTHREAD_MUTEX_INITIALIZER;
#define LOG_LOCK pthread_mutex_lock(&lock_record_log)
#define LOG_UNLOCK pthread_mutex_unlock(&lock_record_log)

#define MAX_LOG_COUNT 5000
static char **log_prepare = NULL;
static char **log_writing = NULL;
static int log_thread_exit = 1;
static int log_idx = 0;

static void *record_log_thread( void *arg )
{
	char *log_str;
	FILE *log_fp = NULL;
	char **tmp = NULL;
	inti i = 0;

	create_dir( log_path );

	log_thread_exit = 0;

	log_fp = fopen(log_path, "a");
	
	while( !log_thread_exit ) {
		if( !log_fp ) {
			log_fp = fopen(log_path, "a");
		}

		//prepare log strings
		LOG_LOCK;
		tmp = log_writing;
		log_writing = log_prepare;
		log_prepare = log_writing;
		log_idx=0;
		LOG_UNLOCK;

		while( i < MAX_LOG_COUNT ) {
			log_str = log_writing[i];

			if( log_str == NULL ) {
				break;
			}

			if( log_fp ) {
				fwrite( log_str, 1, strlen(log_str), log_fp );  //write to file
			}

			free( log_str );        //free
			log_writing[i] = NULL;  //clear

			//next
			i++;
		}
		usleep(100);
	} //while

	if( log_fp ) {
		fclose(log_fp);
	}
	if( log_prepare ) free( log_prepare );
	if( log_writing ) free( log_writing );
	log_prepare = NULL;
	log_writing = NULL;

	return NULL;	
}

/* write error in logfile */
void record_log(char *str)
{
#if 0
	time_t tamp;
	char str_tm[4];
	char log_str[512];
	FILE *log_fp = NULL;
	struct tm tmptr;
	struct timeval tv;
	struct timezone tz;

	if((log_fp = fopen(log_path, "a")) != NULL){
		tamp = time(NULL);
		memset(str_tm, 0, sizeof(str_tm));
		memset(log_str, 0, sizeof(log_str));
		localtime_r(&tamp, &tmptr);
		gettimeofday(&tv, &tz);
		snprintf(str_tm, sizeof(str_tm), "%d", (int)tv.tv_usec/1000);
		if(str_tm[1] == '\0')str_tm[1] = '0';
		if(str_tm[2] == '\0')str_tm[2] = '0';
		strftime(log_str, sizeof(log_str), "%F %T.", &tmptr);
		strcat(log_str, str_tm);
		strcat(log_str, " ");
		strcat(log_str, process_name);
		strcat(log_str, " ");
		strcat(log_str, str);
		if(fwrite(log_str, 1, strlen(log_str), log_fp) < 1){
		}
		fclose(log_fp);
	}	
#else
	static int log_thread_started = 0;
	time_t tamp;
	char str_tm[4];
	char log_str[512];
	struct tm tmptr;
	struct timeval tv;
	struct timezone tz;
	pthread_t pid;
	char *keepstr = strdup( log_str );

	tamp = time(NULL);
	memset(str_tm, 0, sizeof(str_tm));
	memset(log_str, 0, sizeof(log_str));
	localtime_r(&tamp, &tmptr);
	gettimeofday(&tv, &tz);
	snprintf(str_tm, sizeof(str_tm), "%d", (int)tv.tv_usec/1000);
	if(str_tm[1] == '\0')str_tm[1] = '0';
	if(str_tm[2] == '\0')str_tm[2] = '0';
	strftime(log_str, sizeof(log_str), "%F %T. %s %s %s", &tmptr, str_tm, process_name, str );

	//check log thread
	if( log_thread_started == 0 ) {
		log_thread_started = 1;
		log_prepare = (char **)malloc( sizeof(char *)*MAX_LOG_COUNT );
		log_writing = (char **)malloc( sizeof(char *)*MAX_LOG_COUNT );
		memset( log_prepare, 0, sizeof(char *) *MAX_LOG_COUNT );
		memset( log_writing, 0, sizeof(char *) *MAX_LOG_COUNT );
		log_idx = 0;

		pthread_create( &pid, NULL, record_log_thread, (void *)NULL );
	}

	LOG_LOCK;
	if( log_prepare ) {
		log_prepare[log_idx] = keepstr;
		log_idx++;
	}
	LOG_UNLOCK;	

#endif	
}

#else

#include "common.c"
#endif


static void init_sem(int *semid, CONFIG_FILE_ST *ptr)
{
	key_t key;
	char error_str[200];

	/* write error in logfile */
	memset(error_str, 0, sizeof(error_str));
#if 0
	if ((key = ftok(sem_path, SEM_PROJ_ID)) == -1) {
		snprintf(error_str, sizeof(error_str), "EMERG: ftok():%s\n", strerror(errno));
		record_log(error_str);
		return;
	}
#else
	key = 0x1d5200;
#endif

	if((*semid = semget(key, 1, IPC_CREAT|0666)) == -1){
		snprintf(error_str, sizeof(error_str), "EMERG: semget():%s\n", strerror(errno));
		record_log(error_str);
		return;
	}
	if(semctl(*semid, 0, SETVAL, 1) == -1){
		snprintf(error_str, sizeof(error_str), "EMERG: semctl: %s !\n", strerror(errno));
		record_log(error_str);
		semctl(*semid, 0, IPC_RMID);
		return;
	}
}

static int global_share_id = -1;
static int dir_share_id = -1;
static void *global_shmptr = NULL;

static void init_shm(SHM **ptr, CONFIG_FILE_ST *p)
{
#ifdef USE_OLD_MMSHARE
	int fd = -1;
	char error_str[200];

	mode_t mask_tmp;
	mask_tmp = umask(0000);
	if((fd = open(shm_path, O_RDWR|O_CREAT|O_TRUNC, 0666)) == -1){
		printf("could not create %s\n", shm_path);
		return;
	}
	umask(mask_tmp);
	lseek(fd, sizeof(SHM), SEEK_SET);
	write(fd, "\0", 1);
	*ptr = (SHM *)mmap(NULL, sizeof(SHM), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
	if(*ptr == MAP_FAILED){
		snprintf(error_str, sizeof(error_str), "EMERG: mmap():%s\n", strerror(errno));
		record_log(error_str);
		return;
	}
	close(fd);
#else
	void* shmptr = NULL;
	int size = 0;
	key_t share_key;
//	char *ref_count = NULL;
	//char *flag_str = NULL;
	char *path = shm_path;
	char error_str[200];

	size = sizeof(SHM);
	size = size + 16;

//	share_key = ftok(path, 0x000d5000);
	share_key = 0x1d5010;

#if 0
		snprintf( error_str, sizeof( error_str ), 
				"MSG: sys_nic, shm, size:%d, key:0x%x(%d)\n", size, share_key, share_key);
		record_log(error_str);
#endif

	global_share_id = shmget( share_key, size, IPC_CREAT|0666 );
	if( global_share_id == -1 ) {
		snprintf( error_str, sizeof( error_str ), 
				"EMERG: fail shmget, %s, 0x%x\n", strerror(errno), share_key);
		record_log(error_str);
        	return;
	}

	shmptr = shmat( global_share_id, NULL, 0 );
	if( shmptr == (void *)-1 ) {
		snprintf( error_str, sizeof( error_str ), 
				"EMERG: fail shmat, %s, %s\n", strerror(errno), path);
		record_log(error_str);
        	return;
	}

	//flag_str = (char *)shmptr+size-16;

//	if( strcmp( flag_str, "D5001" ) != 0 ) {
		//first, do init.
		memset( shmptr, 0, size );
//		strcpy( flag_str, "D5001" );
//	}

	global_shmptr = shmptr;

//	ref_count = (char *)shmptr+size-1;
//	(*ref_count)++;
	*ptr = (SHM *)shmptr;
#endif

}

static void get_sem(int semid)
{
	struct sembuf lock[2];
	char error_str[200];

	lock[0].sem_num = 0;
	lock[0].sem_op = -1;
	lock[0].sem_flg = SEM_UNDO;

	/*lock[1].sem_num = 0;
	lock[1].sem_op = 1;
	lock[1].sem_flg = SEM_UNDO;*/

	while(semop(semid, lock, 1)){
		if(errno == EINTR)continue;
		snprintf(error_str, sizeof(error_str), "EMERG: get_sem semop():%s\n", strerror(errno));
		record_log(error_str);
		return;
	}
}

static void release_sem(int semid)
{
	int ret;
	char error_str[200];
	struct sembuf unlock;

	unlock.sem_num = 0; 
	unlock.sem_op = 1;
	unlock.sem_flg = SEM_UNDO;

	if((ret = semop(semid, &unlock, 1)) == -1){
		snprintf(error_str, sizeof(error_str), "EMERG: rel_sem semop():%s\n", strerror(errno));
		record_log(error_str);
		return;
	}
}

static void proc_get_name(NET_NAME_ST *nodep)
{
	char linebuf[LINE_SIZE];
	char error_str[200];
	char *retp = NULL;
	int err_val=0;
	NET_NAME_ST *node = NULL;
	FILE *dev_fp;

	if((dev_fp = fopen("/proc/net/dev", "rb")) == NULL){
		snprintf(error_str, sizeof(error_str), "EMERG:  Can't open dev file:%s\n", strerror(errno));
		record_log(error_str);
		return;
	}
	memset(linebuf, 0, sizeof(linebuf));
	fgets(linebuf, sizeof(linebuf), dev_fp);
	fgets(linebuf, sizeof(linebuf), dev_fp);
	while((retp = fgets(linebuf, sizeof(linebuf), dev_fp)) != NULL){
		if((node = (NET_NAME_ST *)malloc(sizeof(NET_NAME_ST))) == NULL){
			err_val = 1;
			break;
		}
		memset(node->name, 0, NIC_NAME_LEN);
		get_name(node->name, retp);
		node->next = nodep->next;
		nodep->next = node;
	}
	if(err_val){
		NET_NAME_ST *curr = nodep->next;
		while(curr != NULL){
			node = curr->next;
			free(curr);
			curr = node;
		}
	}
	fclose(dev_fp);
}

static void ioctl_get_name(NET_NAME_ST *nodep)
{
	int count = 0;
	int inuse = 0;
	int err_val = 0;
	NETCARD_INFO net_name[MAXNICNUM];
	NET_NAME_ST *node = NULL, *curr = NULL;

	memset(net_name, 0, sizeof(net_name));
	if((count = ioc_get_name(net_name)) == 0)return;
	if(nodep->next == NULL)
		inuse = 1;
	while(count > 0){
		curr = nodep->next;
		while(curr != NULL){
			if(!strncmp(net_name[count - 1].charname, curr->name, NIC_NAME_LEN)){
				inuse = 0;
				break;
			}
			inuse = 1;
			curr = curr->next;
		}
		if(inuse){
			if((node = (NET_NAME_ST *)malloc(sizeof(NET_NAME_ST))) == NULL){
				err_val = 1;
				break;
			}
			memset(node->name, 0, NIC_NAME_LEN);
			strncpy(node->name, net_name[count - 1].charname, NIC_NAME_LEN);
			node->next = nodep->next;
			nodep->next = node;
		}
		count--;
	}
	if(err_val){
		curr = nodep->next;
		while(curr != NULL){
			node = curr->next;
			free(curr);
			curr = node;
		}
	}
}

static void get_all_name(NET_NAME_ST *nodep)
{
	proc_get_name(nodep);
	ioctl_get_name(nodep);
}

static void create_monit_list(NET_NAME_ST *nodep, NETCARD_INFO_ST *info_list, char *bond)
{
	int err_val = 0;
	NETCARD_INFO_ST *info_node = NULL;
	NET_NAME_ST *curr, *node;

	curr = nodep->next;
	while(curr != NULL){
		if((info_node = (NETCARD_INFO_ST *)malloc(sizeof(NETCARD_INFO_ST))) == NULL){
			err_val = 1;
			break;
		}
		memset(info_node, 0, sizeof(NETCARD_INFO_ST));
		strncpy(info_node->info.charname, curr->name, NIC_NAME_LEN);
		strncpy(info_node->info.descr, bond, strlen(bond));
		info_node->next = info_list->next;
		info_list->next = info_node;
		curr = curr->next;
	}
	if(err_val){
		NETCARD_INFO_ST *info_curr = info_list->next;
		while(info_curr != NULL){
			info_node = info_curr->next;
			free(info_curr);
			info_curr = info_node;
		}
		curr = nodep->next;
		while(curr != NULL){
			node = curr->next;
			free(curr);
			curr = node;
		}
	}
}

static int get_inc_info(NETCARD_INFO *net)
{
	return if_fetch(net);
}

static void get_inc_stats(NETCARD_INFO *net)
{
	char linebuf[LINE_SIZE];
	char *retp = NULL;
	char *str  = NULL;
	FILE *dev_fp;

	if((dev_fp = fopen("/proc/net/dev", "r")) == NULL)return;
	memset(linebuf, 0, sizeof(linebuf));
	while((retp = fgets(linebuf, sizeof(linebuf), dev_fp)) != NULL){
		if((str = strstr(linebuf, net->charname)) != NULL){
			str +=strlen(net->charname) + 2;
			get_dev_fields(str, net);
			break;
		}
	}
	fclose(dev_fp);
}

static void send_inc_info_one(NETCARD_INFO *net, int semid, SHM *ptr)
{
	int i;
	for(i = 0; ptr->info[i].charname[0] != 0; i++){
		if(!strncmp(ptr->info[i].charname, net->charname, NIC_NAME_LEN)){
			get_sem(semid);
			memcpy(&ptr->info[i], net, sizeof(NETCARD_INFO));
			release_sem(semid);	
		}
	}
}

static void *send_inc_info(void *p)
{
	int i = 0;
	int flags = 1;
	char error_str[200];
	unsigned long long bytes[MAXNICNUM];
	THMEM *ptr = (THMEM *)p;
	NETCARD_INFO_ST *curr;
	struct timespec s_time, os_time;

	if((curr = ptr->listp->next) == NULL){
		pthread_mutex_lock(&mut);
		snprintf(error_str, sizeof(error_str), "EMERG: Empty Netcard list!\n");
		record_log(error_str);
		pthread_mutex_unlock(&mut);
		return NULL;
	}
	s_time.tv_sec = ptr->conf->write_interval;
	s_time.tv_nsec = 0;	

	/* copy all net_info*/
	while(1){
		i = 0;
		get_sem(ptr->semid);
		//memset(ptr->shm_ptr, 0, sizeof(SHM));
		curr = ptr->listp->next;
		while(curr != NULL){
			get_inc_info(&curr->info);
			if(curr->status == NIC_UNLINKABLE){
				curr->info.flags &= (~IFF_UP);
				curr->info.flags &= (~IFF_RUNNING);
			}
			get_inc_stats(&curr->info);
			if(flags){
				bytes[i] = curr->info.rx_bytes + curr->info.tx_bytes;
			}
			curr->info.average_flow =(unsigned long long)((curr->info.rx_bytes + curr->info.tx_bytes - bytes[i])/(ptr->conf->write_interval));
			memcpy(&ptr->shm_ptr->info[i], &curr->info, sizeof(NETCARD_INFO));
			bytes[i] = curr->info.rx_bytes + curr->info.tx_bytes;
			i++;
			curr = curr->next;
		}
		release_sem(ptr->semid);
		flags = 0;
		nanosleep(&s_time, &os_time);
	}
}

static int get_netcard_count(char *name)
{
	int count  = 0;
	FILE *fp = NULL;
	char path[64] = "/proc/net/bonding/";
	char buf[LINE_SIZE];
	char *retp = NULL;
	char *str = NULL;

	strncat(path, name, strlen(name));
	if((fp = fopen(path, "r")) == NULL)return 1;

	memset(buf, 0, sizeof(buf));
	fseek(fp, 65, SEEK_SET);
	while((retp = fgets(buf, sizeof(buf), fp)) != NULL){
		if((str = strstr(buf, "active-backup")) != NULL){
			fclose(fp);
			return 1;
		}
		if(!strncmp(buf, "Slave Interface:", 16))count++;
	}
	fclose(fp);
	return count;
}

static void *cacu_flow(void *p)
{
	int i = 0, count_t = 1;
	int summit = 0;
	int flags = 1;
	int count_ok[MAXNICNUM];
	int count_no[MAXNICNUM];
	char error_str[200];
	unsigned long long bytes[MAXNICNUM];
	THFLOW *ptr = (THFLOW *)p;
	NETCARD_INFO_ST *curr;
	struct timespec s_time, os_time;

	if((curr = ptr->mem.listp->next) == NULL){
		pthread_mutex_lock(&mut);
		snprintf(error_str, sizeof(error_str), "EMERG: Empty Netcard list!\n");
		record_log(error_str);
		pthread_mutex_unlock(&mut);
		return NULL;
	}
	s_time.tv_sec = ptr->mem.conf->flow_interval;
	s_time.tv_nsec = 0;

	for(i = 0; i < MAXNICNUM ; i++){
		count_ok[i] = 0;
		count_no[i] = 0;
	}
	while(1){
		i = 0;
		curr = ptr->mem.listp->next;
		while(curr != NULL){
			get_inc_info(&curr->info);
			get_inc_stats(&curr->info);
			if(flags){
				bytes[i] = curr->info.rx_bytes + curr->info.tx_bytes;
			}
			curr->info.average_flow =(unsigned long long)((curr->info.rx_bytes + curr->info.tx_bytes - bytes[i])/ptr->mem.conf->flow_interval);
			if(!strncmp(curr->info.charname, "bond", 4)){
				count_t = get_netcard_count(curr->info.charname);
			}else {
				count_t = 1;
			}
			summit = (unsigned int)(curr->info.average_flow/1024/1024/ptr->mem.conf->flow_peak/count_t*8*100);
			if( sys_nic_debug ) {
#if  1
				printf("%s:\tcount=%d\tsummit=%d\tflow_limit:%d\taverage_flow:%lld\n", curr->info.charname, count_t, summit, conf.flow_limit, curr->info.average_flow);
#endif
				snprintf(error_str, sizeof(error_str), "%s:\tcount=%d\tsummit=%d\tflow_limit:%d\taverage_flow:%lld\tbytes[%d]:%lld\tcurr->info.rx_bytes:%lld\tcurr->info.tx_bytes\n",
                        curr->info.charname, count_t, summit, conf.flow_limit, curr->info.average_flow,i,bytes[i],curr->info.rx_bytes,curr->info.tx_bytes);
				record_log(error_str);

			}

			if(summit >= ptr->mem.conf->flow_limit){
				memset(ptr->env.Malarm.tSysNetcardAlarm.fault_devname, 0, NIC_NAME_LEN);
				strncpy(ptr->env.Malarm.tSysNetcardAlarm.fault_devname, ptr->env.host_name, ptr->env.host_name_size);
				strncat(ptr->env.Malarm.tSysNetcardAlarm.fault_devname, "-", 1);
				strncat(ptr->env.Malarm.tSysNetcardAlarm.fault_devname, curr->info.charname, (NIC_NAME_LEN - ptr->env.host_name_size - 1));
				ptr->env.Malarm.tSysNetcardAlarm.flags = NETCARD_ALARM_ABNORMAL;
				ptr->env.Malarm.tSysNetcardAlarm.retrytimes = 0;
				ptr->env.Malarm.tMsgFrame.len = sizeof(ptr->env.Malarm);
				ptr->env.Malarm.tMsgFrame.seqno = seqno;
				pthread_mutex_lock(&mut);
				while(count_no[i] > 0){
					send_alarm(&ptr->env.Malarm, ptr->mem.conf->udpport, ptr->mem.conf->ip);
					seqno++;
					ptr->env.Malarm.tMsgFrame.seqno = seqno;
					ptr->env.Malarm.tSysNetcardAlarm.retrytimes++;
					count_no[i]--;
					if(count_no[i] == 0){
						send_inc_info_one(&curr->info, ptr->mem.semid, ptr->mem.shm_ptr);
						if( sys_nic_debug ) {
							snprintf(error_str, sizeof(error_str), 
									"NOTICE: %s flow is abnormal, summit is %d, average flow is %lld !\n", 
									curr->info.charname, summit, curr->info.average_flow);
						} else {
							snprintf(error_str, sizeof(error_str), "NOTICE: %s flow is abnormal !\n", curr->info.charname);
						}
						record_log(error_str);
					}
				}
				pthread_mutex_unlock(&mut);
				count_ok[i] = 3;
			}else{
				memset(ptr->env.Malarm.tSysNetcardAlarm.fault_devname, 0, NIC_NAME_LEN);
				strncpy(ptr->env.Malarm.tSysNetcardAlarm.fault_devname, ptr->env.host_name, ptr->env.host_name_size);
				strncat(ptr->env.Malarm.tSysNetcardAlarm.fault_devname, "-", 1);
				strncat(ptr->env.Malarm.tSysNetcardAlarm.fault_devname, curr->info.charname, (NIC_NAME_LEN - ptr->env.host_name_size - 1));
				ptr->env.Malarm.tSysNetcardAlarm.flags = NETCARD_ALARM_NORMAL;
				ptr->env.Malarm.tSysNetcardAlarm.retrytimes = 0;
				ptr->env.Malarm.tMsgFrame.len = sizeof(ptr->env.Malarm);
				ptr->env.Malarm.tMsgFrame.seqno = seqno;
				pthread_mutex_lock(&mut);
				while(count_ok[i] > 0){
					send_alarm(&ptr->env.Malarm, ptr->mem.conf->udpport, ptr->mem.conf->ip);
					seqno++;
					ptr->env.Malarm.tMsgFrame.seqno = seqno;
					ptr->env.Malarm.tSysNetcardAlarm.retrytimes++;
					count_ok[i]--;
					if(count_ok[i] == 0){
						send_inc_info_one(&curr->info, ptr->mem.semid, ptr->mem.shm_ptr);
						snprintf(error_str, sizeof(error_str), "NOTICE: %s flow is normal now !\n", curr->info.charname);
						record_log(error_str);
					}
				}
				pthread_mutex_unlock(&mut);
				count_no[i] = 3;
			}/* end if(summit... */
			bytes[i] = curr->info.rx_bytes + curr->info.tx_bytes;
			i++;
			curr = curr->next;
		}/* end while(curr...) */
		flags = 0;
		nanosleep(&s_time, &os_time);
	}/* end while(1) */
}
static char *parse_str(char **s)
{
	char *retp = NULL;
	char *p = *s;

	while(isspace(*p))p++;
	retp = p;
	while(!isspace(*p))p++;
	*p = '\0';

	return retp;
}

int ping_gw(char *devname)
{
	FILE *fp;
	int i, j, k;
	char buf[128];
	char getbuf[64];

	i = find_nic_config(devname);
	if( i == -1 )
		return 0;

	if(conf.nic[i].gw_num == 0)
		return 0;

	for(k=0; k<conf.pingnum; ++k){
		for(j=0; j<conf.nic[i].gw_num; ++j){
			snprintf(buf,sizeof(buf),"ping -c 1 -w %d %s|grep received|awk -F, '{print $2}'|awk '{print $1}'", conf.pinglap,conf.nic[i].ping_ip[j]);
			if((fp = popen(buf,"r")) == NULL)
			{
				//perror("popen");
				//return 0;
				continue;
			}else{
				fgets(getbuf,sizeof(getbuf),fp);
				if(strncmp(getbuf,"0",1) != 0)
				{
					pclose(fp);
					return 0;
				}else{
					pclose(fp);
					//return -1;
					continue;
				}
			}
			pclose(fp);
			return 0;

		}
	}

	return -1;
}

static void *check_inc_switch(void *ptr)
{
	THENV *arg = (THENV *)ptr;
	FILE *fp = NULL;
	char name[NIC_NAME_LEN];
	struct timespec s_time, os_time;
	int count = 0;
	char linebuf[LINE_SIZE];
	char error_str[200];
	char *str = NULL;
	char *retp = NULL;

	if((fp = fopen(arg->bond_file_path, "r")) == NULL){
		snprintf(error_str, sizeof(error_str), "EMERG: fopen():%s\n", strerror(errno));
		record_log(error_str);
		free(ptr);
		return NULL;
	}
	fseek(fp, 65, SEEK_SET);
	memset(name, 0, sizeof(name));
	memset(linebuf, 0, sizeof(linebuf));
	if((retp = fgets(linebuf, sizeof(linebuf), fp)) != NULL){
		if((retp = strstr(linebuf, "active-backup")) == NULL){
			free(ptr);
			fclose(fp);
			return NULL;
		}
	}

	s_time.tv_sec = 0;
	s_time.tv_nsec = 100000000;

	while(1){
		while((str = fgets(linebuf, sizeof(linebuf), fp)) != NULL){
			if(!strncmp(linebuf, "Currently Active Slave:", 23)){
				str += 23;
				retp = parse_str(&str);
				break;
			}
		}
		if(name[0] == 0){
			strncpy(name, retp, strlen(retp));
		}else if(strncmp(name, retp, strlen(retp)) != 0){
			memset(arg->Malarm.tSysNetcardAlarm.switch_devname, 0, NIC_NAME_LEN);
			strncpy(arg->Malarm.tSysNetcardAlarm.switch_devname, arg->host_name, arg->host_name_size);
			strncat(arg->Malarm.tSysNetcardAlarm.switch_devname, "-", 1);
			strncat(arg->Malarm.tSysNetcardAlarm.switch_devname, retp, (NIC_NAME_LEN - arg->host_name_size - 1));
			arg->Malarm.tSysNetcardAlarm.flags = NETCARD_ALARM_SWITCH;
			arg->Malarm.tSysNetcardAlarm.retrytimes = 0;
			arg->Malarm.tMsgFrame.len = sizeof(arg->Malarm);
			arg->Malarm.tMsgFrame.seqno = seqno;
			count = 3;
			pthread_mutex_lock(&mut);
			snprintf(error_str, sizeof(error_str),  "NOTICE: Net card checking to %s!\n", retp);
			record_log(error_str);
			while(count > 0){
				send_alarm(&arg->Malarm, arg->conf->udpport, arg->conf->ip);
				seqno++;
				arg->Malarm.tMsgFrame.seqno = seqno;
				arg->Malarm.tSysNetcardAlarm.retrytimes++;
				count--;
			}
			pthread_mutex_unlock(&mut);
			memset(name, 0, NIC_NAME_LEN);
			strncpy(name, retp, strlen(retp));
		}
		fclose(fp);
		nanosleep(&s_time, &os_time);
		if((fp = fopen(arg->bond_file_path, "r")) == NULL){
			free(ptr);
			return NULL;
		}
		fseek(fp, 65, SEEK_SET);
	}
	free(ptr);
	fclose(fp);
	return NULL;
}

static void *create_logfile(void *ptr)
{
	char buf[128];
	char del_file[DAYS][1024];
	char *s;
	int head, tail, fd;
	int flag = 0, del_flag = 0;
	int old_mon = 0;
	int old_day = 0;
	time_t tamp;
	struct tm tmptr;
	struct timespec s_time, os_time;

	s_time.tv_sec = 1;
	s_time.tv_nsec = 0;
	head = tail = 0;
	while(1){
		tamp = time(NULL);
		localtime_r(&tamp, &tmptr);
		if(old_mon != (tmptr.tm_mon + 1))flag = 1;
		else if(old_day != tmptr.tm_mday)flag = 1;
		else flag = 0;
		if(flag){
			LOGPATH_LOCK;
			s = strrchr(log_path, '/');
			s++;
			*s = '\0';
			memset(buf, 0, sizeof(buf));
			strftime(buf, sizeof(buf), "%Y%m%d_", &tmptr);
			strcat(buf, process_name);
			strcat(buf, ".log");
			strcat(log_path, buf);

			mode_t mask_tmp;
			mask_tmp = umask(0000);
			if((fd = open(log_path, O_RDWR|O_CREAT, 0666)) != -1){
				log_flag = 0;
				close(fd);
			}
			umask(mask_tmp);
			strcpy(del_file[head++], log_path);
			LOGPATH_UNLOCK;

			old_mon = tmptr.tm_mon+1;
			old_day = tmptr.tm_mday;
	//		strcpy(del_file[head++], log_path);

			if(head == DAYS){
				head = 0;
				del_flag = 1;
			}
			if(del_flag){
				unlink(del_file[tail]);
				tail++;
				if(tail == DAYS)tail = 0;
			}
		}
		nanosleep(&s_time, &os_time);
	}
}

void write_time(int semid, SHM *ptr)
{
	int i = 0;
	int flag_time_stamp;

	flag_time_stamp = time(NULL);

	while(ptr->info[i].charname[0] != 0){
		ptr->info[i].time_stamp = flag_time_stamp;
		i++;
	}
}
#if  0
char *parse(char *line)
{
	char *begin = NULL;
	char *end = NULL;

	if((begin = strchr(line, '/')) != NULL){
		if((end = strstr(line, "bin")) != NULL){
			*end='\0';
			return begin;
		}
	}
	return NULL;
}
#endif
void release_name_list(NET_NAME_ST *head)
{
	NET_NAME_ST *curr, *save;

	curr = head->next;
	while(curr != NULL){
		save = curr->next;
		free(curr);
		curr = save;
	}
}
int get_netcard(char *line, char *nic)
{
	char *begin, *retp;

	while(isspace(*line))line++;
	begin = line;
	while(!isspace(*line))line++;
	*line++ = '\0';
	if(!strncmp(begin, "nic", 4)){
		if((retp = parse_str(&line)) != NULL){
			strncpy(nic, retp, MAXNICNUM);
			return 1;
		}
	}
	return 0;
}

void sig_handler(int sig)
{
	//	char err_str[200];

#if  0
	if(unlink(SHM_PATH) == -1){
		snprintf(err_str, sizeof(err_str), "NOTICE: error delete %s\n", strerror(errno));
		record_log(err_str);
	}
	if(unlink(SEM_PATH) == -1){
		snprintf(err_str, sizeof(err_str), "NOTICE: error delete %s\n", strerror(errno));
		record_log(err_str);
	}
#endif
	//	semctl(sem_id, 0, IPC_RMID);	

	//	snprintf(err_str, sizeof(err_str), "NOTICE: process exit by signal %d\n", sig);
	//	record_log(err_str);
	semctl(semid,0,IPC_RMID,0);
	shmctl(global_share_id,IPC_RMID,NULL);
	shmctl(dir_share_id,IPC_RMID,NULL);
	exit(0);
}

/*
 * 查看数据结构中是否有给定的网卡
 * 输入：网卡名称
 * 返回值：-1 表示没有
 * 	非0值表示设备列表中的索引
 *
 */
int find_nic_config(char *dev_name){
	int i, index=-1;

	for(i=0; i<nicnum; ++i)
		if(!strcmp(dev_name, conf.nic[i].dev_name))
			index = i;

	return index;
}

/*get_ping_server*/
DOTCONF_CB(cb_str)
{
	int i, index, card_info_index;
	char wrong_ip[125] = {0};

	//"ping"选项的处理
	if((strcmp(cmd ->name, myconf[13]) == 0) && (nicnum <= MAXNICNUM)){
		i = 1;
		if(cmd->data.list[0] && cmd->data.list[1]){
			//查找设备列表中是否已有该网卡
			//如果没有则创建一项
			//如果已有则只要增加ping的地址和地址数量
			//一般都能找到，因为配置文件中一般总是先定义"nic"，后定义"ping"
			//如果没找到，则表明先定义了"ping"，未定义"nic"或后定义"nic"，而未定义"nic"应该是错误的
			index = find_nic_config(cmd->data.list[0]);
			if(index == -1){
				strncpy(conf.nic[nicnum].dev_name, cmd->data.list[0], strlen(cmd->data.list[0]) >= IPLEN ? IPLEN-1 : strlen(cmd->data.list[0]));
				card_info_index = nicnum;
				nicnum++;
			}
			else
				card_info_index = index;

			while(cmd->data.list[i]){
				if((int)(inet_addr(cmd->data.list[i])) == -1){
					sprintf(wrong_ip,"The wrong IP address:'%s'",cmd->data.list[i]);
					strcat(wrong_ip,"\n");
					record_log(wrong_ip);
				} else{
					strncpy(conf.nic[card_info_index].ping_ip[conf.nic[card_info_index].gw_num++], cmd->data.list[i], strlen(cmd->data.list[i]) >= IPLEN ? IPLEN-1 : strlen(cmd->data.list[i]));
				}
				i++;
			}
		}
	}

	//"nic"选项的处理
	if((strcmp(cmd ->name, myconf[12]) == 0) && (nicnum <= MAXNICNUM)){
		//设备列表中没有给定的网卡设备，则添加一项
		//否则不必添加
		//对应配置文件中先指定"ping"后指定"nic"的情况
		index = find_nic_config(cmd->data.str);
		if(index == -1){
			strncpy(conf.nic[nicnum].dev_name, cmd->data.str, strlen(cmd->data.str) >= NIC_NAME_LEN ? NIC_NAME_LEN-1 : strlen(cmd->data.str));
			nicnum++;
		}
	}

	if((strcmp(cmd ->name, myconf[11]) == 0)){
		strncpy(conf.udp, cmd->data.str, strlen(cmd->data.str));
	}

	return NULL;
}

DOTCONF_CB(cb_int)
{
	if(strcmp(cmd ->name, myconf[0]) == 0){
		conf.domain = cmd->data.value;
	}
	if(strcmp(cmd ->name, myconf[1]) == 0){
		conf.serv = cmd->data.value;
	}
	if(strcmp(cmd ->name, myconf[2]) == 0){
		conf.event = cmd->data.value;
	}
	if(strcmp(cmd ->name, myconf[3]) == 0){
		conf.udpport = cmd->data.value;
	}
	if(strcmp(cmd ->name, myconf[6]) == 0){
		conf.monitor_interval = cmd->data.value;
	}
	if(strcmp(cmd ->name, myconf[7]) == 0){
		conf.write_interval = cmd->data.value;
	}
	if(strcmp(cmd ->name, myconf[8]) == 0){
		conf.flow_interval = cmd->data.value;
	}
	if(strcmp(cmd ->name, myconf[9]) == 0){
		conf.flow_limit = cmd->data.value;
	}
	if(strcmp(cmd ->name, myconf[10]) == 0){
		conf.flow_peak = cmd->data.value;
	}
	if(strcmp(cmd ->name, myconf[14]) == 0){
		conf.pingnum = cmd->data.value;
	}
	if(strcmp(cmd ->name, myconf[15]) == 0){
		conf.pinglap = cmd->data.value;
	}
	if(strcmp(cmd ->name, myconf[16]) == 0){
		conf.crazyping = cmd->data.value;
	}


	return NULL;
}

DOTCONF_CB(cb_list)
{
	return NULL;
}

int get_conf()
{
	//	int uid;
	//	char buf[1024];
	//        int i;
	//	struct passwd *user;
	configfile_t *configfile;
    char tmp_str[256];

	//	memset(buf, 0, sizeof(buf));
	//	uid=getuid();
	//	user = getpwnam("d5000");
	//	user = getpwuid(uid);

	//	sprintf(buf,"%s", user->pw_dir);
	//	strcat(buf,conf_path);

	configfile = dotconf_create(conf_path, options, NULL, CASE_INSENSITIVE);
	if (!configfile)
	{
        sprintf(tmp_str,"%s","Warning can't reading config file\n");
		record_log(tmp_str);
		return -1;
	}

	if (dotconf_command_loop(configfile) == 0){
        sprintf(tmp_str,"%s","Warning can't reading config file\n");
		record_log(tmp_str);
		return -1;
	}
	dotconf_cleanup(configfile);

	if(conf.domain == 0)
		conf.domain = 10;
	if(conf.serv == 0)
		conf.serv = 1;
	if(conf.event == 0)
		conf.event = 2;
	if(conf.udpport == 0)
		conf.udpport = 15000;
	if(conf.monitor_interval == 0)
		conf.monitor_interval = 100;
	if(conf.write_interval == 0)
		conf.write_interval = 300;
	if(conf.flow_interval == 0)
		conf.flow_interval = 60;
	if(conf.flow_limit == 0)
		conf.flow_limit = 30;
	if(conf.flow_peak == 0)
		conf.flow_peak = 1000;
	if(conf.udp[0] == 0)
		strcpy(conf.udp, "bond0");
	if(conf.nic[0].dev_name[0] == 0)
		strcpy(conf.nic[0].dev_name, "bond0");
	if(conf.pingnum == 0)
		conf.pingnum = 2;
	if(conf.pinglap == 0)
		conf.pinglap = 1;

	return 0;
}

int isrun(char *p)
{
	char buf[16];
	char cmdbuf[1024];
	FILE *fp;

	memset(buf, 0, sizeof(buf));
	memset(cmdbuf, 0, sizeof(cmdbuf));

	snprintf(cmdbuf, sizeof(cmdbuf), "pidof %s", p);
	fp=popen(cmdbuf, "r");
	fread(buf, sizeof(char), sizeof(buf), fp);
	pclose(fp);
	if(strchr(buf, ' ') != NULL)
		return 1;
	else
		return 0;
}

int get_broad_ip(void)
{
	char ip_p[4][4];
	char error_str[200];
	int skfd;
	struct ifreq ifr;

	memset(&ifr, 0, sizeof(ifr));
	memset(ip_p, 0, sizeof(ip_p));

	if((skfd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)return -1;
	strcpy(ifr.ifr_name, conf.udp);
	if (!ioctl(skfd, SIOCGIFBRDADDR, &ifr)){
		sprintf(ip_p[0], "%d", (unsigned char)ifr.ifr_broadaddr.sa_data[2]);
		sprintf(ip_p[1], "%d", (unsigned char)ifr.ifr_broadaddr.sa_data[3]);
		sprintf(ip_p[2], "%d", (unsigned char)ifr.ifr_broadaddr.sa_data[4]);
		sprintf(ip_p[3], "%d", (unsigned char)ifr.ifr_broadaddr.sa_data[5]);
	}else{
		snprintf(error_str, sizeof(error_str),  "EMERG: Invalid broadcast device -- %s\n", conf.udp);
		record_log(error_str);
		close(skfd);
		return -1;
	}
	close(skfd);
	strcat(conf.ip, ip_p[0]);
	strcat(conf.ip, ".");
	strcat(conf.ip, ip_p[1]);
	strcat(conf.ip, ".");
	strcat(conf.ip, ip_p[2]);
	strcat(conf.ip, ".");
	strcat(conf.ip, ip_p[3]);

	return 0;
}

void create_semdir()
{
#if 0
	int ret = 0;
	mode_t mask_tmp;

	mask_tmp = umask(0000);
	create_dir(sem_path);
	if((ret = open(sem_path, O_RDWR | O_CREAT, 0666)) != -1){
		close(ret);
	}
	umask(mask_tmp);
#endif
}
void create_shmdir()
{
#if 0
	int ret = 0;
	mode_t mask_tmp;

	mask_tmp = umask(0000);
	create_dir(shm_path);
	if((ret = open(shm_path, O_RDWR | O_CREAT, 0666)) != -1){
		close(ret);
	}
	umask(mask_tmp);
#endif
}
void create_confdir()
{
	int ret = 0;
	mode_t mask_tmp;

	mask_tmp = umask(0000);
	create_dir(conf_path);
	if((ret = open(conf_path, O_RDWR | O_CREAT, 0666)) != -1){
		close(ret);
	}
	umask(mask_tmp);
}


void create_logdir()
{
	int len = 0;
	mode_t mask_tmp;

	mask_tmp = umask(0000);
	len = strlen(log_path);

	if(log_path[len-1]!='/')
		strcat(log_path, "/");
	create_dir(log_path);

	umask(mask_tmp);
}
/* create netcard name list */
int create_name_list(NET_NAME_ST *all_name_list, NET_NAME_ST *opt_name_list)
{
	int i, count_t, err_val = 0;
	NET_NAME_ST  *curr, *node;
	char error_str[200];

	for(i = 0, count_t = 0; conf.nic[i].dev_name[0] != 0 && (i < MAXNICNUM); i++){
		curr = all_name_list->next;
		while(curr != NULL){
			if(!strncmp(curr->name, conf.nic[i].dev_name, NIC_NAME_LEN)){
				if((node = (NET_NAME_ST *)malloc(sizeof(NET_NAME_ST))) == NULL){
					err_val = 1;
					break;
				}
				memset(node->name, 0, NIC_NAME_LEN);
				strncpy(node->name, conf.nic[i].dev_name, NIC_NAME_LEN);
				node->next = opt_name_list->next;
				opt_name_list->next = node;
				count_t ++;
				break;
			}
			curr = curr->next;
		}
		if(err_val)break;
	}
	if(count_t != i || err_val){
		for(curr = opt_name_list->next; curr != NULL; curr = curr->next)free(curr);
		snprintf(error_str, sizeof(error_str),   "EMERG: Invalid netcard name --\n");
		record_log(error_str);
		return -1;
	}
	err_val = 0;

	return 0;
}

int get_netcard_status(NETCARD_INFO_ST *listp)
{
	if((listp->info.flags & IFF_UP) != IFF_UP)
		return NIC_DOWN;

	if((listp->info.flags & IFF_RUNNING) != IFF_RUNNING)
		return NIC_UNRUNNING;

	//20100510
	if(conf.crazyping || (elapsed_ping_time == total_ping_time)){
		if(ping_gw(listp->info.charname) != 0)
			return NIC_UNLINKABLE;
	}
	else{
		if(listp->status ==  NIC_UNLINKABLE) 
			return NIC_UNLINKABLE;
	}

	return NIC_NORMAL;
}

int do_alarm(NETCARD_INFO_ST *listp, int nic_status, D5000_NIC_ALARM *Malarm)
{
	int i;
	char error_str[200];

	memset(Malarm->tSysNetcardAlarm.fault_devname, 0, NIC_NAME_LEN);
	strncpy(Malarm->tSysNetcardAlarm.fault_devname, host_name, host_name_size);
	strncat(Malarm->tSysNetcardAlarm.fault_devname, "-", 1);
	strncat(Malarm->tSysNetcardAlarm.fault_devname, listp->info.charname, NIC_NAME_LEN - host_name_size - 1);
	Malarm->tSysNetcardAlarm.retrytimes = 0;
	Malarm->tMsgFrame.len = sizeof(Malarm);
	Malarm->tMsgFrame.seqno = seqno;

	switch(nic_status){
		case NIC_DOWN:
			Malarm->tSysNetcardAlarm.flags = NETCARD_ALARM_FAULT;
			snprintf(error_str, sizeof(error_str), "NOTICE: %s is DOWN!\n", listp->info.charname);
			break;
		case NIC_UNRUNNING:
			Malarm->tSysNetcardAlarm.flags = NETCARD_ALARM_FAULT;
			snprintf(error_str, sizeof(error_str), "NOTICE: %s is UP but  UNRUNNING!\n", listp->info.charname);
			break;
		case NIC_UNLINKABLE:
			Malarm->tSysNetcardAlarm.flags = NETCARD_ALARM_FAULT;
			listp->info.flags &= (~IFF_UP);
			listp->info.flags &= (~IFF_RUNNING);
			snprintf(error_str, sizeof(error_str), "NOTICE: %s is RUNNING but UNLINKABLE!\n", listp->info.charname);
			break;
		case NIC_NORMAL:
			Malarm->tSysNetcardAlarm.flags = NETCARD_ALARM_RESUME;
			snprintf(error_str, sizeof(error_str), "NOTICE: %s is NORMAL!\n", listp->info.charname);
			break;
	}
	pthread_mutex_lock(&mut);
	for(i = 0; i < 3; i++){
		send_alarm(Malarm, conf.udpport, conf.ip);
		seqno++;
		Malarm->tMsgFrame.seqno = seqno;
		Malarm->tSysNetcardAlarm.retrytimes++;
	}
	send_inc_info_one(&listp->info, semid, shm_ptr);
	pthread_mutex_unlock(&mut);
	record_log(error_str);

	return 0;
}

int main(int argc, char ** argv)
{
	int id = -1;
        if((id = semget(0x1d5200, 1, 0666)) != -1)
                semctl(id,0,IPC_RMID,0);
        id = -1;
        if((id = shmget(0x1d5010,sizeof(SHM) + 16 , 0666)) != -1)
                shmctl(id,IPC_RMID,0);
        id = -1;
        if((id = shmget(0x1d6010, 128, 0666)) != -1)
                shmctl(id,IPC_RMID,0);

	int  ret = 0, proc_stat = 0;
	unsigned int i = 0;
	int nic_status;
	int sys_time_stamp = 0; 
	char *retp = NULL;
	char *str = NULL;
	char bond[128];
	char error_str[200];
	char linebuf[LINE_SIZE];
	THENV *arg;
	glob_t res;
	FILE *bond_fp = NULL;
	pthread_t tid[THRNR];
	pthread_t tid_mem;
	pthread_t tid_flow;
	pthread_t tid_time;
	THMEM mem;
	THFLOW flow;
	struct timespec s_time, os_time, log_time;
	NET_NAME_ST all_name_list, opt_name_list;
	NETCARD_INFO_ST  inc_info_list, *listp = NULL;
	D5000_NIC_ALARM Malarm;
	struct sigaction sig;
	struct passwd *user;

//#define TESTINTERVAL
#ifndef TESTINTERVAL
	proc_invocation prcm;
#endif
	char log_record[125]={0};
	char *dir_memory;
	int shm_key =0x1d6010;
	
	if( getenv("SYS_NIC_DEBUG") ) {
		sys_nic_debug = 1;
	} 

	memset(&conf, 0, sizeof(CONFIG_FILE_ST));
	if(isrun(argv[0]) == 1){
		printf("the program is already started!\n");
		exit(0);
	}
	//process register
#ifndef TESTINTERVAL
	if((proc_stat=prcm.proc_init("sys","base_srv","sys_nicmonitor"))==-1){
		perror("proc_init()");
		exit(-1);
	}
#endif

	sig.sa_handler = sig_handler;
	sigemptyset(&sig.sa_mask);
	sigaddset(&sig.sa_mask, SIGINT);
	sigaddset(&sig.sa_mask, SIGTERM);
	sig.sa_flags = 0;
	sigaction(SIGTERM, &sig, NULL); 
	sigaction(SIGINT, &sig, NULL); 
	sigaction(SIGSEGV, &sig, NULL); 

	/* create dir  file path */
	if((user = getpwnam("d5000")) != NULL){
		sprintf(log_path,"%s",user->pw_dir);
		sprintf(shm_path,"%s",user->pw_dir);
		sprintf(sem_path,"%s",user->pw_dir);
		sprintf(conf_path,"%s",user->pw_dir);
	}

	dir_share_id = shmget(shm_key,128,IPC_CREAT|0666);
	if(dir_share_id == -1)
		return -1;
	dir_memory = (char *) shmat(dir_share_id,NULL,0);
	if(dir_memory ==  (void *) -1)
		return -1;
	strcpy(dir_memory,user->pw_dir);
	strcat(log_path,LOG_PATH);
	strcat(shm_path,SHM_PATH);
	strcat(sem_path,SEM_PATH);
	strcat(conf_path,CONF_FILE);

	create_semdir();
	create_shmdir();
	create_logdir();
	create_confdir();

	/* get process name */
	memset(process_name, 0, sizeof(process_name));
	if((retp = strrchr(argv[0], '/')) != NULL){
		retp++;
		strcpy(process_name, retp);
	}else{
		strcpy(process_name, argv[0]);
	}
	/*create logfile thread */
	pthread_create(&tid_time, NULL, create_logfile, NULL);

	/* initialize some....*/
	memset(&all_name_list, 0, sizeof(NET_NAME_ST));
	all_name_list.next = NULL;
	memset(&opt_name_list, 0, sizeof(NET_NAME_ST));
	opt_name_list.next = NULL;

	memset(&inc_info_list, 0, sizeof(NETCARD_INFO_ST));
	inc_info_list.next = NULL;


	/* get all netcard by proc/net/dev and ioctl */
	get_all_name(&all_name_list);

	/* wait for create log thread */
	log_time.tv_sec = 0;
	log_time.tv_nsec = 1000000;
	while(log_flag)nanosleep(&log_time, NULL);

	/* sure the process is started */
	snprintf(error_str, sizeof(error_str), "NOTICE: %s V%s is started !\n", process_name, MNIC_VERSION);
	record_log(error_str);

	get_conf();

	if(shm_path){
		printf("shm_path:%s\n",shm_path);
		sprintf(log_record,"shm_path:%s\n",shm_path);
		record_log(log_record);
	}

	if(log_path){
		printf("log_path:%s\n",log_path);
		sprintf(log_record,"log_path:%s\n",log_path);
		record_log(log_record);
	}


	if(conf.udp){
		printf("udp    %s\n",conf.udp);
		sprintf(log_record,"udp    %s\n",conf.udp);
		record_log(log_record);
	}

	for(i=0;conf.nic[i].dev_name[0]!=0;i++){
		printf("nic    %s\n",conf.nic[i].dev_name);
		sprintf(log_record,"nic    %s\n",conf.nic[i].dev_name);
		record_log(log_record);
	}

	/* get broadcast address*/
	if((ret = get_broad_ip()) != 0)
		return -1;	
	if((ret = create_name_list(&all_name_list, &opt_name_list)) != 0)
		return -1;
	/* get hostname */
	if((ret = gethostname(host_name, sizeof(host_name))) != -1){
		host_name_size = strlen(host_name);
	}else host_name_size = HOST_NAME_SIZE;
	/* initialize Malarm */
	Malarm.tMsgFrame.serv = conf.serv;
	Malarm.tMsgFrame.event = conf.event;
	Malarm.tMsgFrame.domain = conf.domain;

	/* get bonding file */
	memset(bond, 0, sizeof(bond));
	memset(linebuf, 0, sizeof(linebuf));
	if((ret = glob(BOND_PATH, 0, NULL, &res)) != 0){
		snprintf(error_str, sizeof(error_str), "NOTICE: No bonding netcard !\n");
		record_log(error_str);
		strcpy(bond, "No bonding netcard!");
	}
	for (i = 0; i < res.gl_pathc; ++i) {
		if((arg = (THENV *)malloc(sizeof(THENV))) != NULL){
			memset(arg, 0, sizeof(THENV));
			strncpy(arg->bond_file_path, res.gl_pathv[i], strlen(res.gl_pathv[i]));
			arg->Malarm = Malarm;
			strncpy(arg->host_name, host_name, host_name_size);
			arg->host_name_size = host_name_size;
			arg->conf = &conf;
			if(pthread_create(tid+i, NULL, check_inc_switch, (void*)arg)){
				snprintf(error_str, sizeof(error_str), "EMERG: pthread_create(): %s\n", strerror(errno));
				record_log(error_str);
			}
		}
	}
	for(i = 0; i < res.gl_pathc; ++i){
		if((bond_fp = fopen(res.gl_pathv[i], "r")) == NULL){
			snprintf(error_str, sizeof(error_str), "EMERG: fopen(): %s\n", strerror(errno));
			record_log(error_str);
		}else{
			retp = strrchr(res.gl_pathv[i], '/');
			retp++;
			strcat(bond, retp);
			strcat(bond, ":");
			while((str = fgets(linebuf, sizeof(linebuf), bond_fp)) != NULL){
				if(!strncmp(linebuf, "Slave Interface:", 16)){
					str += 16;
					retp = parse_str(&str);
					strcat(bond, retp);
					strcat(bond, " ");
				}
			}
			fclose(bond_fp);
		}
	}

	/* initialize time*/
	s_time.tv_sec = 0;
	s_time.tv_nsec = conf.monitor_interval*1000*1000;

	/* initialize sem*/
	init_sem(&semid, &conf);
	init_shm(&shm_ptr, &conf);
	/* for IPC_RMID */
	sem_id = semid;

	/*  create monitor netcard list */
	create_monit_list(&opt_name_list, &inc_info_list, bond);
	release_name_list(&all_name_list);
	release_name_list(&opt_name_list);

	mem.semid = semid;
	mem.shm_ptr = shm_ptr;
	mem.listp = &inc_info_list;
	mem.conf = &conf;
	if(pthread_create(&tid_mem, NULL, send_inc_info, (void *)&mem)){
		snprintf(error_str, sizeof(error_str), "EMERG: pthread_create(): %s\n", strerror(errno));
		record_log(error_str);
	}

	/* create caculate flow thread*/
	flow.env.Malarm = Malarm;
	strncpy(flow.env.host_name, host_name, host_name_size);
	flow.env.host_name_size = host_name_size;
	flow.mem.semid = semid;
	flow.mem.shm_ptr = shm_ptr;
	flow.mem.listp = &inc_info_list;
	flow.mem.conf = &conf;
	if(pthread_create(&tid_flow, NULL, cacu_flow, (void *)&flow)){
		snprintf(error_str, sizeof(error_str), "EMERG: pthread_create(): %s\n", strerror(errno));
		record_log(error_str);
	}

	total_ping_time =  1000 / conf.monitor_interval;
	if(total_ping_time == 0)
		total_ping_time = 1;
	//elapsed_ping_time = 1;
	elapsed_ping_time = total_ping_time;

	while(1){
		i = 0;
		listp = inc_info_list.next;
		for(i = 0; listp != NULL; i++){
			get_inc_info(&listp->info);
			get_inc_stats(&listp->info);
			nic_status = get_netcard_status(listp);
			if(nic_status != listp->status){
				do_alarm(listp, nic_status, &Malarm);
				listp->status = nic_status;
			}
			listp = listp->next;
		}

		if(seqno > 32765)seqno = 0;
		nanosleep(&s_time, &os_time);


		//20100510
		++elapsed_ping_time;
		if(elapsed_ping_time > total_ping_time)
			elapsed_ping_time = 1;

		sys_time_stamp += conf.monitor_interval;
		if(sys_time_stamp >= 1000){
			sys_time_stamp = 0;
			write_time(semid, shm_ptr);
		}
	}
	for (i = 0; i < res.gl_pathc; i++) {
		pthread_join(tid[i], NULL);
	}
	pthread_join(tid_mem, NULL);
	pthread_join(tid_flow, NULL);
	pthread_join(tid_time, NULL);
	pthread_mutex_destroy(&mut);
	globfree(&res);
#ifdef USE_OLD_MMSHARE
	munmap(shm_ptr, sizeof(SHM));
#else
	{
	
	void *shmptr = shm_ptr;
#if 0
	snprintf(error_str, sizeof(error_str), "NOTICE: free shm %p, glo:%p\n", shmptr, global_shmptr);
	record_log(error_str);
#endif

	if( shmptr == global_shmptr ) {
		char *ref_count = NULL;
		int is_last = 0;
		int size = sizeof(SHM);

		ref_count = (char *)shmptr + size + 16 - 1;

		is_last = *ref_count == 1?1:0;
#if 0
	snprintf(error_str, sizeof(error_str), "NOTICE: sys_nic, size:%d, ref_count: %d, last:%d\n", 
					size, *ref_count, is_last);
	record_log(error_str);
#endif

//		if( is_last ) {
			memset( shmptr, 0, size + 16 );
//		}

		shmdt( shmptr );
//		shmctl( global_share_id, IPC_RMID, NULL );
//		if( is_last ) {
//			global_shmptr = NULL;
//			global_share_id = -1;
//		}
	}
	}	
#endif
	return 0;
}
