#include <sys/types.h>
#include <sys/param.h>
#include <stddef.h>
#include <sys/sysctl.h>
#include <sys/resource.h>
#include <stdlib.h>
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/utsname.h>
#include <stdbool.h>
#include <sys/socket.h>


#ifndef HOST_NAME_MAX
	#define HOST_NAME_MAX 255
#endif


#define GETSYSCTL(name, var) getsysctl(name, &(var), sizeof(var))


struct network_info {

	struct timespec check_time;

	u_long inbound_packets;
	u_long outbound_packets;

	u_long inbound_bytes;
	u_long outbound_bytes;

};

struct fhs_info {

	char   hostname[HOST_NAME_MAX + 1];
	double load_avg[3];
	float  cpu_stat[CPUSTATES];
	int    memory_total;         // MByte
	int    memory_stat[6];       // MByte 
	int    swap_stat[6];         // Size MByte, in/out : KByte


	struct network_info network_old;
	struct network_info network_now;

};


static void getsysctl(const char *name, void *ptr, size_t len)
{
	size_t nlen = len;

	if (sysctlbyname(name, ptr, &nlen, NULL, 0) == -1)
	{
		fprintf(stderr, "sysctl(%s...) failed: %s\n", name, strerror(errno));
		//quit(23);
	}
	if (nlen != len)
	{
		fprintf(stderr, "sysctl(%s...) expected %lu byte, got %lu byte\n", name, (unsigned long)len, (unsigned long)nlen);
		//quit(23);
	}

	return;
}


long percentages(int cnt, int * out, register long * new, register long * old, long * diffs)
{

	register int i;
	register long change;
	register long total_change;
	register long *dp;
	long half_total;

	/* initialization */
	total_change = 0;
	dp = diffs;

	/* calculate changes for each state and the overall change */
	for (i = 0; i < cnt; i++)
	{
		if ((change = *new - *old) < 0)
		{
			/* this only happens when the counter wraps */
			change = (int)
				((unsigned long)*new-(unsigned long)*old);
		}
		total_change += (*dp++ = change);
		*old++ = *new++;
	}

	/* avoid divide by zero potential */
	if (total_change == 0)
	{
		total_change = 1;
	}

	/* calculate percentages based on overall change, rounding up */
	half_total = total_change / 2l;

	/* Do not divide by 0. Causes Floating point exception */
	if(total_change) {
		for (i = 0; i < cnt; i++)
		{
			*out++ = (int)((*diffs++ * 1000 + half_total) / total_change);
		}
	}

	/* return the total in case the caller wants to use it */
	return(total_change);
}



bool get_loadavg( struct fhs_info * fhs)
{

	int i = 0;
	struct loadavg sysload;

	GETSYSCTL("vm.loadavg", sysload);
	//getsysctl("vm.loadavg", &sysload, sizeof(sysload));

	for (i = 0; i < 3; i++)
	{
		fhs->load_avg[i] = (double)sysload.ldavg[i] / sysload.fscale;
	}
	
	return true;
}


	

static long cp_time[CPUSTATES];
static long cp_old[CPUSTATES];
static long cp_diff[CPUSTATES];

bool get_cpuusage( struct fhs_info * fhs )
{
	int i;
	int cpu_stat[CPUSTATES];

	GETSYSCTL("kern.cp_time", cp_time);
	percentages(CPUSTATES, cpu_stat, cp_time, cp_old, cp_diff);

	for( i = 0; i < CPUSTATES; i++)
	{
		if( cpu_stat[i] >= 1000)
			fhs->cpu_stat[i] = 100.0;
		else
			fhs->cpu_stat[i] = ((float)cpu_stat[i])/10.0;
	}

	return true;
}




static int pageshift;		/* log base 2 of the pagesize */
#define pagetok(size) ((size) << pageshift)

