/*****************************************************/
/*Title:    sysctrl.c	                             */
/*Descr:    report operation system status           */
/*Author:   Liang Hanxi                              */
/*Create:   2002-06-24                               */
/*Modify:                                            */
/*****************************************************/

#include "./include/sysctrl.h"

#define MAX_MNT_FILESYS 32 //in CC client >16

//static mnt_list			MntInfo[MAX_MNT_FILESYS];
//static BYTE				MntNum=0;
static hb_sysinfo		SysInfo;
extern int				errno;

static BYTE get_idlecpu();
static int parse_infoline(char *str,char (*row)[64],int maxrow);

static int get_raminfo(hb_sysinfo *info);
static int get_ptinfo(hb_sysinfo *info);
static int change_hb_byte(hb_sysinfo *info, BYTE *output, BYTE *outlen);

static BYTE snmp_hb_byte[512];
static BYTE snmp_hb_len;

void sysctrl_init()
{
	memset(&SysInfo,0,sizeof(SysInfo));		
	
	SysInfo.up_time=time(NULL);
	SysInfo.idle_cpu_rate=get_idlecpu();
	get_raminfo(&SysInfo);
	get_ptinfo(&SysInfo);
	
	change_hb_byte(&SysInfo,snmp_hb_byte,&snmp_hb_len);
}

void system_report()
{
	static int			m_state=0;
	//struct sysinfo		info;
	//unsigned long		totaldisk,freedisk;
	
	switch(m_state)
	{		
	case 50*60*10:			//10min
		m_state=0;
		
		get_ptinfo(&SysInfo);
		change_hb_byte(&SysInfo,snmp_hb_byte,&snmp_hb_len);
		set_status(8,snmp_hb_len,(BYTE*)snmp_hb_byte);

		break;
	default:
		m_state++;
		if(m_state%(50*30)==0)	//30s
		{
			SysInfo.idle_cpu_rate=get_idlecpu();
			get_raminfo(&SysInfo);
			change_hb_byte(&SysInfo,snmp_hb_byte,&snmp_hb_len);
			set_status(8,snmp_hb_len,(BYTE*)snmp_hb_byte);
		}
		break;
	}
}

BYTE get_idlecpu()
{
	char			buf[128],row[5][64];
	unsigned long			timeofuser,timeofsys,timeofnice,timeofidle;
	static unsigned long	oldusertime=0,oldsystime=0,oldnicetime=0,oldidletime=0;
	
	unsigned long			idlecpu,totalcpu;
	unsigned short			idlerate;
	FILE *stat_fp=NULL;
	
	if((stat_fp=fopen("/proc/stat","r"))==NULL)
	{
		printf("Fail to open /proc/stat\n");
		exit(1);
	}
	
	if(stat_fp == NULL)
		return 0;

	if(fseek(stat_fp,0,SEEK_SET)!=0)
	{
		return 0;
	}
	if(fgets(buf,128,stat_fp)==NULL)
	{
		return 0;
	}

	if(parse_infoline(buf,row,5)<5)
		return 0;

	timeofuser=strtoul(row[1],NULL,10);
	timeofnice=strtoul(row[2],NULL,10);
	timeofsys=strtoul(row[3],NULL,10);
	timeofidle=strtoul(row[4],NULL,10);

	totalcpu=timeofuser - oldusertime + timeofnice - oldnicetime + timeofsys - oldsystime + timeofidle - oldidletime;
	if(totalcpu==0)
	{
		fclose(stat_fp);
		return 0;
	}

	idlecpu=timeofidle-oldidletime;
	idlerate=(unsigned short)(((double)idlecpu/totalcpu)*100);
	//store current time
	oldusertime=timeofuser;
	oldnicetime=timeofnice;
	oldsystime=timeofsys;
	oldidletime=timeofidle;

	if(idlerate > 100)
		idlerate=100;
	
	fclose(stat_fp);
		
	return (BYTE)idlerate;
}


int get_raminfo(hb_sysinfo *info)
{
	int rn;
	unsigned char rb,prb;
	int field_id=0;
	int field_id2=0;
	char field_value[256][256];
	FILE *mem_fp=NULL;

	if((mem_fp=fopen("/proc/meminfo","r"))==NULL)
	{
		printf("Fail to open /proc/meminfo\n");
		exit(1);
	}
	
	if(mem_fp == NULL)
		return 0;
		
	memset(field_value,0,sizeof(field_value));
	
	if(fseek(mem_fp,0,SEEK_SET)!=0)
	{
		fclose(mem_fp);
		return 0;
	}

	while((rn = fread(&rb,1,1,mem_fp)))
	{
		if(rb != 0x0A)
			field_value[field_id][field_id2]=rb;
		if(!(prb == 0x20 && rb == 0x20))
			field_id2++;
		if((prb != 0x20 && rb == 0x20) || (rb == 0x0A))
		{
			field_id2=0;
			field_id++;
		}
		prb=rb;
	}
	
	info->ram_total_used=atol(field_value[1])-atol(field_value[4]);
	info->ram_total=atol(field_value[1]);
	info->ram_swap_used=atol(field_value[34])-atol(field_value[37]);
	info->ram_swap_total=atol(field_value[34]);
	info->ram_buffers=atol(field_value[7]);
	info->ram_cached=atol(field_value[10]);

	fclose(mem_fp);
	
	return 1;
}

