/*************************************************
File name:	sysStat.c
Author: 	
Version:	9:00:00 
Date:  		2007-09-04
Description:获取操作系统的基本信息，包括内存，硬盘信息等
			
			
			
												
History:               
No. 		
Author:		  
Date:		 
Version:	   
Description:
*************************************************/
#include "sysStat.h"

//cpu info file
#define SYSSTAT_FILE "/proc/stat"

//harddisk info file
#define ETC_MNTTAB "/etc/mtab"

//memory and swap info file
#define MEMINFO_FILE "/proc/meminfo"

#define BUFFSIZE 1024

/* by simon at 23/9/25 */
cpuTime oldCpuTime;

/*************************************************
Function:        // getCpuInfo
Description:     // 获取CPU信息参数
Calls:           // loadCpuTime
Called By:       // dualsrv module; beatSend module;
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // nowCpuInfo:Cpu信息
Return:          // 1:successful; 0:failed;
Others:          // "oldCpuTime" define in sysStat.h as global var
*************************************************/
int getCpuInfo(cpuInfo * nowCpuInfo)
{
	unsigned long unitUserTime;
	unsigned long unitNiceTime;
	unsigned long unitSystemTime;
	unsigned long unitIdleTime;
	double unitCpuLoad;
	cpuTime newCpuTime;
	loadCpuTime(&newCpuTime);

	//获取cpu的时间参数
	unitUserTime = newCpuTime.timeOfUser - oldCpuTime.timeOfUser;
	unitNiceTime = newCpuTime.timeOfNice - oldCpuTime.timeOfNice;
	unitSystemTime = newCpuTime.timeOfSystem - oldCpuTime.timeOfSystem;
	unitIdleTime = newCpuTime.timeOfIdle - oldCpuTime.timeOfIdle;

	//cpu负载
	unitCpuLoad =
		100 * (double) (unitUserTime + unitNiceTime + unitSystemTime)
		/ (double) (unitUserTime + unitNiceTime + unitSystemTime +
					unitIdleTime);
			
	nowCpuInfo->cpuLoad = ceil(unitCpuLoad);

	//printf("%lu  %lu %lu %lu \n ",newCpuTime.timeOfUser,newCpuTime.timeOfNice,newCpuTime.timeOfSystem,newCpuTime.timeOfIdle);
	//printf("%lu  %lu %lu %lu \n ",oldCpuTime.timeOfUser,oldCpuTime.timeOfNice,oldCpuTime.timeOfSystem,oldCpuTime.timeOfIdle);
	//printf("%lu  %lu %lu %lu %f\n ",unitUserTime,unitNiceTime,unitSystemTime,unitIdleTime,unitCpuLoad);
	//更换旧的时间参数		
	oldCpuTime = newCpuTime;
	//printf("%lu  %lu %lu %lu \n ",oldCpuTime.timeOfUser,oldCpuTime.timeOfNice,oldCpuTime.timeOfSystem,oldCpuTime.timeOfIdle);
	return (1);
}

/*************************************************
Function:        // loadCpuTime
Description:     // 获取cpu时间参数
Calls:           // 
Called By:       // getCpuInfo
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // nowCpuTime:cpu时间参数
Return:          // 1:successful; 0:failed;
Others:          // 
*************************************************/
int loadCpuTime(cpuTime * nowCpuTime)
{
	int statfd;
	char *b;
	char buff[BUFFSIZE];
	if ((statfd = open(SYSSTAT_FILE, O_RDONLY, 0)) != -1) {
		buff[BUFFSIZE - 1] = 0;
		read(statfd, buff, BUFFSIZE - 1);
		close(statfd);
		/*
		   *itot = 0;
		   *i1 = 1;
		 */
		b = buff;
		b = strstr(buff, "cpu ");
		sscanf(b, "cpu  %lu %lu %lu %lu", &(nowCpuTime->timeOfUser),
			   &(nowCpuTime->timeOfNice), &(nowCpuTime->timeOfSystem),
			   &(nowCpuTime->timeOfIdle));

		//printf("nowCpuTime->timeOfUser = %lu \n ",nowCpuTime->timeOfUser);
		/*
		   b = strstr(buff, "page ");
		   sscanf(b, "page %u %u", pin, pout);

		   b = strstr(buff, "swap ");
		   sscanf(b, "swap %u %u", swpin, swpout);

		   b = strstr(buff, "intr ");
		   sscanf(b, "intr %u %u", itot, i1);

		   b = strstr(buff, "ctxt ");
		   sscanf(b, "ctxt %u", ct);
		 */
		return (1);
	} else {
		perror("/proc/stat");
		return (0);
	}
}