bool get_memory( struct fhs_info * fhs )
{

	long memory_total;
	int memory_stat[6];
	long bufspace = 0;

	GETSYSCTL("hw.physmem", memory_total);
	GETSYSCTL("vfs.bufspace", bufspace);
	GETSYSCTL("vm.stats.vm.v_active_count",   memory_stat[0]);
	GETSYSCTL("vm.stats.vm.v_inactive_count", memory_stat[1]);
	GETSYSCTL("vm.stats.vm.v_wire_count",     memory_stat[2]);
	GETSYSCTL("vm.stats.vm.v_cache_count",    memory_stat[3]);
	GETSYSCTL("vm.stats.vm.v_free_count",     memory_stat[5]);

	// byte -> Mbyte
	fhs->memory_total = memory_total /1024/1024;

	/* convert memory stats to Kbytes -> Mbytes: +512/1024 -> round() */
	fhs->memory_stat[0] = ( pagetok(memory_stat[0]) + 512 ) /1024;
	fhs->memory_stat[1] = ( pagetok(memory_stat[1]) + 512 ) /1024;
	fhs->memory_stat[2] = ( pagetok(memory_stat[2]) + 512 ) /1024;
	fhs->memory_stat[3] = ( pagetok(memory_stat[3]) + 512 ) /1024;
	fhs->memory_stat[4] = (( bufspace / 1024)       + 512 ) /1024;
	fhs->memory_stat[5] = ( pagetok(memory_stat[5]) + 512 ) /1024;
	

	return true;;
}


#include <fcntl.h>
#include <kvm.h>
static kvm_t *kd;

static int swapmode(int *retavail, int *retfree)
{
	int n;
	int pagesize = getpagesize();
	struct kvm_swap swapary[1];

	*retavail = 0;
	*retfree = 0;

#define CONVERT(v)	((quad_t)(v) * pagesize / 1024)

	n = kvm_getswapinfo(kd, swapary, 1, 0);
	if (n < 0 || swapary[0].ksw_total == 0)
		return (0);

	*retavail = CONVERT(swapary[0].ksw_total);
	*retfree = CONVERT(swapary[0].ksw_total - swapary[0].ksw_used);

	n = (int)(swapary[0].ksw_used * 100.0 / swapary[0].ksw_total);
	return (n);
}



static int swappgsin = -1;
static int swappgsout = -1;
static unsigned int swap_delay = 0;
static int swapavail = 0;
static int swapfree = 0;

bool get_swap(struct fhs_info * fhs)
{
	int nspgsin, nspgsout;
	GETSYSCTL("vm.stats.vm.v_swappgsin",      nspgsin);
	GETSYSCTL("vm.stats.vm.v_swappgsout",     nspgsout);

	// first interval 
	if (swappgsin < 0) 
	{
		fhs->swap_stat[4] = 0;
		fhs->swap_stat[5] = 0;
	}

	// compute differences between old and new swap statistic 
	else 
	{
		fhs->swap_stat[4] = pagetok(((nspgsin - swappgsin)));
		fhs->swap_stat[5] = pagetok(((nspgsout - swappgsout)));
	}

	swappgsin = nspgsin;
	swappgsout = nspgsout;

	// call CPU heavy swapmode() only for changes 
	if (fhs->swap_stat[4] > 0 || fhs->swap_stat[5] > 0 || swap_delay == 0) 
	{
		fhs->swap_stat[3] = swapmode(&swapavail, &swapfree);
		fhs->swap_stat[0] = ( swapavail + 512 ) / 1024;
		fhs->swap_stat[1] = ( swapavail - swapfree + 512) / 1024;
		fhs->swap_stat[2] = ( swapfree + 512 ) / 1024;
	}
	else
	{
		fhs->swap_stat[0] = ( swapavail + 512 ) / 1024;
		fhs->swap_stat[1] = ( swapavail - swapfree + 512 ) / 1024;
		fhs->swap_stat[2] = ( swapfree + 512 ) / 1024;
	}
	
	swap_delay = 1;

	return true;
}


