262 lines
6.7 KiB
C
262 lines
6.7 KiB
C
/*
|
||
* UNO Monitor Daemon
|
||
* Kidacro <kidacro@archamedis.net>
|
||
*
|
||
* gather_stats.c - retrieves stats from system
|
||
*
|
||
*/
|
||
|
||
#include <stdio.h>
|
||
#include <string.h>
|
||
#include <stdlib.h>
|
||
#include <ctype.h>
|
||
#include <sys/sysinfo.h>
|
||
#include <sys/vfs.h>
|
||
|
||
#define MAX_ENTRIES 10
|
||
|
||
// from monitor_daemon.c
|
||
void send_stats();
|
||
|
||
// local function prototypes
|
||
void get_stats();
|
||
char *trim(char *str);
|
||
static void get_cpu_load();
|
||
static void get_cpu_temp();
|
||
static void get_free_mem();
|
||
static void get_free_space();
|
||
|
||
// external vars (monitor_daemon.c)
|
||
extern const char *cpu_temp_file;
|
||
extern const char *cpu_fanspeed_file;
|
||
extern char *drive_free_space[MAX_ENTRIES];
|
||
extern int drive_free_space_count;
|
||
extern FILE *log_stream;
|
||
extern int debug;
|
||
extern int line_length;
|
||
extern int line_count;
|
||
|
||
// stats vars
|
||
// TODO: make the character sizes dynamic based on line_length
|
||
// src/gather_stats.c:43:6: error: variably modified ‘freespace’ at file scope <-- damn C
|
||
// so we have to make a concession and either #define a max or.... no clue... go back to PHP?
|
||
char cpuload[4]; // line 1
|
||
char cputemp[6]; // line 1
|
||
char freemem[6]; // line 1
|
||
char freespace[16]; // line 2
|
||
|
||
// sysinfo vars
|
||
int sysinfo(struct sysinfo *info);
|
||
|
||
// proto:
|
||
// struct sysinfo {
|
||
// long uptime; /* Seconds since boot */
|
||
// unsigned long loads[3]; /* 1, 5, and 15 minute load averages */
|
||
// unsigned long totalram; /* Total usable main memory size */
|
||
// unsigned long freeram; /* Available memory size */
|
||
// unsigned long sharedram; /* Amount of shared memory */
|
||
// unsigned long bufferram; /* Memory used by buffers */
|
||
// unsigned long totalswap; /* Total swap space size */
|
||
// unsigned long freeswap; /* swap space still available */
|
||
// unsigned short procs; /* Number of current processes */
|
||
// unsigned long totalhigh; /* Total high memory size */
|
||
// unsigned long freehigh; /* Available high memory size */
|
||
// unsigned int mem_unit; /* Memory unit size in bytes */
|
||
// char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding to 64 bytes */
|
||
//};
|
||
|
||
// trims end of strings
|
||
char *trim(char *str)
|
||
{
|
||
size_t len = 0;
|
||
char *frontp = str;
|
||
char *endp = NULL;
|
||
|
||
if( str == NULL ) { return NULL; }
|
||
if( str[0] == '\0' ) { return str; }
|
||
|
||
len = strlen(str);
|
||
endp = str + len;
|
||
|
||
/* Move the front and back pointers to address the first non-whitespace
|
||
* characters from each end.
|
||
*/
|
||
while(isspace((unsigned char) *frontp)) { ++frontp; }
|
||
if(endp != frontp) {
|
||
while(isspace((unsigned char) *(--endp)) && endp != frontp) {}
|
||
}
|
||
|
||
if(frontp != str && endp == frontp) {
|
||
*str = '\0';
|
||
}
|
||
else if(str + len - 1 != endp) {
|
||
*(endp + 1) = '\0';
|
||
}
|
||
|
||
/* Shift the string so that it starts at str so that if it's dynamically
|
||
* allocated, we can still free it on the returned pointer. Note the reuse
|
||
* of endp to mean the front of the string buffer now.
|
||
*/
|
||
endp = str;
|
||
if(frontp != str) {
|
||
while(*frontp) { *endp++ = *frontp++; }
|
||
*endp = '\0';
|
||
}
|
||
|
||
return str;
|
||
}
|
||
|
||
// get stats (retreive, combine, and send stats)
|
||
// TODO: force trunication for each line to line_length
|
||
// no reason to hardcode '24' below when we know the exact line_length
|
||
void get_stats()
|
||
{
|
||
char line_1[24], line_2[24], line_3[24];
|
||
|
||
get_cpu_load();
|
||
get_cpu_temp();
|
||
get_free_mem();
|
||
get_free_space();
|
||
|
||
snprintf(line_1,sizeof(line_1),"#1%s%% %sC %sM@",cpuload,cputemp,freemem);
|
||
snprintf(line_2,sizeof(line_2),"#2%s@",trim(freespace));
|
||
snprintf(line_3,sizeof(line_3),"#3%s@",cpuload);
|
||
|
||
send_stats(line_1,line_2,line_3);
|
||
|
||
return;
|
||
}
|
||
|
||
static void get_cpu_load()
|
||
{
|
||
//static unsigned int lastTotalUser, lastTotalUserLow, lastTotalSys, lastTotalIdle;
|
||
static unsigned long long lastTotalUser, lastTotalUserLow, lastTotalSys, lastTotalIdle;
|
||
float percent;
|
||
static float lastPercent;
|
||
int intPercent, read_result = 0;
|
||
FILE* file;
|
||
unsigned long long totalUser, totalUserLow, totalSys, totalIdle, total;
|
||
|
||
file = fopen("/proc/stat", "r");
|
||
read_result = fscanf(file, "cpu %llu %llu %llu %llu", &totalUser, &totalUserLow, &totalSys, &totalIdle);
|
||
fclose(file);
|
||
|
||
// if result cannot be read, set to 0
|
||
if(read_result < 0) {
|
||
snprintf(&*cpuload, sizeof(0), "%d", 0);
|
||
return;
|
||
}
|
||
|
||
// we dont have a good value, use old value
|
||
if(totalUser < lastTotalUser || totalUserLow < lastTotalUserLow ||
|
||
totalSys < lastTotalSys || totalIdle < lastTotalIdle)
|
||
{
|
||
//percent = -1.0;
|
||
percent = lastPercent;
|
||
}
|
||
|
||
// we have a good value, save it and process it
|
||
else
|
||
{
|
||
total = (totalUser - lastTotalUser) + (totalUserLow - lastTotalUserLow) + (totalSys - lastTotalSys);
|
||
percent = total * 100;
|
||
total += (totalIdle - lastTotalIdle);
|
||
percent /= total;
|
||
lastPercent = percent;
|
||
}
|
||
|
||
lastTotalUser = totalUser;
|
||
lastTotalUserLow = totalUserLow;
|
||
lastTotalSys = totalSys;
|
||
lastTotalIdle = totalIdle;
|
||
intPercent = percent;
|
||
|
||
snprintf(&*cpuload, sizeof(intPercent), "%d", intPercent);
|
||
|
||
return;
|
||
}
|
||
|
||
static void get_cpu_temp()
|
||
{
|
||
FILE* ptr;
|
||
char str[10];
|
||
|
||
// opening file in readonly mode
|
||
ptr = fopen(&*cpu_temp_file, "r");
|
||
|
||
if(NULL == ptr) {
|
||
fprintf(log_stream,"File %s can't be opened!\n",cpu_temp_file);
|
||
return;
|
||
}
|
||
|
||
while(fgets(str, 10, ptr) != NULL) {
|
||
if(debug) {
|
||
fprintf(log_stream,"Raw CPU temp: %s\n", str);
|
||
}
|
||
}
|
||
|
||
/*
|
||
1 decimal place
|
||
char a = str[0];
|
||
char b = str[1];
|
||
char c = str[2];
|
||
snprintf(&*cputemp,6,"%c%c.%c",a,b,c);*/
|
||
|
||
// no decimals
|
||
char a = str[0];
|
||
char b = str[1];
|
||
snprintf(&*cputemp,6,"%c%c",a,b);
|
||
|
||
fclose(ptr);
|
||
|
||
return;
|
||
}
|
||
|
||
static void get_free_mem()
|
||
{
|
||
struct sysinfo info;
|
||
int myfreemem;
|
||
|
||
if(sysinfo(&info) < 0) {
|
||
return;
|
||
}
|
||
|
||
if(debug) {
|
||
fprintf(log_stream,"RAW free mem: %ld\n",info.freeram);
|
||
}
|
||
|
||
myfreemem = info.freeram / 1024 / 1024;
|
||
snprintf(&*freemem,sizeof(freemem),"%d",myfreemem);
|
||
|
||
return;
|
||
}
|
||
|
||
static void get_free_space()
|
||
{
|
||
struct statfs info;
|
||
int n = 0;
|
||
char *mydrive;
|
||
char myfree_string[line_length];
|
||
long unsigned int mytmpfree;
|
||
|
||
for(n = 0; n < drive_free_space_count; n++) {
|
||
mydrive = drive_free_space[n];
|
||
statfs(mydrive, &info);
|
||
mytmpfree = ((info.f_bavail*4) / 1024 / 1024) + 1;
|
||
snprintf(myfree_string,line_length,"%ldG ",mytmpfree);
|
||
strcat(freespace,myfree_string);
|
||
|
||
if(debug) {
|
||
fprintf(log_stream, "My Drive: %s\n"
|
||
" block size : %ld,"
|
||
" total data blocks : %ld,"
|
||
" free blocks for root: %ld,"
|
||
" free blocks for user: %ld,"
|
||
" free space in G: %ld\n\n",
|
||
mydrive, info.f_bsize, info.f_blocks, info.f_bfree, info.f_bavail, mytmpfree);
|
||
}
|
||
}
|
||
|
||
return;
|
||
}
|