/*************************************************
Function:        // getMemInfo
Description:     // 获取内存信息
Calls:           // 
Called By:       // dualsrv module; beatSend module;
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // nowMemInfo:内存信息;
Return:          // 1:successful; 0:failed;
Others:          // 
*************************************************/
int getMemInfo(memInfo * nowMemInfo)
{
	int statfd;
	unsigned long memFree;
	char *b;
	char buff[BUFFSIZE];
	char sizeStr[50];
	char kbStr[10];

	if ((statfd = open(MEMINFO_FILE, O_RDONLY, 0)) != -1) {
		buff[BUFFSIZE - 1] = 0;
		read(statfd, buff, BUFFSIZE - 1);
		close(statfd);
		b = buff;
		//总共的内存空间
		b = strstr(buff, "MemTotal: ");
		sscanf(b, "MemTotal:    %s %s", sizeStr, kbStr);
		nowMemInfo->total = atol(sizeStr);
		//printf("memTotal = %lu \n",nowMemInfo->total);
		//未使用的内存空间
		b = strstr(buff, "MemFree: ");
		sscanf(b, "MemFree:    %s %s", sizeStr, kbStr);
		memFree = atol(sizeStr);
		nowMemInfo->used = nowMemInfo->total - memFree;
		//printf("memUsed = %lu \n",nowMemInfo->used);
		return (1);
	} else {
		return (0);
	}
}

/*************************************************
Function:        // getSwapInfo
Description:     // 获取swap信息
Calls:           // 
Called By:       // dualsrv module; beatSend module;
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // nowSwapInfo:swap信息
Return:          // 1:successful; 0:failed;
Others:          // 
*************************************************/
int getSwapInfo(swapInfo * nowSwapInfo)
{
	int statfd;
	unsigned long swapFree;
	char *b;
	char buff[BUFFSIZE];
	char sizeStr[50];
	char kbStr[10];

	if ((statfd = open(MEMINFO_FILE, O_RDONLY, 0)) != -1) {
		buff[BUFFSIZE - 1] = 0;
		read(statfd, buff, BUFFSIZE - 1);
		close(statfd);
		b = buff;
		
		//总共的swap空间
		b = strstr(buff, "SwapTotal: ");
		sscanf(b, "SwapTotal:    %s %s", sizeStr, kbStr);
		nowSwapInfo->total = atol(sizeStr);
		//未使用的swap空间
		b = strstr(buff, "SwapFree: ");
		sscanf(b, "SwapFree:    %s %s", sizeStr, kbStr);
		swapFree = atol(sizeStr);
		nowSwapInfo->used = nowSwapInfo->total - swapFree;
		return (1);
	} else {
		return (0);
	}
}

/*************************************************
Function:        // getHdiskInfo
Description:     // 获取硬盘信息
Calls:           // getDiskTotal; loadHdaInfo;
Called By:       // dualsrv module; beatSend module;
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // nowHdiskInfo:硬盘信息
Return:          // 1:successful; 0:failed;
Others:          // 
*************************************************/
int getHdiskInfo(hdiskInfo * nowHdiskInfo)
{
	int i;
	loadHdaInfo(nowHdiskInfo);

	if (nowHdiskInfo->hdaNum < 1) {
		printf("Cannot get hdisk info!\n");
		return (0);
	}

	nowHdiskInfo->total = getDiskTotal();
	nowHdiskInfo->used = 0;
	for (i = 0; i < nowHdiskInfo->hdaNum; i++) {

		nowHdiskInfo->used += nowHdiskInfo->hdaArr[i].used;
	}
	return (1);
}