bool get_hostname( struct fhs_info * fi )
{
	if( gethostname( fi->hostname, HOST_NAME_MAX ) == 0 )
		return true;
	else
	{
		printf("hostname get failed. [%d][%s]", errno, strerror(errno));
		return false;
	}
}



#include <net/if.h>
#include <net/if_mib.h>
#include <time.h>

int if_count[] = { CTL_NET, PF_LINK, NETLINK_GENERIC, IFMIB_SYSTEM, IFMIB_IFCOUNT };
int if_info[]  = { CTL_NET, PF_LINK, NETLINK_GENERIC, IFMIB_IFDATA,            0, IFDATA_GENERAL };

bool get_network( struct fhs_info * fhs )
{

	// 기존 추출된 정보를 old 로 이동 처리후 0 reset
	memcpy( &(fhs->network_old), &(fhs->network_now), sizeof( struct network_info));
	memset( &(fhs->network_now), 0x00, sizeof(struct network_info));

	u_int count = 0;
	size_t data_len = sizeof(count);

	if( sysctl( if_count, 5, (void *)&count, (size_t *)&data_len, (void *)NULL, (size_t)0 ) != 0 )
	{
		printf("Network interface count get failed. [%d][%s]", errno, strerror(errno));
		return false;
	}

	// interface 가  없는 경우
	if( count <= 0 )
		return true;


	int i;
	struct ifmibdata data;
	data_len = sizeof( struct ifmibdata );

	struct network_info total;
	memset( &total, 0x00, sizeof(struct network_info));

	for( i = 1; i <= count ; i++ )
	{
		if_info[4] = i;

		if( (sysctl( if_info, 6, (void *)&data, (size_t *)&data_len, (void *)NULL, (size_t)0 ) != 0) && (errno != ENOENT) )
		{
			printf("Network interface sysctl error getting interface data. [%d][%s]", errno, strerror(errno));
			return false;
		}

		// local loopback interface (lo) 제외 
		// - 장비의 트래픽 정보를 수집하는 것이므로.. lo 꺼는 빼는 것이 맞다.
		if( strncmp( data.ifmd_name, "lo", 2) == 0 )
			continue;

		// link aggregation 처리되 lagg 쨒nterface 제외
		// - link ggreagtion 처리된 개별 interface 통계가 lagg 에 sum 되어 나타나므로... 통계 중복 발생.
		// - 이를 해결하기 위해 lagg interface 는 수집 제외
		if( strncmp( data.ifmd_name, "lagg", 4) == 0 )
			continue;

		//printf("Network interface name : %s\n", data.ifmd_name );

		total.inbound_packets  += data.ifmd_data.ifi_ipackets;
		total.outbound_packets += data.ifmd_data.ifi_opackets;
		total.inbound_bytes    += data.ifmd_data.ifi_ibytes;
		total.outbound_bytes   += data.ifmd_data.ifi_obytes;
	}

	// 시간 정보 추출
	clock_gettime( CLOCK_MONOTONIC, &(total.check_time));
	memcpy( &(fhs->network_now), &total, sizeof( struct network_info));

	return true;
}




#include <sys/mount.h>
#include <stdint.h>
void print_mountinfo()
{
	int mntsize;
	struct statfs *mntbuf;
	long blocksize;
	int i;

	getbsize( &mntsize, &blocksize);
	//printf("\nblocksize = %ld\n", blocksize);

	mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);

	printf("\nMount: /stg\n");
	printf("    Filesystem   Type       Size(M)     Used(M)    Avail(M)  Capacity  Mounted on\n");
	
	for( i = 0; i < mntsize; i++ )
	{

		if( strncmp( "/stg", mntbuf[i].f_mntonname, 4) == 0 )
		{
			int64_t used = mntbuf[i].f_blocks - mntbuf[i].f_bfree;
			int64_t availblks = mntbuf[i].f_bavail + used;

			printf("    %-12s", mntbuf[i].f_mntfromname );
			printf(" %-7s"    , mntbuf[i].f_fstypename );
			printf(" %10jd"   , mntbuf[i].f_blocks * mntbuf[i].f_bsize / 1024 / 1024 );
			printf(" %11jd"   , (( used * mntbuf[i].f_bsize + 1023) / 1024 + 1023 ) / 1024 );
			printf(" %11jd"   , mntbuf[i].f_bavail * mntbuf[i].f_bsize / 1024 / 1024 );
			printf(" %8.0f%%" , availblks == 0 ? 100.0 : (double)used / (double)availblks * 100.0);
			printf("  %s"     , mntbuf[i].f_mntonname);

			printf("\n");
		}


	}

	return;
}