int get_ptinfo(hb_sysinfo *info)
{
	FILE *handle;
	char line[256];
	char path[256];
	char *pc;
	struct statfs fsbuf;

	handle=fopen("/etc/mtab","r");
	if(handle == NULL)
		return 0;
	
	info->pt_count=0;
	while(fgets(line,256,handle))
	{
		if(strncmp(line,"/dev",4) == 0)
		{
			strtok(line," ");
			pc=strtok(NULL," ");
			if(pc == NULL)
				continue;
			sprintf(path,"%s",pc);
			if(statfs(path,&fsbuf) == 0)
			{
				sprintf(info->pt[info->pt_count].mountpoint_path,"%s",path);
				info->pt[info->pt_count].used_space=(fsbuf.f_blocks - fsbuf.f_bfree) * (fsbuf.f_bsize / 1024);
				info->pt[info->pt_count].total_space=fsbuf.f_blocks * (fsbuf.f_bsize / 1024);
				//printf("%s\t%ld\t%ld\n",path,info->pt[info->pt_count].total_space,info->pt[info->pt_count].used_space);
				info->pt_count++;
				if(info->pt_count == MAX_PARTITION_NUM)
				{
					fclose(handle);
					return 1;
				}
			}
		}
	}

	fclose(handle);
	
	return 1;
}

int change_hb_byte(hb_sysinfo *info, BYTE *output, BYTE *outlen)
{
	DWORD *pd;
	BYTE *pb;
	BYTE *copy;
	int i;
	BYTE len;
	
	copy=output;
	pd=(DWORD*)copy;
	*pd=htonl(info->up_time);
	
	copy+=sizeof(DWORD);
	pb=(BYTE*)copy;
	*pb=(BYTE)(info->idle_cpu_rate);
	
	copy+=sizeof(BYTE);
	pd=(DWORD*)copy;
	*pd=htonl(info->ram_total_used);
	
	copy+=sizeof(DWORD);
	pd=(DWORD*)copy;
	*pd=htonl(info->ram_total);
	
	copy+=sizeof(DWORD);
	pd=(DWORD*)copy;
	*pd=htonl(info->ram_swap_used);
	
	copy+=sizeof(DWORD);
	pd=(DWORD*)copy;
	*pd=htonl(info->ram_swap_total);
	
	copy+=sizeof(DWORD);
	pd=(DWORD*)copy;
	*pd=htonl(info->ram_buffers);
	
	copy+=sizeof(DWORD);
	pd=(DWORD*)copy;
	*pd=htonl(info->ram_cached);
	
	copy+=sizeof(DWORD);
	pb=(BYTE*)copy;
	*pb=(BYTE)(info->pt_count);
	
	copy+=sizeof(BYTE);
	
	for(i=0;i<info->pt_count;i++)
	{
		len=strlen(info->pt[i].mountpoint_path);
		pb=(BYTE*)copy;
		*pb=(BYTE)len;
		
		copy+=sizeof(BYTE);
		memcpy(copy,info->pt[i].mountpoint_path,len);
		
		copy+=len;
		pd=(DWORD*)copy;
		*pd=htonl(info->pt[i].used_space);
		
		copy+=sizeof(DWORD);
		pd=(DWORD*)copy;
		*pd=htonl(info->pt[i].total_space);
		
		copy+=sizeof(DWORD);
	}
	
	*outlen=copy - output;
	
	return 1;
}

int parse_infoline(char *str,char (*row)[64],int maxrow)
{
	char		*pstr=str;
	int 		len,index=0,i;
	BOOL		black=0;
	len=strlen(str);
	for(i=0;i<len && index<maxrow;i++)
	{
		if(isspace(str[i]))
		{
			if(black==0)
				pstr=str+i+1;
			else
			{
				str[i]='\0';
				if(strlen(pstr)>64)
					pstr[63]=0;
				sprintf(row[index++],"%s",pstr);
				pstr=str+i+1;	
			}
			black=0;
		}
		else
			black=1;
	}
	if(black==1)
	{
		if(strlen(pstr)>64)
			pstr[63]=0;
		sprintf(row[index++],"%s",pstr);
	}
	return index;
}