/*************************************************
Function:        // getDiskTotal
Description:     // 获取硬盘的总空间
Calls:           // 
Called By:       // getHdiskInfo
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // >0:硬盘的总空间; 0:failed;
Others:          // 
*************************************************/
unsigned long getDiskTotal(void)
{
	int fd;
	struct hd_driveid HRD_info;
	fd = open("/dev/hda", O_RDONLY);
	ioctl(fd, HDIO_GET_IDENTITY, &HRD_info);
	close(fd);
	return ((int) (HRD_info.lba_capacity / 2));
}

/*************************************************
Function:        // loadHdaInfo
Description:     // 获取硬盘的part number
Calls:           // 
Called By:       // getHdiskInfo
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // noweHdiskInfo:硬盘信息;
Return:          // >0:this disk's part number; 0:failed;
Others:          // 
*************************************************/
int loadHdaInfo(hdiskInfo * nowHdiskInfo)
{
	struct mntent *mntent;
	FILE *mntfp;
	int hdaCount = 0, i = 0;
	struct statvfs vfs;


	//step 1.Find every part's define
	mntfp = setmntent(ETC_MNTTAB, "r");
	while ((mntent = getmntent(mntfp))) {
		strcpy(nowHdiskInfo->hdaArr[hdaCount].name, mntent->mnt_fsname);
		strcpy(nowHdiskInfo->hdaArr[hdaCount].path, mntent->mnt_dir);
		hdaCount++;
	}
	endmntent(mntfp);
	free(mntent);
	nowHdiskInfo->hdaNum = hdaCount;

	//step 2.Find every part's information
	for (i = 0; i < hdaCount; i++) {
		if (statvfs(nowHdiskInfo->hdaArr[i].path, &vfs) == -1) {
			fprintf(stderr, "nowHdiskInfo->hdaArr[%d].path=%s \n", i,
					nowHdiskInfo->hdaArr[i].path);
			fprintf(stderr, "statvfs error\n");
			return (0);
		}
		nowHdiskInfo->hdaArr[i].total = vfs.f_blocks;
		if (vfs.f_frsize > 255) {
			nowHdiskInfo->hdaArr[i].total =
				nowHdiskInfo->hdaArr[i].total * (vfs.f_frsize / 1024);
		}


		nowHdiskInfo->hdaArr[i].used = vfs.f_blocks - vfs.f_bfree;
		if (vfs.f_frsize > 255) {
			nowHdiskInfo->hdaArr[i].used =
				nowHdiskInfo->hdaArr[i].used * (vfs.f_frsize / 1024);
		}
#if sysStat_DEBUG
		fprintf(stderr, "nowHdiskInfo->hdaArr[%d].total  = %lu \n", i,
				nowHdiskInfo->hdaArr[i].total);
		fprintf(stderr, "nowHdiskInfo->hdaArr[%d].used  = %lu \n", i,
				nowHdiskInfo->hdaArr[i].used);
#endif
	}							//end of for(..)
	return (1);
}