#include <libgeom.h>
#include <devstat.h>

struct gmesh gmp;
void *sp, *sq;
double dt;
struct timespec tp, tq;
struct devstat *gsp, *gsq;

void print_diskstat()
{
	int i;
	uint64_t queuelength;
	long double busy;

	struct gident *gid;
	struct gprovider *pp;
	struct gconsumer *cp;

	sp = geom_stats_snapshot_get();
	if (sp == NULL)
		err(1, "geom_stats_snapshot()");

	geom_stats_snapshot_timestamp(sp, &tp);
	dt = tp.tv_sec - tq.tv_sec;
	dt += (tp.tv_nsec - tq.tv_nsec) * 1e-9;
	tq = tp;

	geom_stats_snapshot_reset(sp);
	geom_stats_snapshot_reset(sq);

	printf("Disk stat:\n");
	printf("    Queue_length  Busy(%%)  Name\n");
	for(;;)
	{
		gsp = geom_stats_snapshot_next(sp);
		gsq = geom_stats_snapshot_next(sq);

		if (gsp == NULL || gsq == NULL)
			break;
		if (gsp->id == NULL)
			continue;

		gid = geom_lookupid(&gmp, gsp->id);
		if (gid == NULL) 
		{
			geom_deletetree(&gmp);
			i = geom_gettree(&gmp);
			if (i != 0)
				err(1,  "geom_gettree = %d", i);
		
			gid = geom_lookupid(&gmp, gsp->id);
		}

		if (gid == NULL ||  gid->lg_what == ISCONSUMER )
			continue;

		if ( gid->lg_what == ISPROVIDER && ((struct gprovider *)(gid->lg_ptr))->lg_geom->lg_rank != 1)
			continue;

		if (gsp->sequence0 != gsp->sequence1) {
			printf("*\n");
			continue;
		}

		devstat_compute_statistics(gsp, gsq, dt, 
				DSM_QUEUE_LENGTH, &queuelength,
				DSM_BUSY_PCT, &busy,
				DSM_NONE);

		printf("    ");
		printf("%12ju", (uintmax_t)queuelength );
		printf(" %6.1lf    ", (double)busy );

		if (gid == NULL) 
		{
			printf("??");
		} 
		else if (gid->lg_what == ISPROVIDER) 
		{
			pp = gid->lg_ptr;
			printf("%s", pp->lg_name);
		} 
		else if (gid->lg_what == ISCONSUMER) 
		{
			cp = gid->lg_ptr;
			printf("[CONSUMER] %s/%s/%s",
					cp->lg_geom->lg_class->lg_name,
					cp->lg_geom->lg_name,
					cp->lg_provider->lg_name);
		}



		printf("\n");
		*gsq = *gsp;
	}

	geom_stats_snapshot_free(sp);

	return;
}

#include <sys/socket.h>
#include <sys/socketvar.h>

#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/in_pcb.h>
#include <netinet/tcp_var.h>
#include <arpa/inet.h>
#define	TCPSTATES
#include <netinet/tcp_fsm.h>


#define	C(x)	((u_int)((x) & 0xff))

void print_session()
{
	int total = 0 ;
	int total_80 = 0;
	int total_80_establish = 0;

	const char * mibvar = "net.inet.tcp.pcblist";
	size_t len = 0;
	char * buf = NULL;
	
	printf("TCP Session stat:\n");

	if( sysctlbyname( mibvar, 0, &len, 0, 0 ) < 0 )
	{
		if(errno != ENOENT)
			fprintf(stderr, "    - sysctlbyname(%s...) get length failed: %s\n", mibvar, strerror(errno));
		else
			fprintf(stderr, "    - sysctlbyname(%s...) not found. OS version check[%s]\n", mibvar, strerror(errno));
		
		return;
	}

	buf = malloc(len);
	if( buf == NULL )
	{
		fprintf(stderr, "    - malloc error :%lu byte [%s]\n", (u_long)len, strerror(errno));
		return;
	}

	if( sysctlbyname( mibvar, buf, &len, 0, 0 ) < 0 )
	{
		fprintf(stderr, "    - sysctlbyname(%s...) get data failed: %s\n", mibvar, strerror(errno));
		free(buf);
		return;
	}


	/* 
	struct xinpgen *xig, *oxig;
	struct xsocket *so;
	struct xtcp_timer *timer;
	struct tcpcb *tp = NULL;
	struct inpcb *inp;

	const char * vchar;
	char line[80];
	int port;

	oxig = xig = (struct xinpgen *)buf;

	printf("    %-5.5s %-6.6s %-6.6s %-22.22s %-22.22s (state)\n", "Proto", "Recv-Q", "Send-Q", "Local Address", "Foreign Address");
	for (xig = (struct xinpgen *)((char *)xig + xig->xig_len)
			; xig->xig_len > sizeof(struct xinpgen)
			; xig = (struct xinpgen *)((char *)xig + xig->xig_len)) 
	{
		
		timer = &((struct xtcpcb *)xig)->xt_timer;
		tp    = &((struct xtcpcb *)xig)->xt_tp;
		inp   = &((struct xtcpcb *)xig)->xt_inp;
		so    = &((struct xtcpcb *)xig)->xt_socket;

		// Ignore sockets for protocols other than the desired one. 
		if (so->xso_protocol != IPPROTO_TCP)
			continue;

		// Ignore PCBs which were freed during copyout. 
		if (inp->inp_gencnt > oxig->xig_gen)
			continue;

		if ((inp->inp_vflag & INP_IPV4) == 0)
			continue;

		vchar = ((inp->inp_vflag & INP_IPV4) != 0) ?    "4 " : "  ";
		if ((tp->t_flags & TF_TOE) != 0)
			printf("    %-3.3s%-2.2s ", "toe", vchar);
		else
			printf("    %-3.3s%-2.2s ", "tcp", vchar);


		printf("%6u %6u ", so->so_rcv.sb_cc, so->so_snd.sb_cc);

		if (inp->inp_vflag & INP_IPV4) 
		{
			//inetprint(&inp->inp_laddr, (int)inp->inp_lport, "tcp", 1);

			inp->inp_laddr.s_addr = ntohl(inp->inp_laddr.s_addr);
			port = ntohs((u_short)inp->inp_lport);

			if( inp->inp_laddr.s_addr == INADDR_ANY)
			{
				sprintf( line, "*");
			}
			else
			{
				sprintf( line, "%u.%u.%u.%u"
						, C(inp->inp_laddr.s_addr >> 24)
						, C(inp->inp_laddr.s_addr >> 16)
						, C(inp->inp_laddr.s_addr >> 8)
						, C(inp->inp_laddr.s_addr));
			}

			if(port == 0 ) 
			{
				strcat( line, ".* ");
			}
			else
			{
	
				char temp[80];
				sprintf( temp, ".%d ", port);
				strcat( line, temp);
				
				if( port == 80 )
				{
					total_80++;

					if( tp && tp->t_state == 4 )
						total_80_establish++;

				}
			}
				
			printf("%-22.22s ", line);

			
			//inetprint(&inp->inp_faddr, (int)inp->inp_fport, name, 1);
			inp->inp_faddr.s_addr = ntohl(inp->inp_faddr.s_addr);
			port = ntohs((u_short)inp->inp_fport);
	

			if( inp->inp_faddr.s_addr == INADDR_ANY)
			{
				sprintf( line, "*");
			}
			else
			{
				sprintf(line, "%u.%u.%u.%u"
						, C(inp->inp_faddr.s_addr >> 24)
						, C(inp->inp_faddr.s_addr >> 16)
						, C(inp->inp_faddr.s_addr >> 8)
						, C(inp->inp_faddr.s_addr));
			}

			if(port  == 0 ) 
			{
				strcat( line, ".* ");
			}
			else
			{
				char temp[80];
				sprintf( temp, ".%d ", port);
				strcat( line, temp);
			}

			printf("%-22.22s ", line);

		}

		//printf("        %d", tp->t_state);
		if (tp->t_state < 0 || tp->t_state >= TCP_NSTATES)
			printf("%d", tp->t_state);
		else 
			printf("%s", tcpstates[tp->t_state]);


		printf("\n");
		
		total++;
	}
	*/

	struct xinpgen *xig, *oxig;
	struct xsocket *so;
	struct inpcb *inp;
	struct tcpcb *tp = NULL;
	int port;


	oxig = xig = (struct xinpgen *)buf;

	for (xig = (struct xinpgen *)((char *)xig + xig->xig_len)
			; xig->xig_len > sizeof(struct xinpgen)
			; xig = (struct xinpgen *)((char *)xig + xig->xig_len)) 
	{

		so    = &((struct xtcpcb *)xig)->xt_socket;
		inp   = &((struct xtcpcb *)xig)->xt_inp;		
		tp    = &((struct xtcpcb *)xig)->xt_tp;


		// Ignore sockets for protocols other than the desired one. 
		if( so->xso_protocol != IPPROTO_TCP )
			continue;

		// Ignore PCBs which were freed during copyout. 
		if( inp->inp_gencnt > oxig->xig_gen )
			continue;

		// IP v4, v6 가 아닌 경우 제외
		if( (inp->inp_vflag & INP_IPV4) == 0 && (inp->inp_vflag & INP_IPV6) == 0 )
			continue;


		total++;

		// Local port 정보 주출.
		port = ntohs((u_short)inp->inp_lport);
		if( port == 80 )
		{
			total_80++;

			if( tp && tp->t_state == 4 )
				total_80_establish++;
		}


	}

	free(buf);

	printf("    TCP session                  : %5d\n", total );
	printf("    TCP 80 port session          : %5d\n", total_80 );
	printf("    TCP 80 port establish session: %5d\n", total_80_establish );

	return;

}