/*************************************************
Function:        // getProcGrpInfo
Description:     // 获得全部进程的信息
Calls:           // getProcInfo;
Called By:       // dualsrv module; beatSend module;
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // nowProcGrpInfo:进程组信息
Return:          // 1:successful; 0:failed;
Others:          // 
*************************************************/
int getProcGrpInfo(procGrpInfo * nowProcGrpInfo)
{
	int procNameCount, pidCount, i;
	char *pidList, *tmpProcName, *tmpPidStr;
	char getGrpPidComm[1024];
	char buff[BUFFSIZE];
	FILE *fp = NULL;
	int pidArr[MAX_PROC_NUM];
	int procNameListSize = sizeof(nowProcGrpInfo->procNameList);
	char procNameList[procNameListSize];
	char *tmpPnameList;

	procNameCount = 0;
	memcpy(procNameList, nowProcGrpInfo->procNameList, procNameListSize);
	tmpPnameList = procNameList;
	while (((tmpProcName = strsep(&tmpPnameList, " ")) != NULL)
		   && procNameCount < MAX_PROC_NUM) {
		sprintf(nowProcGrpInfo->procInfoArr[procNameCount].procName, "%s",
				tmpProcName);
		procNameCount++;
	}
	nowProcGrpInfo->procNum = procNameCount;

	//检测进程的状态
	sprintf(getGrpPidComm, "pidof -s %s", nowProcGrpInfo->procNameList);
	if ((fp = popen(getGrpPidComm, "r")) == NULL) {
		return (0);
	}
	if (fgets(buff, sizeof(buff), fp) == NULL) {
		pclose(fp);
		return (0);
	}
	pclose(fp);

	pidList = buff;
	pidCount = 0;
	while ((tmpPidStr = strsep(&pidList, " ")) != NULL) {
		pidArr[pidCount] = atoi(tmpPidStr);
		pidCount++;
	}

	if (nowProcGrpInfo->procNum == pidCount) {
		for (i = 0; i < nowProcGrpInfo->procNum; i++) {
			nowProcGrpInfo->procInfoArr[i].pid = pidArr[i];
			nowProcGrpInfo->procInfoArr[i].stat = 1;
		}
	} else {
		for (i = 0; i < nowProcGrpInfo->procNum; i++) {
			getProcInfo(&(nowProcGrpInfo->procInfoArr[i]));
		}
	}

	return (1);
}

/*************************************************
Function:        // getProcInfo
Description:     // 获得指定进程的信息
Calls:           // 
Called By:       // getProcGrpInfo
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // thisProcInfo:指定的进程;
Return:          // 1:successful; 0:failed;
Others:          // 
*************************************************/
int getProcInfo(procInfo * thisProcInfo)
{
	char procName[50];
	char getPidComm[100];
	FILE *fp = NULL;
	char buff[BUFFSIZE];
	int n, pid;
	char pidStr[10];
	sprintf(procName, "%s", thisProcInfo->procName);
#if sysStat_DEBUG
	fprintf(stderr, "procName = %s\n", procName);
#endif
	sprintf(getPidComm, "pidof -s %s", procName);
	if ((fp = popen(getPidComm, "r")) == NULL) {
		return (0);
	}
	if (fgets(buff, sizeof(buff), fp) == NULL) {
		pclose(fp);
		return (0);
	}
	pclose(fp);
	n = sscanf(buff, "%s", pidStr);
	if (n > 0) {
		pid = atol(pidStr);
		thisProcInfo->pid = pid;
		thisProcInfo->stat = 1;
#if sysStat_DEBUG
		fprintf(stderr, "%s(pid=%d) is running \n", procName, pid);
#endif
	} else {
		thisProcInfo->pid = 0;
		thisProcInfo->stat = 0;
#if sysStat_DEBUG
		fprintf(stderr, "%s is stopped \n", procName);
#endif
	}

	return (1);
}

/*************************************************
Function:        // getNetworkStat
Description:     // 获取网络状态
Calls:           // 
Called By:       // dualsrv module; beatSend module;
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // 1:successful; 0:failed;
Others:          // 
*************************************************/
int getNetworkStat(void)
{
	char sysCommStr[100];
	FILE *fp = NULL;
	char buff[BUFFSIZE];
	int n, packetNum;
	char inputStr[10];
	
	sprintf(sysCommStr, "ping -b -c 2 172.18.255.255|grep -c 172.18");
	if ((fp = popen(sysCommStr, "r")) == NULL) {
		return (0);
	}
	if (fgets(buff, sizeof(buff), fp) == NULL) {
		pclose(fp);
		return (0);
	}
	pclose(fp);
	n = sscanf(buff, "%s", inputStr);
	if (n > 0) {
		packetNum = atol(inputStr);
		if (packetNum > 4) {
#if sysStat_DEBUG
			fprintf(stderr, "Network is ok \n");
#endif
			return (1);
		}
	}
#if sysStat_DEBUG
	fprintf(stderr, "Network is stopped \n");
#endif
	return (0);
}