void print_fhsinfo( struct fhs_info * fhs )
{
	// Hostname
	printf("\nHostname            : %s", fhs->hostname );	
	
	
	// Load average
	/*
	printf("\nLoad averages");
	for (i = 0; i < 3; i++)
	{
		printf("%c %5.2f", i == 0 ? ':' : ',', fhs->load_avg[i] );
	}
	*/
	// 5분 정보만 사용
	printf("\nLoad average (5min) : %5.2f", fhs->load_avg[1]);
	


	// CPU
	// - 변동률이 커서 사용하지 않는다.
	/*
	char *cpustatenames[CPUSTATES] = { "user,", "nice,", "system,", "interrupt,", "idle" };
	printf("\nCPU: ");	
	for( i=0; i < CPUSTATES; i++)
	{
		printf( "%4.1f%% %s", fhs->cpu_stat[i], cpustatenames[i]);
	}
	*/


	// Memory
	// - 사용률 정보만 사용 ( total - free )/total * 100 
	/*
	char *memorynames[] = { "M Active, ", "M Inact, ", "M Wired, ", "M Cache, ", "M Buf, ", "M Free" };
	printf("\nMem: ");
	for( i=0; i < 6; i++ )
	{
		printf("%d%s",  fhs->memory_stat[i], memorynames[i]);
	}
	*/

	printf("\nMemory usage (%%)    : %3.0f%%\n    - total: %8dM\n    - free : %8dM"
			, (fhs->memory_total - fhs->memory_stat[5]) * 100.0 / fhs->memory_total
			, fhs->memory_total
			, fhs->memory_stat[5]
			);


	// Swap
	// - 사용률 정보만 사용
	/*
	char *swapnames[] = { "M Total, ", "M Used, ", "M Free, ", "% Inuse, ", "K In, ", "K Out" };
	printf("\nSwap: ");
	for( i=0; i < 6; i++ )
	{
		printf("%d%s",  fhs->swap_stat[i], swapnames[i]);
	}
	*/
	printf("\nSwap usage (%%)      : %d%%\n    - total: %8dM\n    - used : %8dM"
			, fhs->swap_stat[3]
			, fhs->swap_stat[0]
			, fhs->swap_stat[1] );




	// Mount info
	print_mountinfo();

	// Disk stat
	print_diskstat();


	// Network info
	printf("Network stat:\n");
	
	if( fhs->network_now.check_time.tv_sec == 0 &&  fhs->network_now.check_time.tv_nsec == 0 )
	{
		printf("    - not vaild");
	}
	else
	{
		double	elapsed = 0.0;

		elapsed =  (fhs->network_now.check_time.tv_sec -  fhs->network_old.check_time.tv_sec)
			       + ((fhs->network_now.check_time.tv_nsec -  fhs->network_old.check_time.tv_nsec) * 1e-9);

		printf("    check period    : %12.1f sec\n", elapsed );
		printf("    inbound packets : %12lu\n", fhs->network_now.inbound_packets - fhs->network_old.inbound_packets );
		printf("    outbound packets: %12lu\n", fhs->network_now.outbound_packets - fhs->network_old.outbound_packets );
		printf("    inbound traffic : %12.0f Byte/sec\n", (fhs->network_now.inbound_bytes - fhs->network_old.inbound_bytes) / elapsed );
		printf("    outbound traffic: %12.0f Byte/sec\n", (fhs->network_now.outbound_bytes - fhs->network_old.outbound_bytes) / elapsed );

	}
	
	// Session info
	print_session();


	//printf("\n");
	return;
}



/* Log base 2 of 1024 is 10 (2^10 == 1024) */
#define LOG1024		10

int main ()
{
	struct fhs_info fhs;


	// For Memory
	int pagesize = getpagesize();
	pageshift = 0;
	while (pagesize > 1) 
	{
		pageshift++;
		pagesize >>= 1;
	}
	/* we only need the amount of log(2)1024 for our conversion */
	pageshift -= LOG1024;

	
	// For Swap
	kd = kvm_open(NULL, "/dev/null", NULL, O_RDONLY, "kvm_open");
	if (kd == NULL)
		return (-1);


	// Disk stat
	int i;
	int error;
	
	i = geom_gettree(&gmp);
	if (i != 0)
		err(1, "geom_gettree = %d", i);

	error = geom_stats_open();
	if (error)
		err(1, "geom_stats_open()");

	sq = NULL;
	sq = geom_stats_snapshot_get();
	if (sq == NULL)
		err(1 , "geom_stats_snapshot()");
	
	geom_stats_snapshot_timestamp(sq, &tq);


	// Print system info
	while(1)
	//for( int count = 0 ; count < 1000; count++ )
	{
		get_loadavg ( &fhs );
		get_cpuusage( &fhs );
		get_memory  ( &fhs );
		get_swap    ( &fhs );
		get_hostname( &fhs );
		get_network ( &fhs );

		print_fhsinfo( &fhs );

		//printf("\n%-*s %s", 20, "FileSystem", "aaa");

		sleep(1);
	}

	kvm_close( kd );


	return 0;
}




